pyo/0000755000175000017500000000000012652732474010671 5ustar tiagotiagopyo/ChangeLog0000644000175000017500000011057212652732202012436 0ustar tiagotiago2016-01-08 belangeo * Final revision for version 0.7.8. - SHA: e71cb0b5254da456bea129113da3d258a5b75dea 2016-01-07 belangeo * Added new object: Expr, sample-based prefix expression evaluator. 2015-12-04 belangeo * Added new object: Resample, allow multi-rate DSP chains. 2015-12-04 belangeo * Added Juce PyoPlugin framework in the embedded folder. 2015-10-26 belangeo * Fixed memory leak when using PyFloat_AS_DOUBLE(PyNumber_Float(x)) to fill table data. 2015-10-25 belangeo * Added a closeGui() method to the Server object. This allow to programatically close the Server window. 2015-10-24 belangeo * Added a method addMidiEvent to the Server object. This allow to programatically simulate MIDI events. Added the functionnaility to the embedded framework and modify the puredata pyo~ object help patch to illustrate how to generate MIDI events from the host program. 2015-10-18 belangeo * Fixed triangle waveform amplitude in LFO object. Fixed calculation of Follower/Follower2 lowpass cutoff frequencies. 2015-10-12 belangeo * Final revision for version 0.7.7. - SHA : 217b0cb40c8b82dad8c66718910fcd6e8f983034 2015-10-11 belangeo * Fixed clicks at the end of the Adsr envelope. 2015-09-25 belangeo * Added a trigger stream to Looper to signal the beginning of a new loop. 2015-09-15 belangeo * Automatically add the current working directory in sys.path when the background server is started. 2015-09-03 belangeo * Added a pause() method to Linseg and Expseg objects (keep the internal phase). 2015-09-03 belangeo * All OSC objects now accept string or unicode types as address parameter. 2015-09-03 belangeo * Fixed crash (OSX) when the server GUI is closed with the red button. 2015-09-02 belangeo * Fixed crash on server shutdown. 2015-08-25 belangeo * Added new objects: MidiListener and OscListener (self-contained MIDI and OSC servers). ------------------------------------------------------------------------------------- 2015-07-27 belangeo * Final revision for version 0.7.6. - rev 1335 2015-07-24 belangeo * Release tag: 0.7.6. - rev 1333 2015-07-24 belangeo * Added missing types to OscDataSend and OscDataReceive (char, blob, True, False, None and MIDI packet). - rev 1332 2015-07-21 belangeo * Fixed Centroid output with silence as input. - rev 1330 2015-07-21 belangeo * Added new objet: RawMidi, a raw Midi handler. - rev 1329 2015-07-21 belangeo * Added pyoArgsAssert call in each object's methods. - rev 1320, 1325, 1327, 1328 2015-07-20 belangeo * Fixed the "segmentation fault" that occur sometimes when deleting an object. - rev 1326 2015-05-31 belangeo * E-Pyo: Fixed project tree. - rev 1315 2015-05-29 belangeo * E-Pyo: stderr now prints to the output panel. - rev 1314 2015-05-25 belangeo * E-Pyo: Added code block selection (#--> and #<-- are delimiters). The background server now prints to the output panel. - rev 1313 2015-04-29 belangeo * Fixed CPU usage of PeakAmp. - rev 1312 ------------------------------------------------------------------------------------- 2015-03-05 belangeo * Fixed crash when portaudio stream is stopped on OSX (created when fixed for Windows). Rev 1310 is the sources for 0.7.5 release. - rev 1310 2015-03-05 belangeo * Release tag: 0.7.5. - rev 1308 2015-03-05 belangeo * Added documentation for server methods setTimeCallable and setMeterCallable. - rev 1304 2015-03-05 belangeo * Changed license to the more permissive LGPL version 3. - rev 1303 2015-03-03 belangeo * The Server can be booted with a different number of input and output channels. - rev 1301 2015-03-03 belangeo * Wraped input of Record in an InputFader object. - rev 1300 2015-03-03 belangeo * Fixed bug in Hilbert object. - rev 1299 2015-02-18 belangeo * Added mul, add and sub methods to PyoTableObject. These methods can take float, list or another PyoTableObject as argument. - rev 1298 2015-02-13 belangeo * Added new objet: AtanTable, generates arctangent transfert functions. - rev 1296 2015-02-11 belangeo * Fixed a bug when changing the looping mode of the Looper object. - rev 1295 2015-02-09 belangeo * Added a reset method to the Looper objet. - rev 1294 2015-02-08 belangeo * E-Pyo: Added a refresh button to actualize the content of the folder panel. - rev 1292 2015-02-07 belangeo * E-Pyo: Added a menu item to set a master document (the one that will be executed whatever which one has the focus). - rev 1291 2015-02-03 belangeo * Added getServer, getSamplingRate and getBufferSize to PyoObjectBase. These methods can be accessed from any pyo objects. - rev 1290 2015-02-03 belangeo * Fixed a bug with class method referenced inside pyo object. Save them as weak reference, allowing the garbage collector to properly delete the objects when reference count falls to 0. - rev 1289 2015-02-02 belangeo * Added new objet: TableWrite, records values in a table at arbitrary location. - rev 1288 ------------------------------------------------------------------------------------- 2015-01-29 belangeo * Release tag: 0.7.4 - rev 1284 2015-01-29 belangeo * Added new function: floatmap, 0-1 range mapper. Fixed bug in DataTable initialization and added an automatic refresh of the DataTable grapher window. - rev 1282 2015-01-26 belangeo * Added new objet: Particle, a full control granular synthesis generator. - rev 1281 2015-01-24 belangeo * Added setSync method to Granule object. Allow to toggle between synchronous and asynchronous granulation. Added noteon and noteoff trigger streams to Notein object. - rev 1280 2014-12-15 belangeo * Added reset method to CtlScan and CtlScan2 objects. - rev 1279 2014-12-03 belangeo * Added new objet: PeakAmp, a peak amplitude follower. - rev 1277 2014-11-27 belangeo * Added reset method to Beat and Euclide objects. - rev 1275 ------------------------------------------------------------------------------------- 2014-10-17 belangeo * Release tag: 0.7.3. - rev 1273 2014-11-15 belangeo * Added new objet: Scope, an audio waveform display. - rev 1270 2014-11-12 belangeo * E-Pyo: Fix marker's line numbering. - rev 1267 2014-11-08 belangeo * E-Pyo: Added Save As Template... menu item. - rev 1263 2014-11-02 belangeo * Fixed bug in Fader decreasing ramp. - rev 1262 2014-10-28 belangeo * Added midi output methods to the Server object. noteout, afterout, ctlout, programout, pressout and bendout. - rev 1261 2014-10-28 belangeo * Server.setMidiOutputDevice(idx) with `idx` greater than the higher portmidi devices index opens all available output devices. - rev 1260 2014-10-24 belangeo * Added new object: FToM, converts an audio stream containning frequencies in hertz to a midi note audio stream. - rev 1259 2014-10-23 belangeo * Added new function: hzToMidi, converts a frequency in hertz to a midi note value. - rev 1258 ------------------------------------------------------------------------------------- 2014-10-17 belangeo * Release tag: 0.7.2. - rev 1256 2014-10-16 belangeo * Server.setMidiInputDevice(idx) with `idx` greater than the higher portmidi input index opens all available devices. - rev 1254 2014-10-16 belangeo * OSX installer: Also install pyo in anaconda site-packages directory if exist. - rev 1253 2014-10-16 belangeo * Added new object : TrigBurst, generates a time/amplitude expandable trigger pattern. - rev 1252 2014-10-14 belangeo * Added new object : Euclide, Euclidean rhythm generator. - rev 1251 2014-10-13 belangeo * Windows installers now check for the current python installation directory before installing files. - rev 1244 - 1250 2014-10-10 belangeo * E-Pyo: Fixed inconsistencies in Find/Replace behaviours. - rev 1241 2014-10-10 belangeo * Added new object : SmoothDelay, a delay line that does not produce clicks or pitch shifting when the delay time is changing. - rev 1239 2014-10-08 belangeo * Added new object : AttackDetector, audio signal onset detection. - rev 1238 2014-10-07 belangeo * Added new object : Centroid, Computes the spectral centroid of an input signal. - rev 1237 ------------------------------------------------------------------------------------- 2014-08-29 belangeo * Release tag: 0.7.1. - rev 1236 2014-09-12 belangeo * E-Pyo: Added RadioPyo to the template choices. - rev 1234 2014-09-09 belangeo * Fixed Compare when used with None or a string. Print a warning and set 'comp' attribute to 0. - rev 1229 2014-09-05 belangeo * Fixed live interpreter of the server window when using arrow keys navigation. - rev 1228 2014-09-04 belangeo * E-Pyo: Check if WxPython 3.0 is installed, otherwise uses 2.8. - rev 1227 2014-09-02 belangeo * Added anti-aliasing to PyoTableObject's grapher widget. Fixed Ctrl+W on the grapher. - rev 1225, 1226 ------------------------------------------------------------------------------------- 2014-08-29 belangeo * Release tag: 0.7.0. - rev 1224 2014-08-26 belangeo * pyo can now be used without any GUI toolkit (WxPython or TKinter). Widgets are simply disabled. - rev 1208 2014-06-22 belangeo * Added Server methods to auto-connect Jack ports to already opened ports. - rev 1201 2014-05-23 belangeo * E-Pyo: output log now in realtime. - rev 1197 2014-04-24 belangeo * Added new object: Tanh, hyperbolic tangent function on audio signal. - rev 1188 ------------------------------------------------------------------------------------- 2014-04-11 belangeo * Release tag: 0.6.9. - rev 1185 2014-04-11 belangeo * Added lot of methods to PyoTableObject (retify, bipolarGain, invert, lowpass, fadein, fadeout, pow). - rev 1182 2014-04-04 belangeo * Added new object: PartialTable, generates waveforms made of inharmonic components. - rev 1177 2014-03-12 belangeo * Added a Scope example in examples/utilities. - rev 1168 2013-12-24 belangeo * Added new object: STRev, Stereo reverb. - rev 1154 2013-12-24 belangeo * Added dataOnly argument to SLMap. User can now control parameters, in ctrl window, that do not accept audio signal but discreet values. - rev 1153 2013-12-10 belangeo * Added new object: ComplexRes, Complex one-pole resonator filter. - rev 1148 2013-10-18 belangeo * Added new object: TrackHold, Performs a 'thru' and hold on its input signal. - rev 1143 ------------------------------------------------------------------------------------- 2013-10-16 belangeo * Release tag: 0.6.8. - rev 1142 2013-10-16 belangeo * Added multi server facility and and embeded callback support for plugin development (code by Guillaume Barrette). - rev 1141 2013-10-06 belangeo * Add a channel offset to the server physical inputs and outputs. - rev 1136 2013-10-03 belangeo * Added support for reading/writing various soundfile formats. FLAC and OGG need libsndfile to be compiled with both of them enabled. - rev 1133 2013-07-25 belangeo * Added new object: PVMix, Mix the most prominent components from two phase vocoder streaming objects. - rev 1130 2013-07-25 belangeo * Added new object: TableScale, Scales values from a table and writes them into another table. - rev 1129 2013-07-22 belangeo * Added new object: Granule, another granular synthesis generator. - rev 1127 2013-07-16 belangeo * Added new object: PVBufTabLoops, phase vocoder buffer with bin independent speed playback (controlled with a PyoTableObject). - rev 1126 2013-07-16 belangeo * Added new object: PVBufLoops, phase vocoder buffer with bin independent speed playback. - rev 1125 2013-07-10 belangeo * Added new objects: PVShift, spectral frequency shifter. PVAmpMod and PVFreqMod, frequency independent modulations. - rev 1124 2013-07-01 belangeo * Added new objects: PVDelay, spectral delays and PVBuffer, phase vocoder recorder and playback. - rev 1123 2013-06-20 belangeo * Added setJackAuto method to the Server to disable (enabled by default) Jack ports auto-connection. - rev 1122 2013-06-19 belangeo * Added graph() method to DataTable object. Opens a multisliders window to edit the table content. - rev 1120 2013-06-18 belangeo * Added new object: PVFilter. Spectral filtering. - rev 1119 2013-06-18 belangeo * Added new object: PVCross, PVMult, PVMorph. Spectral morphing. - rev 1117 2013-06-13 belangeo * Added new object: PVAddSynth, Phase Vocoder additive synthesis object. - rev 1116 2013-06-11 belangeo * Phase Vocoder, first draft. PVAnal, PVSynth, PVTranspose, PVVerb and PVGate. - rev 1114 2013-05-27 belangeo * E-Pyo: Added "Search in Project Files" option. - rev 1108 2013-05-24 belangeo * E-Pyo: Added Filters Menu. User-defined text processing functions. - rev 1107 2013-05-23 belangeo * Now using Sphinx to generate the API documentation. - rev 1105 2013-05-15 belangeo * Added new objects: ButLP, ButHP, ButBP, ButBR, second-order Butterworth filters. - rev 1104 2013-05-09 belangeo * Added new objects: Reson and Resonx, second-order resonant bandpass filters. - rev 1102 ------------------------------------------------------------------------------------- 2013-05-08 belangeo * Release tag: 0.6.6. - rev 1100 2013-05-08 belangeo * Fixed Notein bug when receiving note-off message with positive velocity. - rev 1096 2013-05-07 belangeo * Added new object: Spectrum, Frequency spectrum analyzer. - rev 1095 2013-04-19 belangeo * Added new object: CvlVerb, convolution based reverb. - rev 1094 ------------------------------------------------------------------------------------- 2013-04-13 belangeo * Release tag: 0.6.5. - rev 1091 2013-04-12 belangeo * Added new object: Average, Moving average filter. - rev 1090 2013-04-12 belangeo * Added new object: SVF, State Variable Filter with continuous filter type change. - rev 1089 2013-10-11 belangeo * Added a setStealing() method to the Notein object. - rev 1087 2013-10-10 belangeo * Added a reset() method to the PyoTableObject. - rev 1086 2013-03-08 belangeo * Added new object: Yin, pitch tracker using the Yin algorithm. - rev 1084 2013-03-01 belangeo * Graphical display of NewMatrix object now updates in real-time. - rev 1082 2013-02-28 belangeo * Graphical display of table objects now updates in real-time. - rev 1080 ------------------------------------------------------------------------------------- 2013-02-17 belangeo * Release tag: 0.6.4. - rev 1078 2013-02-13 belangeo * Added pyo.USE_DOUBLE constant. 'import pyo' sets this constant to 0 and 'import pyo64' sets it to 1 - rev 1073 2013-01-21 belangeo * Added __del__ method to the Server object with checks and necessary actions if the server is already started and/or booted. - rev 1065 2013-01-11 belangeo * Added new object: RCOsc. Waveform aproximation of a RC circuit. - rev 1063 2013-01-07 belangeo * Added new operators on To PyoObject. **, %, - (negative) and comparison operators. - rev 1062 2012-12-25 belangeo * Added new object: Delay1. Delays a signal by one sample. - rev 1058 2012-12-19 belangeo * Added new objects: Min and Max. Outputs minimum or maximum between two values. - rev 1049 2012-12-19 belangeo * Added a template for extending pyo with custom objects. - rev 1047 2012-12-18 belangeo * Added "sendMidiNote(pitch, velocity, channel, timestamp) method to the Server object". - rev 1046 2012-11-17 belangeo * Added new object: Atone: First-order recursive high-pass filter with variable frequency response. - rev 1031 2012-11-15 belangeo * Added new object: SuperSaw: Roland JP-8000 Supersaw emulator. - rev 1029 2012-11-14 belangeo * Added new object: TablePut: Writes values, without repetitions, from an audio stream into a DataTable. - rev 1027 ------------------------------------------------------------------------------------- 2012-10-26 belangeo * rev 1025: Release tag: 0.6.3. 2012-10-13 belangeo * Added new function: pa_get_devices_infos: Returns info about all devices found by Portaudio. - rev 1024 2012-10-12 belangeo * Added new object: SumOsc: Discrete summation formulae to produce complex spectra. - rev 1023 2012-10-11 belangeo * Added new method to OscReceive and OscListReceive: setValue(path, value) let the user to initialize the value for a given path. - rev 1022 2012-10-05 belangeo * Added new functions: pa_get_input_max_channels and pa_get_output_max_channels. - rev 1020 2012-08-17 belangeo * Added new object: OscTrig: An oscillator reading a waveform table with sample accurate reset signal. - rev 1017 2012-08-17 belangeo * Added new object: TrigVal: Outputs a previously defined value on a trigger signal. - rev 1016 2012-08-01 belangeo * Added new object: CosLogTable: Construct a table from logarithmic-cosine segments in breakpoint fashion. - rev 1014 2012-08-01 belangeo * Added new object: LogTable: Construct a table from logarithmic segments in breakpoint fashion. - rev 1013 2012-07-31 belangeo * Added new object: Balance: Adjust rms power of an audio signal according to the rms power of another. - rev 1012 ------------------------------------------------------------------------------------- 2012-06-30 belangeo * Added new object: CtlScan2. Scan for Midi controller number and Midi channel in input. - rev 1007 2012-06-26 belangeo * Added "offline_nb" mode to the Server, allowing non-blocking bounce to disk. - rev 1004 2012-06-13 belangeo * Fixed issue 34 : Better handling of type exceptions for arguments waiting for PyoObject, PyoTableObject or list. - rev 1000 2012-06-08 belangeo * Added ChebyTable.getNormTable() method to retrieve the normalization function for the current polynomial. - rev 996 2012-05-31 belangeo * E-Pyo now creates its resources folder in the user home directory. - rev 991 2012-05-30 belangeo * Fixed PyoObject.set() method bug. - rev 987 2012-05-26 belangeo * Added new function: savefileFromTable(). Used internally by PyoTableObject to save sound to disk. - rev 983 2012-05-25 belangeo * Added two methods to PyoObject class: isPlaying() and isOutputting(). - rev 979 2012-05-25 belangeo * Added debugging methods utilities: Server.getStreams(), Server.getNumberOfStreams() and Stream.getStreamObject(). - rev 977 2012-05-24 belangeo * Fixed memory leak on object's deletion (refcount was always one more than expected). - rev 974 2012-05-10 belangeo * Removed printing to the console from pa_get_* and pm_get_* functions. - rev 973 2012-05-10 belangeo * Added new object: Vocoder. Vocoder effect. - rev 972 2012-05-09 belangeo * Ensures that every example in the examples folder that don't need audio input have the duplex mode set to 0. - rev 971 2012-05-09 belangeo * Added new object: MatrixRecLoop. Records samples in loop into a previously created NewMatrix. - rev 970 2012-05-08 belangeo * Fixed issue 30. Lin/Exp/Cos/CurveTable compare size with last position in the list and increase size if needed. - rev 969 2012-05-08 belangeo * Added compiler flag --no-messages to suppress startup messages. - rev 968 ------------------------------------------------------------------------------------- 2012-05-02 belangeo * rev 966 - Upgraded version number to 0.6.2, release tag: 0.6.1. 2012-04-28 belangeo * Added new function : convertStringToSysEncoding. For users who use non-ascii characters in their path. - rev 945 2012-04-13 belangeo * Added new object : NextTrig. A trigger opens a gate only for the next one. - rev 925 2012-04-13 belangeo * Added PyoObject.range(min, max) method. Adjust mul and add attributes. - rev 923 2012-04-13 belangeo * Added new object : Urn. Periodic pseudo-random integer generator without duplicates. - rev 922 2012-04-09 belangeo * Added new object : Count. Counts integers at audio rate. - rev 919 2012-04-06 belangeo * Added new object : OscListReceive. Handles list of floats from OSC as audio streams. - rev 914 2012-04-03 belangeo * Added functionalities to OSC objects (add, remove, setInterpolation, etc.). - rev 913 ------------------------------------------------------------------------------------- 2012-01-03 belangeo * rev 807 - Updated version number, release tag: 0.6.0. 2011-12-22 belangeo * Added new object: MToT. Midi to transposition factor conversion. - rev 805 2011-12-20 belangeo * Added new objects: XnoiseDur, Recursive time varying X-class pseudo-random generator. SincTable, sinc window function. - rev 803 2011-12-19 belangeo * Added new object: VoiceManager. Polyphony voice manager. - rev 802 2011-12-14 belangeo * Added downsamp() function. Sampling rate conversion of a soundfile. - rev 798 2011-12-13 belangeo * Added upsamp() function. Sampling rate conversion of a soundfile. - rev 797 2011-12-13 belangeo * Added copy() method to the PyoTableObject. - rev 796 2011-12-12 belangeo * Added reverse() method to the PyoTableObject. - rev 795 2011-12-11 belangeo * Added removeDC() method to the PyoTableObject. - rev 794 2011-12-07 belangeo * Added new object: Biquada. Biquadratric filter controlled with filter's coefficients. - rev 793 2011-12-05 belangeo * Added new function: distanceToSegment. Find the distance from a point to a line or line segment. - rev 790 2011-11-29 belangeo * Added new object: Iter. Triggers iterate over a list of user-defined values. - rev 784 2011-11-26 belangeo * Added new object: Vectral. Performs magnitude smoothing between successive frames. - rev 782 2011-11-23 belangeo * Added server's attribute : globalseed. An int used as the seed by random objects. Can be changed multiple times inside a script. - rev 778 2011-11-22 belangeo * Added new object: RandDur. Recursive time varying pseudo-random generator. - rev 776 2011-11-22 belangeo * Added new object: Timer. Reports elpased time between two triggers. - rev 772 2011-11-15 belangeo * Added mouse callback to SndTable.view method to allow simple scrubbing. - rev 763 2011-11-09 belangeo * midiToHz and midiToTranspo now accept list or tuple in input. - rev 759 2011-11-04 belangeo * Snap takes choice on more than one octave. - rev 754 2011-10-27 belangeo * Added new object: MToF. Midi to frequency conversion. - rev 748 2011-10-26 belangeo * Added new objects: CentsToTranspo and TranspoToCents. Cents/transposition factor conversions. - rev 747 2011-10-26 belangeo * Added new object: Scale. Maps an input range of audio values to an output range. - rev 746 2011-10-25 belangeo * Added new objects: DBToA and AToDB. Amplitude/decibel conversions. - rev 745 2011-10-22 belangeo * Added "append" and "insert" methods to SndTable object. - rev 740 2011-10-13 belangeo * Added new objects : Touchin : Get the current value of the after-touch controller. Programin : Get the current value of a program change controller. - rev 730 2011-10-13 belangeo * Added new object : Bendin : Get the current value of the pitch bend controller. - rev 729 2011-10-12 belangeo * Added midi channel attributes to Midictl and Notein. Added setCentralKey(x) method to Notein. - rev 726 2011-10-05 belangeo * Added new object : Ceil : Returns the smallest integral value greater than or equal to the input signal. - rev 720 2011-10-02 belangeo * Added new object : MidiDelAdsr : Midi triggered ADSR envelope with pre-delay. - rev 719 2011-09-25 belangeo * Updated version number to 0.5.1. - rev 713 2011-08-13 belangeo * Added new object : CtlScan : Scan for Midi controller number in input. - rev 707 ------------------------------------------------------------------------------------- 2011-07-31 belangeo * rev 702 - pyo 0.5.0 release. 2011-07-31 belangeo * Added new objects : NoteinRec and NoteinRead. Records and reads Notein automations. - rev 701 2011-08-30 belangeo * Added new object : WinTable. Generates different kind of windowing functions. - rev 700 2011-07-22 belangeo * Added new function : reducePoints(), apply a Douglas–Peucker curve reduction algorithm. Added loadRecFile() method to table objects. - rev 688 2011-07-20 belangeo * Added new objects : ControlRec and ControlRead. Records automations at user-defined sampling rate. - rev 687 2011-07-18 belangeo * Added C impementation of the Looper object. - rev 682 2011-07-07 belangeo * Added new arithmetic object: Round. - rev 675 2011-07-06 belangeo * Added new arithmetic object: Floor. - rev 674 2011-07-03 belangeo * Added new objects: OscDataSend and OscDataReceive. - rev 668 2011-06-15 belangeo * Added 'feedback' attribute to NewTable object. - rev 659 2011-06-14 belangeo * New object : TrigTableRec. - rev 658 2011-06-02 belangeo * Added cartesian to polar and polar to cartesian conversions. - rev 655 2011-06-01 belangeo * Protected (self->steps == 0) in line generation to avoid division by zero. - rev 654 2011-05-31 belangeo * Added Fast Fourier Transform (FFT, IFFT). - rev 652 ------------------------------------------------------------------------------------- 2011-05-18 belangeo * Added getVersion() function and upgrade version number to '0.4.1'. - rev 645 2011-05-18 belangeo * Improved soundfile player family (SfPlayer, SfMarkerShuffler and SfMarkerLooper). - rev 644 2011-05-13 belangeo * New object : FourBand (linear phase spectrum splitter). - rev 640 2011-05-11 belangeo * New object : ParaTable (parabola window function). - rev 637 2011-05-11 belangeo * Added 'outputAmp' argument to Compress and Gate. Useful to link several channels. - rev 636 2011-05-10 belangeo * New object: Gate (noise gate). - rev 635 2011-05-10 belangeo * New object: Follower2 (different attack and release times). - rev 634 2011-05-10 belangeo * Completely redesigned Follower. - rev 633 2011-05-10 belangeo * Completely redesigned Compress. - rev 632 2011-05-05 belangeo * SigTo can be used with PyoObject as input value. - rev 631 2011-05-03 belangeo * Port filter optimization. - rev 630 2011-05-03 belangeo * Fixed glitches in objects using recursive delay lines. - rev 629 2011-05-02 belangeo * Fixed bug in Expseg and TrigExpseg "exp" argument initilization. - rev 624 ------------------------------------------------------------------------------------- 2011-02-29 belangeo * rev 622 - pyo 0.4.0 release. 2011-04-26 belangeo * Added new object : OscBank. Mixes any number of oscillators. - rev 606 2011-04-22 belangeo * Added new object : FreqShift, frequency shifter using single sideband amplitude modulation. - rev 605 2011-04-15 belangeo * Added new object : Denorm. - rev 601 2011-04-15 belangeo * Added portaudio non-interleaved callback for ASIO support. - rev 577 2011-04-15 belangeo * Fixed crash when duplex=0 on Windows - rev 574 2011-04-10 belangeo * New object : MidiAdsr, a Midi triggered ADSR envelope generator. - rev 572 2011-04-01 belangeo * New objects : LFO, Band-limited Low Frequency Oscillator with different wave shapes. - rev 571 2011-03-27 belangeo * New chaotic attractor objects : Lorenz and Rossler - rev 567 2011-03-14 belangeo * Convolution-based filter family : IRWinSinc, IRPulse, IRAverage, IRFM - rev 565 2011-03-02 belangeo * Added new object : BrownNoise - rev 564 2011-03-02 belangeo * Added new object : Wrap (Wraps-around the signal that exceeds the `min` and `max` thresholds.) - rev 562 2011-03-01 belangeo * Added new object : Mirror (Reflects the signal that exceeds the `min` and `max` thresholds.) - rev 561 2011-03-01 belangeo * Added new object : Between (Output a trig if input is between `min` and `max`) - rev 558 2011-02-27 belangeo * Added new object : CrossFM - rev 552 2011-02-26 belangeo * Added new object : PinkNoise - rev 551 2011-02-26 belangeo * Added new object : Blit (Band Limited Impulse Train) - rev 550 2011-02-23 belangeo * Added new object : AllpassWG - rev 548 2011-02-21 belangeo * All trig signals can be treated as number, allowing arithmetic operations. - rev 547 ------------------------------------------------------------------------------------- 2010-02-20 belangeo * rev 544 - pyo 0.03 release. 2010-12-30 belangeo * Added new object : Mixer - rev 537 2010-12-13 belangeo * Added graph() method to some PyoTableObjects, allowing the control of the envelope's shape with a grapher window. - rev 532 ------------------------------------------------------------------------------------- 2010-11-02 belangeo * rev 515 - pyo 0.02 release. 2010-10-24 belangeo * Fixed timming issue. - rev 507 2010-10-09 belangeo * Added `starttime` attribute to the server, allowing faster rendering of a first part of a piece. - rev 473 2010-10-08 belangeo * Added a clock of the current time in the server window and allow server's customization with parameters in the .gui() method. - rev 468 2010-10-07 belangeo * Added new object : MatrixMorph - rev 463 2010-10-04 mantaraya36 belangeo * Added offline rendering. - rev 452 2010-09-30 belangeo * Added support for wxPython toolkit. If wx is installed, pyo will use it instead of Tk. - rev 442 2010-09-23 belangeo * Added new objet : Percent - rev 434 2010-09-21 belangeo * Added support for Coreaudio backend. Build with --use-coreaudio option. - rev 431 2010-09-17 mantaraya36 * Added support for Jack audio backend. Build with --use-jack option. - rev 423 2010-09-16 belangeo * Added --use-double option to compile pyo in double version. It creates a new library, called _pyo64.so, in the same directory as _pyo.so. To use it, simply import pyo64 (from pyo64 import *). - rev 417. 2010-09-13 belangeo * Added "dur" and "delay" arguments to play and out methods of PyoObject. - rev 413. ------------------------------------------------------------------------------------- 2010-09-06 belangeo * rev 390 - pyo 0.01 release. pyo/doc-sphinx/0000755000175000017500000000000012652732202012732 5ustar tiagotiagopyo/doc-sphinx/build.py0000644000175000017500000000400512652732202014402 0ustar tiagotiagoimport os, sys from types import ListType from pyo import * build_format = "html" build_folder = "./build_html" if "--latex" in sys.argv: build_format = "latex" build_folder = "./build_latex" f = open(os.getcwd() + '/source/api/alphabetical.rst', 'w') # Header f.write("Alphabetical class reference\n") f.write("=======================================\n") f.write("\n\n.. module:: pyo\n\n") def getDocFirstLine(obj): try: text = eval(obj).__doc__ if text == None: text = '' except: text = '' if text != '': spl = text.split('\n') if len(spl) == 1: f = spl[0] else: f = spl[1] else: f = text return f format = "- :py:class:`%s` : %s\n" lines = [] for key in ['Server', 'Stream', 'TableStream', 'PyoObjectBase', 'Map']: if type(OBJECTS_TREE[key]) == ListType: for obj in OBJECTS_TREE[key]: lines.append(format % (obj, getDocFirstLine(obj))) else: if key == 'Map': key2list = ['SLMap'] else: key2list = ['PyoMatrixObject', 'PyoTableObject', 'PyoObject', 'PyoPVObject'] for key2 in key2list: if type(OBJECTS_TREE[key][key2]) == ListType: for obj in OBJECTS_TREE[key][key2]: lines.append(format % (obj, getDocFirstLine(obj))) else: for key3 in sorted(OBJECTS_TREE[key][key2]): for obj in OBJECTS_TREE[key][key2][key3]: lines.append(format % (obj, getDocFirstLine(obj))) lines.sort() for line in lines: f.write(line) f.close() os.system("sphinx-build -a -b %s ./source %s" % (build_format, build_folder)) if build_format == "latex": os.system("cd build_latex; pdflatex -interaction nonstopmode Pyo; pdflatex -interaction nonstopmode Pyo") rep = raw_input("Do you want to upload to ajax server (y/n) ? ") if rep == "y": os.system("scp -r build_html/* jeadum1@ajaxsoundstudio.com:/home/jeadum1/ajaxsoundstudio.com/pyodoc") pyo/doc-sphinx/source/0000755000175000017500000000000012652732202014232 5ustar tiagotiagopyo/doc-sphinx/source/tutorials/0000755000175000017500000000000012652732202016260 5ustar tiagotiagopyo/doc-sphinx/source/tutorials/pyotableobject1.rst0000644000175000017500000000434512652732202022107 0ustar tiagotiagoExample of a custom PyoTableObject ==================================== .. code-block:: python from pyo import * class TriTable(PyoTableObject): """ Square waveform generator. Generates square waveforms made up of fixed number of harmonics. :Parent: :py:class:`PyoTableObject` :Args: order : int, optional Number of harmonics square waveform is made of. The waveform will contains `order` odd harmonics. Defaults to 10. size : int, optional Table size in samples. Defaults to 8192. >>> s = Server().boot() >>> s.start() >>> t = TriTable(order=15).normalize() >>> a = Osc(table=t, freq=[199,200], mul=.2).out() """ def __init__(self, order=10, size=8192): PyoTableObject.__init__(self, size) self._order = order self._tri_table = HarmTable(self._create_list(order), size) self._base_objs = self._tri_table.getBaseObjects() def _create_list(self, order): # internal method used to compute the harmonics's weight l = [] ph = 1.0 for i in range(1,order*2): if i % 2 == 0: l.append(0) else: l.append(ph / (i*i)) ph *= -1 return l def setOrder(self, x): """ Change the `order` attribute and redraw the waveform. :Args: x : int New number of harmonics """ self._order = x self._tri_table.replace(self._create_list(x)) self.normalize() self.refreshView() @property def order(self): """int. Number of harmonics triangular waveform is made of.""" return self._order @order.setter def order(self, x): self.setOrder(x) # Run the script to test the TriTable object. if __name__ == "__main__": s = Server().boot() t = TriTable(10, 8192) t.normalize() t.view() a = Osc(t, 500, mul=.3).out() s.gui(locals()) pyo/doc-sphinx/source/tutorials/pyoobject1.rst0000644000175000017500000002664412652732202021105 0ustar tiagotiagoTutorial on creating a custom PyoObject (RingMod) ================================================== There are few steps we need to take care of in order to create a class with all of the PyoObject behaviors. Things to consider: - The parent class must be PyoObject, that means the PyoObject's __init__ method must be called inside the object's __init__ method to properly initialize PyoObject's basic attributes. - When a PyoObject receives another PyoObject, it looks for a list of objects called "self._base_objs". This list must contain the C implementation of the audio objects generating the output sound of the process. - Adding "mul" and "add" arguments (they act on objects in self._base_objs). - All PyoObjects support "list expansion". - All PyoObjects with sound in input support cross-fading between old and new sources. - We will probably want to override the play(), out() and stop() methods. - There is an attribute for any function that modify a parameter. - We should override the ctrl() method to allow a GUI to control parameters. In this tutorial, we will define a RingMod object with this definition: .. code-block:: python RingMod(input, freq=100, mul=1, add=0) First of all, we need to import the pyo module .. code-block:: python from pyo import * Step 1 - Declaring the class ------------------------------ We will create a new class called RingMod with PyoObject as its parent class. Another good habit is to put a __doc__ string at the beginning of our classes. Doing so will allow other users to retrieve the object's documentation with the standard python help() function. .. code-block:: python class RingMod(PyoObject): """ Ring modulator. Ring modulation is a signal-processing effect in electronics performed by multiplying two signals, where one is typically a sine-wave or another simple waveform. :Parent: :py:class:`PyoObject` :Args: input : PyoObject Input signal to process. freq : float or PyoObject, optional Frequency, in cycles per second, of the modulator. Defaults to 100. >>> s = Server().boot() >>> s.start() >>> src = SfPlayer(SNDS_PATH+"/transparent.aif", loop=True, mul=.3) >>> lfo = Sine(.25, phase=[0,.5], mul=.5, add=.5) >>> ring = RingMod(src, freq=[800,1000], mul=lfo).out() """ Step 2 - The __init__ method ------------------------------- This is the place where we have to take care of some of pyo's generic behaviours. The most important thing to remember is that when a PyoObject receives another PyoObject in input, it looks for an attribute called self._base_objs. This attribute is a list of the object's base classes and is considered the audio output signal of the object (the Sine object uses internally an object called Sine_base). The getBaseObjects() method returns the list of base classes for a given PyoObject. We will call the getBaseObjects() method on the objects generating the output signal of our process. .play(), .out(), .stop() and .mix() methods act on this list. We also need to add two arguments to the definition of the object: "mul" and "add". The attributes "self._mul" and "self._add" are handled by the parent class and are automatically applied to the objects stored in the list "self._base_objs". Finally, we have to consider the "multi-channel expansion" feature, allowing lists given as arguments to create multiple instances of our object and managing multiple audio streams. Two functions help us to accomplish this: convertArgsToLists(*args) : Return arguments converted to lists and the maximum list size. wrap(list,i) : Return value at position "i" in "list" with wrap around len(list). .. code-block:: python def __init__(self, input, freq=100, mul=1, add=0): # Properly initialize PyoObject's basic attributes PyoObject.__init__(self, mul, add) # Keep references of all raw arguments self._input = input self._freq = freq # Using InputFader to manage input sound allows cross-fade when changing sources self._in_fader = InputFader(input) # Convert all arguments to lists for "multi-channel expansion" in_fader,freq,mul,add,lmax = convertArgsToLists(self._in_fader,freq,mul,add) # Apply processing self._mod = Sine(freq=freq, mul=in_fader) # Use Sig object as a through to prevent modifying "mul" attribute of self._mod self._ring = Sig(self._mod, mul=mul, add=add) # self._base_objs is the audio output seen by the outside world! self._base_objs = self._ring.getBaseObjects() Step 3 - setXXX methods and attributes ------------------------------------------ Now, we will add methods and attributes getter and setter for all controllable parameters. It should be noted that we use the setInput() method of the InputFader object to change an input source. This object implements a cross-fade between the old source and the new one with a cross-fade duration argument. Here, we need to keep references of raw argument in order to get the real current state when we call the dump() method. .. code-block:: python def setInput(self, x, fadetime=0.05): """ Replace the `input` attribute. :Args: x : PyoObject New signal to process. fadetime : float, optional Crossfade time between old and new input. Defaults to 0.05. """ self._input = x self._in_fader.setInput(x, fadetime) def setFreq(self, x): """ Replace the `freq` attribute. :Args: x : float or PyoObject New `freq` attribute. """ self._freq = x self._mod.freq = x @property # getter def input(self): """PyoObject. Input signal to process.""" return self._input @input.setter # setter def input(self, x): self.setInput(x) @property def freq(self): """float or PyoObject. Frequency of the modulator.""" return self._freq @freq.setter def freq(self, x): self.setFreq(x) Step 4 - The ctrl() method ----------------------------- The ctrl() method of a PyoObject is used to pop-up a GUI to control the parameters of the object. The initialization of sliders is done with a list of SLMap objects where we can set the range of the slider, the type of scaling, the name of the attribute linked to the slider and the initial value. We will define a default "self._map_list" that will be used if the user doesn't provide one to the parameter "map_list". If the object doesn't have any parameter to control with a GUI, this .. code-block:: python def ctrl(self, map_list=None, title=None, wxnoserver=False): self._map_list = [SLMap(10, 2000, "log", "freq", self._freq), SLMapMul(self._mul)] PyoObject.ctrl(self, map_list, title, wxnoserver) Step 5 - Overriding the .play(), .stop() and .out() methods ------------------------------------------------------------- Finally, we might want to override .play(), .stop() and .out() methods to be sure all our internal PyoObjects are consequently managed instead of only objects in self._base_obj, as it is in built-in objects. To handle properly the process for self._base_objs, we still need to call the method that belongs to PyoObject. We return the returned value (self) of these methods in order to possibly append the method to the object's creation. See the definition of these methods in the PyoObject man page to understand the meaning of arguments. .. code-block:: python def play(self, dur=0, delay=0): self._mod.play(dur, delay) return PyoObject.play(self, dur, delay) def stop(self): self._mod.stop() return PyoObject.stop(self) def out(self, chnl=0, inc=1, dur=0, delay=0): self._mod.play(dur, delay) return PyoObject.out(self, chnl, inc, dur, delay) Here we are, we've just created our first custom pyo object! Complete class definition and test ---------------------------------------- .. code-block:: python from pyo import * class RingMod(PyoObject): """ Ring modulator. Ring modulation is a signal-processing effect in electronics performed by multiplying two signals, where one is typically a sine-wave or another simple waveform. :Parent: :py:class:`PyoObject` :Args: input : PyoObject Input signal to process. freq : float or PyoObject, optional Frequency, in cycles per second, of the modulator. Defaults to 100. >>> s = Server().boot() >>> s.start() >>> src = SfPlayer(SNDS_PATH+"/transparent.aif", loop=True, mul=.3) >>> lfo = Sine(.25, phase=[0,.5], mul=.5, add=.5) >>> ring = RingMod(src, freq=[800,1000], mul=lfo).out() """ def __init__(self, input, freq=100, mul=1, add=0): PyoObject.__init__(self, mul, add) self._input = input self._freq = freq self._in_fader = InputFader(input) in_fader,freq,mul,add,lmax = convertArgsToLists(self._in_fader,freq,mul,add) self._mod = Sine(freq=freq, mul=in_fader) self._ring = Sig(self._mod, mul=mul, add=add) self._base_objs = self._ring.getBaseObjects() def setInput(self, x, fadetime=0.05): """ Replace the `input` attribute. :Args: x : PyoObject New signal to process. fadetime : float, optional Crossfade time between old and new input. Defaults to 0.05. """ self._input = x self._in_fader.setInput(x, fadetime) def setFreq(self, x): """ Replace the `freq` attribute. :Args: x : float or PyoObject New `freq` attribute. """ self._freq = x self._mod.freq = x def play(self, dur=0, delay=0): self._mod.play(dur, delay) return PyoObject.play(self, dur, delay) def stop(self): self._mod.stop() return PyoObject.stop(self) def out(self, chnl=0, inc=1, dur=0, delay=0): self._mod.play(dur, delay) return PyoObject.out(self, chnl, inc, dur, delay) def ctrl(self, map_list=None, title=None, wxnoserver=False): self._map_list = [SLMap(10, 2000, "log", "freq", self._freq), SLMapMul(self._mul)] PyoObject.ctrl(self, map_list, title, wxnoserver) @property # getter def input(self): """PyoObject. Input signal to process.""" return self._input @input.setter # setter def input(self, x): self.setInput(x) @property def freq(self): """float or PyoObject. Frequency of the modulator.""" return self._freq @freq.setter def freq(self, x): self.setFreq(x) # Run the script to test the RingMod object. if __name__ == "__main__": s = Server().boot() src = SfPlayer(SNDS_PATH+"/transparent.aif", loop=True, mul=.3) lfo = Sine(.25, phase=[0,.5], mul=.5, add=.5) ring = RingMod(src, freq=[800,1000], mul=lfo).out() s.gui(locals()) pyo/doc-sphinx/source/tutorials/pyoobject2.rst0000644000175000017500000003752512652732202021106 0ustar tiagotiagoTutorial on creating a custom PyoObject (Flanger) ================================================== There are few steps we need to take care of in order to create a class with all of the PyoObject behaviors. Things to consider: - The parent class must be PyoObject, that means the PyoObject's __init__ method must be called inside the object's __init__ method to properly initialize PyoObject's basic attributes. - When a PyoObject receives another PyoObject, it looks for a list of objects called "self._base_objs". This list must contain the C implementation of the audio objects generating the output sound of the process. - Adding "mul" and "add" arguments (they act on objects in self._base_objs). - All PyoObjects support "list expansion". - All PyoObjects with sound in input support cross-fading between old and new sources. - We will probably want to override the play(), out() and stop() methods. - There is an attribute for any function that modify a parameter. - We should override the ctrl() method to allow a GUI to control parameters. In this tutorial, we will define a Flanger object with this definition: .. code-block:: python Flanger(input, depth=0.75, lfofreq=0.2, feedback=0.25, mul=1, add=0) First of all, we need to import the pyo module .. code-block:: python from pyo import * Step 1 - Declaring the class ------------------------------ We will create a new class called Flanger with PyoObject as its parent class. Another good habit is to put a __doc__ string at the beginning of our classes. Doing so will allow other users to retrieve the object's documentation with the standard python help() function. .. code-block:: python class Flanger(PyoObject): """ Flanging effect. A flanging is an audio effect produced by mixing two identical signals together, with one signal delayed by a small and gradually changing period, usually smaller than 20 milliseconds. This produces a swept comb filter effect: peaks and notches are produced in the resultant frequency spectrum, related to each other in a linear harmonic series. Varying the time delay causes these to sweep up and down the frequency spectrum. :Parent: :py:class:`PyoObject` :Args: input : PyoObject Input signal to process. depth : float or PyoObject, optional Amplitude of the delay line modulation, between 0 and 1. Defaults to 0.75. lfofreq : float or PyoObject, optional Frequency of the delay line modulation, in Hertz. Defaults to 0.2. feedback : float or PyoObject, optional Amount of output signal reinjected into the delay line. Defaults to 0.25. >>> s = Server().boot() >>> s.start() >>> inp = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True) >>> lf = Sine(0.005, mul=0.25, add=0.5) >>> flg = Flanger(input=inp, depth=0.9, lfofreq=0.1, feedback=lf).out() """ Step 2 - The __init__ method ------------------------------- This is the place where we have to take care of some of pyo's generic behaviours. The most important thing to remember is that when a PyoObject receives another PyoObject in input, it looks for an attribute called self._base_objs. This attribute is a list of the object's base classes and is considered the audio output signal of the object (the Sine object uses internally an object called Sine_base). The getBaseObjects() method returns the list of base classes for a given PyoObject. We will call the getBaseObjects() method on the objects generating the output signal of our process. .play(), .out(), .stop() and .mix() methods act on this list. We also need to add two arguments to the definition of the object: "mul" and "add". The attributes "self._mul" and "self._add" are handled by the parent class and are automatically applied to the objects stored in the list "self._base_objs". Finally, we have to consider the "multi-channel expansion" feature, allowing lists given as arguments to create multiple instances of our object and managing multiple audio streams. Two functions help us to accomplish this: convertArgsToLists(*args) : Return arguments converted to lists and the maximum list size. wrap(list,i) : Return value at position "i" in "list" with wrap around len(list). .. code-block:: python def __init__(self, input, depth=0.75, lfofreq=0.2, feedback=0.5, mul=1, add=0): # Properly initialize PyoObject's basic attributes PyoObject.__init__(self) # Keep references of all raw arguments self._input = input self._depth = depth self._lfofreq = lfofreq self._feedback = feedback # Using InputFader to manage input sound allows cross-fade when changing sources self._in_fader = InputFader(input) # Convert all arguments to lists for "multi-channel expansion" in_fader, depth, lfofreq, feedback, mul, add, lmax = convertArgsToLists( self._in_fader, depth, lfofreq, feedback, mul, add) # Apply processing self._modamp = Sig(depth, mul=0.005) self._mod = Sine(freq=lfofreq, mul=self._modamp, add=0.005) self._dls = Delay(in_fader, delay=self._mod, feedback=feedback) self._flange = Interp(in_fader, self._dls, mul=mul, add=add) # self._base_objs is the audio output seen by the outside world! self._base_objs = self._flange.getBaseObjects() Step 3 - setXXX methods and attributes ------------------------------------------ Now, we will add methods and attributes getter and setter for all controllable parameters. It should be noted that we use the setInput() method of the InputFader object to change an input source. This object implements a cross-fade between the old source and the new one with a cross-fade duration argument. Here, we need to keep references of raw argument in order to get the real current state when we call the dump() method. .. code-block:: python def setInput(self, x, fadetime=0.05): """ Replace the `input` attribute. :Args: x : PyoObject New signal to process. fadetime : float, optional Crossfade time between old and new input. Defaults to 0.05. """ self._input = x self._in_fader.setInput(x, fadetime) def setDepth(self, x): """ Replace the `depth` attribute. :Args: x : float or PyoObject New `depth` attribute. """ self._depth = x self._modamp.value = x def setLfoFreq(self, x): """ Replace the `lfofreq` attribute. :Args: x : float or PyoObject New `lfofreq` attribute. """ self._lfofreq = x self._mod.freq = x def setFeedback(self, x): """ Replace the `feedback` attribute. :Args: x : float or PyoObject New `feedback` attribute. """ self._feedback = x self._dls.feedback = x @property def input(self): """PyoObject. Input signal to process.""" return self._input @input.setter def input(self, x): self.setInput(x) @property def depth(self): """float or PyoObject. Amplitude of the delay line modulation.""" return self._depth @depth.setter def depth(self, x): self.setDepth(x) @property def lfofreq(self): """float or PyoObject. Frequency of the delay line modulation.""" return self._lfofreq @lfofreq.setter def lfofreq(self, x): self.setLfoFreq(x) @property def feedback(self): """float or PyoObject. Amount of out sig sent back in delay line.""" return self._feedback @feedback.setter def feedback(self, x): self.setFeedback(x) Step 4 - The ctrl() method ----------------------------- The ctrl() method of a PyoObject is used to pop-up a GUI to control the parameters of the object. The initialization of sliders is done with a list of SLMap objects where we can set the range of the slider, the type of scaling, the name of the attribute linked to the slider and the initial value. We will define a default "self._map_list" that will be used if the user doesn't provide one to the parameter "map_list". If the object doesn't have any parameter to control with a GUI, this .. code-block:: python def ctrl(self, map_list=None, title=None, wxnoserver=False): self._map_list = [SLMap(0., 1., "lin", "depth", self._depth), SLMap(0.001, 20., "log", "lfofreq", self._lfofreq), SLMap(0., 1., "lin", "feedback", self._feedback), SLMapMul(self._mul)] PyoObject.ctrl(self, map_list, title, wxnoserver) Step 5 - Overriding the .play(), .stop() and .out() methods ------------------------------------------------------------- Finally, we might want to override .play(), .stop() and .out() methods to be sure all our internal PyoObjects are consequently managed instead of only objects in self._base_obj, as it is in built-in objects. To handle properly the process for self._base_objs, we still need to call the method that belongs to PyoObject. We return the returned value (self) of these methods in order to possibly append the method to the object's creation. See the definition of these methods in the PyoObject man page to understand the meaning of arguments. .. code-block:: python def play(self, dur=0, delay=0): self._modamp.play(dur, delay) self._mod.play(dur, delay) self._dls.play(dur, delay) return PyoObject.play(self, dur, delay) def stop(self): self._modamp.stop() self._mod.stop() self._dls.stop() return PyoObject.stop(self) def out(self, chnl=0, inc=1, dur=0, delay=0): self._modamp.play(dur, delay) self._mod.play(dur, delay) self._dls.play(dur, delay) return PyoObject.out(self, chnl, inc, dur, delay) Here we are, we've just created our second custom pyo object! Complete class definition and test ---------------------------------------- .. code-block:: python from pyo import * class Flanger(PyoObject): """ Flanging effect. A flanging is an audio effect produced by mixing two identical signals together, with one signal delayed by a small and gradually changing period, usually smaller than 20 milliseconds. This produces a swept comb filter effect: peaks and notches are produced in the resultant frequency spectrum, related to each other in a linear harmonic series. Varying the time delay causes these to sweep up and down the frequency spectrum. :Parent: :py:class:`PyoObject` :Args: input : PyoObject Input signal to process. depth : float or PyoObject, optional Amplitude of the delay line modulation, between 0 and 1. Defaults to 0.75. lfofreq : float or PyoObject, optional Frequency of the delay line modulation, in Hertz. Defaults to 0.2. feedback : float or PyoObject, optional Amount of output signal reinjected into the delay line. Defaults to 0.25. >>> s = Server().boot() >>> s.start() >>> inp = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True) >>> lf = Sine(0.005, mul=0.25, add=0.5) >>> flg = Flanger(input=inp, depth=0.9, lfofreq=0.1, feedback=lf).out() """ def __init__(self, input, depth=0.75, lfofreq=0.2, feedback=0.5, mul=1, add=0): PyoObject.__init__(self) self._input = input self._depth = depth self._lfofreq = lfofreq self._feedback = feedback self._in_fader = InputFader(input) in_fader, depth, lfofreq, feedback, mul, add, lmax = convertArgsToLists( self._in_fader, depth, lfofreq, feedback, mul, add) self._modamp = Sig(depth, mul=0.005) self._mod = Sine(freq=lfofreq, mul=self._modamp, add=0.005) self._dls = Delay(in_fader, delay=self._mod, feedback=feedback) self._flange = Interp(in_fader, self._dls, mul=mul, add=add) self._base_objs = self._flange.getBaseObjects() def setInput(self, x, fadetime=0.05): """ Replace the `input` attribute. :Args: x : PyoObject New signal to process. fadetime : float, optional Crossfade time between old and new input. Defaults to 0.05. """ self._input = x self._in_fader.setInput(x, fadetime) def setDepth(self, x): """ Replace the `depth` attribute. :Args: x : float or PyoObject New `depth` attribute. """ self._depth = x self._modamp.value = x def setLfoFreq(self, x): """ Replace the `lfofreq` attribute. :Args: x : float or PyoObject New `lfofreq` attribute. """ self._lfofreq = x self._mod.freq = x def setFeedback(self, x): """ Replace the `feedback` attribute. :Args: x : float or PyoObject New `feedback` attribute. """ self._feedback = x self._dls.feedback = x def play(self, dur=0, delay=0): self._modamp.play(dur, delay) self._mod.play(dur, delay) self._dls.play(dur, delay) return PyoObject.play(self, dur, delay) def stop(self): self._modamp.stop() self._mod.stop() self._dls.stop() return PyoObject.stop(self) def out(self, chnl=0, inc=1, dur=0, delay=0): self._modamp.play(dur, delay) self._mod.play(dur, delay) self._dls.play(dur, delay) return PyoObject.out(self, chnl, inc, dur, delay) def ctrl(self, map_list=None, title=None, wxnoserver=False): self._map_list = [SLMap(0., 1., "lin", "depth", self._depth), SLMap(0.001, 20., "log", "lfofreq", self._lfofreq), SLMap(0., 1., "lin", "feedback", self._feedback), SLMapMul(self._mul)] PyoObject.ctrl(self, map_list, title, wxnoserver) @property def input(self): """PyoObject. Input signal to process.""" return self._input @input.setter def input(self, x): self.setInput(x) @property def depth(self): """float or PyoObject. Amplitude of the delay line modulation.""" return self._depth @depth.setter def depth(self, x): self.setDepth(x) @property def lfofreq(self): """float or PyoObject. Frequency of the delay line modulation.""" return self._lfofreq @lfofreq.setter def lfofreq(self, x): self.setLfoFreq(x) @property def feedback(self): """float or PyoObject. Amount of out sig sent back in delay line.""" return self._feedback @feedback.setter def feedback(self, x): self.setFeedback(x) # Run the script to test the Flanger object. if __name__ == "__main__": s = Server().boot() src = BrownNoise([.2,.2]).out() fl = Flanger(src, depth=.9, lfofreq=.1, feedback=.5, mul=.5).out() s.gui(locals()) pyo/doc-sphinx/source/tutorials/index.rst0000644000175000017500000000014712652732202020123 0ustar tiagotiagoTutorials ============== .. toctree:: :maxdepth: 1 pyoobject1 pyoobject2 pyotableobject1 pyo/doc-sphinx/source/compiling.rst0000644000175000017500000000673712652732202016762 0ustar tiagotiagoCompiling ===================== Here is how you can compile pyo from sources. Dependencies -------------- To compile pyo, you will need the following dependencies: - `Python 2.6 or 2.7 `_ - `WxPython 3.0 `_ - `Portaudio `_ - `Portmidi `_ - `libsndfile `_ - `liblo `_ Getting sources ------------------- You can download pyo's source checking out the source code here: .. code-block:: bash git clone https://github.com/belangeo/pyo.git Compilation --------------- Please note that under Mac OS X you will need to install the **Apple's developer tools** to compile pyo. Once you have all the required dependencies, go in pyo's directory: .. code-block:: bash cd path/to/pyo You then need to build the extension: .. code-block:: bash sudo python setup.py install You can customize you compilation by giving some flags to the command line. .. _compilation-flags-label: Compilation flags ********************* If you want to be able to use coreaudio (Mac OS X): .. code-block:: bash --use-coreaudio If you want JACK support (Linux, Mac OS X): .. code-block:: bash --use-jack If you want to be able to use a 64-bit pyo (All platforms, this is the sample resolution, not the architecture), this will build both single and double precision: .. code-block:: bash --use-double If you want to disable most of messages printed to the console: .. code-block:: bash --no-messages If you want to compile external classes defined in externals folder: .. code-block:: bash --compile-externals Compilation scripts ********************** To compile both 32-bit and 64-bit resolutions on linux (with jack support): .. code-block:: bash sudo sh scripts/compile_linux_withJack.sh To compile both 32-bit and 64-bit resolutions on OS X (without Jack): .. code-block:: bash sudo sh scripts/compile_OSX.sh To compile both 32-bit and 64-bit resolutions on OS X (with Jack): .. code-block:: bash sudo sh scripts/compile_OSX_withJack.sh Ubuntu (Debian) ------------------- Under Ubuntu you can type the following commands to get pyo up and running: .. code-block:: bash sudo apt-get install libjack-jackd2-dev libportmidi-dev portaudio19-dev liblo-dev sudo apt-get install libsndfile-dev python-dev python-tk sudo apt-get install python-imaging-tk python-wxgtk3.0 git clone https://github.com/belangeo/pyo.git cd pyo sudo python setup.py install --install-layout=deb --use-jack --use-double * On Ubuntu system prior to vivid, wxpython 3.0 must be compiled from sources. OSX (Homebrew) -------------------- Under OS X, it is very simple to build pyo from sources with the Homebrew package mananger. First, you need to install `Homebrew `. Then, in a terminal window: .. code-block:: bash brew install python liblo libsndfile portaudio portmidi --universal git clone https://github.com/belangeo/pyo.git cd pyo python setup.py install --use-coreaudio --use-double * To build a universal portmidi library with homebrew, the formula must be modified like this: Add the option "universal": .. code-block:: bash option :universal And modify the "install function" to add the universal variable: .. code-block:: bash def install ENV.universal_binary if build.universal? pyo/doc-sphinx/source/conf.py0000644000175000017500000001753212652732202015541 0ustar tiagotiago# -*- coding: utf-8 -*- # # Pyo documentation build configuration file, created by # sphinx-quickstart on Thu May 16 15:35:44 2013. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os from pyo import PYO_VERSION # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('../../pyolib')) sys.path.insert(1, os.path.abspath('../..')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.mathjax', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Pyo' copyright = u'2015, Olivier Bélanger' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = PYO_VERSION # The full version, including alpha/beta/rc tags. release = PYO_VERSION # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'nature' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {"bodyfont": "sans-serif"} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. html_favicon = "E-PyoIcon.ico" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. html_domain_indices = False # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'Pyodoc' # -- Options for LaTeX output -------------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'Pyo.tex', u'Pyo Documentation', u'Olivier Bélanger', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. latex_domain_indices = False # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'pyo', u'Pyo Documentation', [u'Olivier Bélanger'], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'Pyo', u'Pyo Documentation', u'Olivier Bélanger', 'Pyo', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. texinfo_domain_indices = False # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' autodoc_member_order = 'bysource' add_module_names = False html_add_permalinks = None html_show_sourcelink = False pyo/doc-sphinx/source/download.rst0000644000175000017500000000053412652732202016575 0ustar tiagotiagoDownloading ================= Installers are available for Windows (Win 7/8/10) and for Max OS X (from 10.6 to 10.10). To download the latest pre-compiled version of pyo, go to the pyo's `web page `_. Under Debian distros, you can get pyo from the package manager. The library's name is **python-pyo**. pyo/doc-sphinx/source/_static/0000755000175000017500000000000012652732202015660 5ustar tiagotiagopyo/doc-sphinx/source/_static/E-PyoIcon.ico0000644000175000017500000015077412652732202020134 0ustar tiagotiago V00 h&L  (  hPNG  IHDR\rf IDATx]`UE֞H"E,꺫keW]**JE, v.{[{ {dr_ 9sfܹ9}PHM+|>fRs P P`P5d6߯222Χ69߄%+&K} N֪ nl1++h)$R\Ay K;i`Ʀq)wuXꁅ@!L,e"iWY|Z~ 5k֨E~Pѽ~CR5ZEM!t2$r)P232!TT~Aо*))Q[m}+ Z֭?337@XQPl ¢5'(%= z EBLȚ>6l駟C~,Lr K+^|f֯o_SS#nW_~Q~6ܶ f2 gd@|~ܹSM{^zҥ3~Ԗ[nab +Ȅ: 2Ἐ iT%MUH7YT}nnhPٌ_)p0Xʪ_jW^Vv]{^t9ˮ;7j gϭMD:5Xh22ydꮌI@$vZLw+n쳣q$ Қŋ꛾>$w7~׻ -oO$81±@`-Ҭӻݐ^}}G"UUU-//_/[!4}w?yKuazAj!TPLA a%- 0Ri@JӪMUNN<ȫk~ݢ{㍷CP7[=xQP(ciQxxj^@- a OMZjֽRЀ'\~|&~ݔ9,WPB)&VB"|fcȈ';w`wZ>oÙ hl( ciBH E`  l|UhCO>z;/Y3csrYTTGP]])>0l1H_EwnF@:#%J #/:3s3 a>Ln^ ;e j<ND@^@t`&('Lh? ߻$ |JǖIY >c v"WPnV C%( |x^U#qelS\ &@~`eh5\P[StNN;uGqh1Gӧw dFMJ`3hf*ZYh^Cf|kS~QOnWXxP~~f>U# D%M`$;JqJPC`pd-~6ȏBӛT>\XTО{'Gv>LA_k& $MyZ#@Br>[gesE/ p}wݫ~> Nh׮]o=Z*?­drLKj%ϩ# Y%f3Gy_,@=^<?D ZH& 2{1RZxPCWUKnjgywC/Zt?#sHX+*g_^״U{"%<" mA3W?;39LjjB)I --b9gϪgtKǟj岓 ߆'AhVRIi)(O&+֮]4Һa]Ιg =c2;th1 iV=J>|n͵z{(jT,`D5C^/ernҠ7 #IgX@rQD- \v{UWٶӃ 0FN3lqN |5vL8onW^z'def` l5‚8>]#0г*Ux.侉/+ˮغGT5hЩ; ,۲ h>?kǟ̘qu' Y%K zNeeX^MW){@E7Ҳo0N0G=g~; ]8AakuB[sٌ+pʊKJNw_}-Dx+[)ӭ:72I - DA醲7L~OL2EPf1f9YJ46r7ڔpC?:ZN)kfϞ[j %GC VVF~Fz٘J_=|ӳ{צ_p}Bm+G"=Uی Ϲe|x .Z۷/EEExi෌fjlMkVyᜓO:۩ӦdufI*-V/o)>?BlS‹k >>4@xܽzБ6-D)Â38ثXrU;w|ʔ #GA5eg Zhv?}Byee3g^S}ճ:W_ֱc #q5= ߖlJfbƏ׭?y啗eߩjmoR,B}3>a5(Gl|дߒku }uu `Ðƌdڴ)(@ڀxK iu懂Ub 4S]\=kMYRfu0rH dÂDX5֬^jR~nᆫgj sU*_AaaH:lL`ةX׾ z yJIDG5afu'Naw9]e5V#>5@W\[}E3|prpzg{]ZÇLC%B@8^r=}g_CIߣFxUkgyI+yCK:vnxՐ2nK6ý`Wͨ8,wgbxPKZ[Ueerp!eV\کSDoMً飚Yg `0ᛵkV 8}Ѐou5(9/欒VZwsʊp#$$Di~/f9N}$bw?;nʸ>B{ rpX5Mޜw۝/-RE-wgҼAW<w=Ĺ\NaЏote\WUx7 󎹵84rY68 @OKf!ctbᰈ'diނ䔕U⾆xcE_^@6Q88H)Т^Ei~H]3_~ '+-+J~(i/n[Tulը2QI^ + kVSN=n1GUazVZz}?;Ӽ\~[}]b?)*)JN1s0Ʀ}np|Q+W#zPS)z~% cT6/4hX?\>P~a[&2m:a K/w+j!VdnDgp%f01;t[ne.]7{S|<Noh/5L;]]kiC=}?j+Q`\M~]z{I+zvӃA \e9o-jl pU)g*>-GP<;cZ4.@Yň+wk `KU81%%Ǟ &<6;`o|}atn]y䑇 `ly"|XAj?2 ,ߜx:o1J@-6| UWUq&6pUN ad?3FVz<€bWŨif["*21DpK/>u׿16zYzѦZ,F"Ӧ]߶?K /V$vK*=;@L l:cb`? 89vn ?Dn;v W)=ג{:J !ˡn(; {gs PDӍF7j^ 'vjWzjK.XW^%?_- trͮt_ma&~U?}PoAs &DaOߟ3\XX$_gIKEmM?$]^#կXf͚9s jYZPėT\ӧOO>v1)0yՒ%f}};R_fiu%sykUl_B_x~9Жk@761Z^|ްacjK0_m #5=v-`#1+۩}[= UH~{o 5p3cseWV<Աd,n $4sZQ \ T@Gk_lc4 )[T]zJ:v[^Q%_+WItW0@?h%Snj@cM6V$U[ 8'sI *u 2\=;m%K@Z1nܹjkСhLs@l4 K䟭f8f5KRH/DhWXx-V/+e0SXG?xAԵCqNj0 ?Ww5:K ޜSAZڤ Y̢&7Bp3+D > 1h_ d8`LQI%c%ґJ TJ:utoeh] @۲sϞ7Ҿ; L@ @z'Hk @3Hw4De\p*//`N8ehL@\?SNB͸*^ ~+ eU"m- fg^*8?>VW9D4JWXi՟im61q_€]7_~塹6H,M;ib뢾y흋w8 3 +=gtnJ--c ?9 X zߖ2ʫ`Y>Jޒzl}K|̾+Ԫ+-!=h*PHxX%Oq1m&+15gϾMQ;n?d">U=KJWV?=GM%$-ӎ# q;QSVǴ Vagm ׏9SOIoiܩLaV0R8 V2Ҧa Kb7|JSٴkRFcЌBB%K=ؓۼֻUX2Ԁ`@Z剙VՓO>]II@(rG:˲dJޘ.F2'N*&i6#>f2 W]u=L@Wg^{ fޱ^w#_' ' G>s֬9 cxt_W@ڕ(x)QVRt/m% c%%C;U:Z>C0!- n ?8ǟS\\|"&0ȃ>c!$Xq&p5J#Ѽ"YH&N"0^ @[UY9|M2A^'n YsܦJBdIQnYHŴOX; sbX|f8㤍 nNeUɧ_Ub N. n- .*-dI檿?jf:~ቧ &;xҖ8OZfq[[1_ar_/6H5n/`ߊVqޟMVX '^~Ce;eQcgmݰQ^g@I>Dɒ%TM,p<ʕz豜ӹ@ߣMc?&P ™V, m3v`SH!ϟ1 l@&V%$_4h„-];_fhn;^$#a6] fbKxl开|邽^zZ [cjQh&$~w?dd_/_pҽ"͊-Lo x4mfJg;R~L3E_tIOH%ٺ17vOx"w=["8/V[p(~RE!+̦~6~&~f5uK:mA7if/dj鯿C 7Gs%۪x*S$x^|t/n3a^6? =7mh keȱsԋ/ H" &OO>;.imWŴ=4nM3[!4bLh/n?m]h^&v2< ݴͰV`ip}QnŮm5 G^@ԩA}.z;+أ*KJEi1ittK~l%g뎔f6f-qL$Z4. 3uk 3g~p7n@w`ZdnmNOeӲ,w-|N[~ mW¼lINj_$^<~/^g>Ch䷍Mڼml:dQp.2$e|cI0s+rxzxlz<~Gܴg~my f7-◴oXd%mɋI3ݱMvltBWs3#4na?JK?3-戒\JzJeWf~m /43[i30-[؉Kxl3x[(?@a|`ο/:՗ ZTTR\G,_ܴ/'nnGL&̢T`|\ݢFwh.jq|%r") nY|fat~; 'p-If\3Hiİی+hfx[p;r5torFՙwKyffeM3ی'Dm8y^@atI'፱0;mP Mv $~z_XL;=8 U+No6+ASI۶'7mӖpI~15i+4g4c{n#űyl4=׏/ }.zh2@a)pˤg+,F]L ;/ÅǴ%^:m ^$=3\ҲiHp6xIx*mC*l&iV{xq(HU^Y0O -=XZZZ_srs @1n':Ä׌-AҖ촄h$L^I6v>$ܤf ~Wq9,@~'O{cqo A|V;bƏfa_^I^~/~G"?'q//nMɯ vdlI+(ΞQ woP6l(m-Y[SLC+az鯿nX6T&%[>\c+ 7!~#t/یO7A+|v:my+4Rʹ%i&qMē03Ŷae'_hLZV^ooueBWUW9Pru{Uǎ%yz{\t֡0@z5T 7;~|*z!˗]be7H<p%EX0ґ0yN&n~ 7y&iFH?ŊHKHB<43v4yMh 7yuUV~q wZ MzPe_V˖-G9 b _EK̴v_ԶVeeͷU׬U)B`~ޫ.+֯o y` D 5GIH<0M[ǤIm Wl0hnfri?EK^Q9AIfmF r ،/n7/dlOAlO$[pI5LwG !-;Z: ;ԕ3.} ?PFjS_eWாLwQee0f7Fuhu%j?;n Z~\d Zy/']8̈́KYv;r״qK —8bG*L<&Mc H 7Kn&=7LO5b.t<½x"$xl;Ʃ UVSN:A]~@5\(UUeCB25i4b*—Q(YWTƎT5Zf:8V^^μ;^W?&=U- ֽ{?;oIrjz3#10喛q(Z P$^̏/ 3-cYɚ5kj10_v3i͝|A. hvJ1fėp &8#M-noH0L_lM ibK^oڶhF%Ŏ/a|iS@=_`fj$)]^|ͺeW~oVoBd*>i'fG)P2ݧ`=۳{@ڢUбcno5M>/@|I5my.++mikVLіJkfr45zΟ*>߉?_3MRcO?m'8nn*ZC)su_3#egBwү+WMFzRԅv* YP( JP?i\ шh*f @V\{jij7KW\v:#+YT9oƲ_E4'gBt!t`M׏Y&*0 4$}Gws2 (ΖzLrTbl]F \~9,KВjIl%Bd>k~GWB>|}!]UO2ҝ_tM|@ҘI+x2$q5ߌkG?)M~V:IS{#mZI6{-??n0gS'Wq_Cդ*ȴX^̿% c}ÏjqzO&r;Xqs[03+Vr0yFYQZYB`jOmr]b%bL&RBfeVC9/ f)j:X  ]c M#e=ʟ/a?D 2Jhn-t+ԡ8 y(3=yϾa6I )*\{MAnJ@AAʒ~N+ȏoW<6|&?'vr %-?i4 4_l4FCus$&~5f9hN>Ƌ sDhD#ߛ ݷtj O@_:`0e5.&`S<{Ez_$XL|k,L쪜l|z];0vf$-!4I&`Y1k-%  b|lxHΊͬ0,[mS-x?COUիWq, hSxΠ#>^E`ά?? /,ogDpG{l0|o TH(`9 f̒- h2QK@@( # Cc7+ fE_ % [O7㒟4q-ϒ4/4DM^-}oȯG?ܩg_=l}/ϙgnU;8du\oF oÈ~9np5u#_ۏƥ J}YH=SIa~⟴iX6prOJ/ML[FɊ")nV". 7L?iF~6Ё3\Y,1OlF0 @05wt-X^T W% ~ [~i16hש==ύ>/ _!v:z ӣP1/f1p 0O " ?N+^IVnB} {U Yʪ~ k6-GfL7/& 1M> wmô~1]3~ɗؤј~kGr׏Q磂LqI;}wkwI7E/qH'Xr1nG ^n3KgW]+ȇc@annNP ,fT׬ԩc5T*>H7Ըq[T$ncG?i^0 IDATK\YYθtWa"0ai3^v328d5?z.sc/,X|!4Vrd(\c5ђ^?6v 6b`2bs<44׃i4vF:4J(1@ktiA2`Ff\mGa4b#Bwv9 ʹm3̤1]O ̟CW}},/FwL?Zo^Dz*uCˢ}/͛{]2~'_Pg~Z`w@$k0`- eaӺ`|h݇0#ݱK#0l_L5ݬ)0tmFi M^ 8~ m3tG3y̩ƆHj?K:_|UPyT ȡg8-g9s=˔a 'j3v/;j;jn og@`FgA#KiŦa1Di6O~ Z4-f*mxK3QЖ.a&xlIϥ`a۶64xIcm&yb-,GyO,$ J.=k5pO-?uM.6jzÏtq;o %ϛ|iY:-?=M ~}v& OYۼzU9oX/JKیlMF -n :mk;DW4ė4t$&Ϡ_h^B@hb [c^^43/XۦLV$s\|`o>}/a4~u-(2!ǡ>+If$f^Q~j-E7 ȐΩ$z1 YQ4"xg2v/n#<6!Op}N4pG^n&itm!q&O$#a+?׼؈3Yo)~[!|;e elFMIꖟwF]gsy r1Б'}pO@_3 sFskҿ៴.V@P6Wp0hM$?y"% gnn_x&qfOl۶%rL-?o]xa8'X"Eϑ}|o?ӧA ?qBgO0VɆ aMaoߊ.]:'4mW2?mc{īP_&G)?u~F>)kl3[w_1, @@㠸 +BJ.iD.kT~xAwH?{{eleKM?RyH~ךG1fz75ǿ~}zZ͖M҇p}9<DM| p; x3P:tYGaPxPրV Y2aE8Be39/ҙ.M[xMxNWh^#M∛~nK%m>ƌcx6 ܠÃ9~[~PG[n: DTT\2a?[ _{o& tM3}F oJ<9Ld/իSFWh}(gަϸAL5 m!3WMWғ8pFY-t/ᤉ[l4#n3tK>.nWo%\Ha?WoK-.ZO7P\~8<;?Ae^ϖ?\^|% ~vOj_͵u+=!+wߺwfтs >7hF*Y6 M-4I-~ [H? Hv$ZhtPo>~?_ORqvڟD/ j?Ҙ{>D81n4#WYV߲GLN@cz 30T:w,lU2 j%fDyHi =1-iGh0#cOнl i-~. 8Dg~ 'w䂙18ݫn Tys~ mlKj[6UϞ[k[,n !z pmzea6~ _V O8fqS^٦Hn+ciF㑖]̸[Lͼ.$Ӄko|'߻gx晧Q=+K;nC9.d0?oh,$RͤlZ"~`JVm#{g~'ͅ29^ۏ~>6%XT^\ô1s3Y HǙ$yϯ<`I܋6 3% aO خ t9u ::Cx¦FnL6KbG Ӧ[+~~VJf?Kgc?Z~$[G~~cG NgN9)ǏYy'x*0&0g5!ש3շ /Ovw  ᙀzc|!WB) ~pI]n|4&)-iɫ4iH>" n-oҼBgv;<5jXS<?oMHw<ϣ) 5{^k|o8lNoWjz5Uva !w_2a >$ɠSZemm7L۶M>;~&~&it?n>LˡԽ i#"a~n P՞~ZF&5U=s ~= OO8<-4~|CNȻ&,ónmUmM #GڄK-3O0 |G$ϚPlc#hhs γOz򉉍jg- zc79? pK.H?{MaQ;ݎ"̴ 3#qa!>^m]bK?ҘƸԼ360?j$Hk ~W'zhtsny_ijqh ~gk5WMbinת=[vN;``-{aߣ`{h:w Dc ", ;\b-44|n$7%nӘcM/b3Mq9lpTe-A}t5<#]},F?i'~pv?7챵l/X{MtuͨϦK /;hf}0I@>sם~^bRIҌidzv"Nt Imџʟ7yi /Mso#xgn9ӰԓNڏclF{yyգ?@eEo5 iO:|OogKzȣG66:j<2h3Ƭ^/+\|;ZGf\D#=ޟS)0qӦ~,E>' >n b$L@= '9):BG7Ö-@X S޽@gWIQjBpV9qhQې8oXxm>Ӷݑ̓5m[0͸69׿sTgȧ9(]_S}NSȺ[~ܻw C<Apg{z'[_>k;eܹSNUU5zpЊ!4uםvyOq{Ct`X gLoM[336W6ĘtiLׁni0L+9H/YC99W7i !887TO(P Ճ?S񀟂bЗ4Ö,jv0W0@A>s߿~{TX",9dOnHEE7it~-67f<+E,|^iشH~ ~y.rsV1T_8 9uZ"޵~}3bCj~~Ճ<Ĥo8O[OX46<# {jh2s6R7ݦyMZ$7s0 p3 }v3&&~9Ɠtah+ ԂϿ~v~l"Λ~G-u?gCX.Axs=l?okx*V]<Ѷp݀v݀>ƺw*4+3;BC.\{f>o-VeߵuVoe" JR|dlA i9{ǷX^/cD7J^ 614nH|&]b{LKx ħ-3F_1qHφ6PTW _Eeҧr?xI>Z:sK?,4o rnt~y2̼$, FPD`2;c2xgE/:W_t[y뭻[6\nw˂.0^ Qչ߇Ƹ&'`iwܾ_ջ0KD"-(E; }ñKa1!:i|Ȑ`?OcEIHaB[z4[xŶy.6* ~,U\x4\}@5?LqExfܯ+E~cy[c0K]Z!b?STW?f,p?pDd*"hBs0%XZ^V qk@D[e)̋NyxMDuZ~YÖmogT'?~X;0b/,,ԣ=X'u67 ]>7-ls箏1ûhǬ1SqkO=$ *_E[ dDFWX$CM[cѭ @D0Wlqߙrk cDh{7j~S}gƀ;_t~؃+ ?g?cO2j)yޝaݺ'9{_Թ.,8|D =`}bmm0,0L;"G zxfLdfztN+WRgʭƸ-݅|=[ gOxK>*!/!?xnMx: wu_K EYY7Kvuyqݒ/š$P[{:~Lui'VV_N z:j>-`<_yJT ؟9{8ܻɴdO ~,8NX_FPq*;oPFG^n~*p73T~,󷂖c\3p)U]tfZ~#c?nݺd< ץNQb#SmX~ΣsK/Ru룃Ѣcm:7x>?oؽu|ϏuϽQm-D%wbūs[㞁O%+y_"LB?#$,X1 .>,`Əx< 8w)0%/J/]7"*l-?[퐟\u#jU1K ~-wBLg#>}s/Fcol;)\ ` :5kߋ9ط!I;ZUp\`w}~ܩ86[~ɿ΅ꇟcY~$2:kϽN ~Vp;lGwAze ˯RsnWt>|F~6eyfe ,֟i'%כ:tӹ. Ҧ~ SISeS"5jZi8Ƭx_/;kRM?5ؔsWo7?oe~itwkS_:~[Àmeޟks0AO8Z)7NV} >>rgϗp8D"| qɒqG48[vVZ🤯?cZ氕k pFIsp݋~.UL˖/l',2snρܠ6=z,"nKQ}|*̕+W=C?Ŋ\ ?%rqu _O<իV] S3t5̂K[tb3gˊʥN;|h'//w}ı?Zkk3F4vw??[~VV~~hsQ/o׮MzM̉kx(U\pܥUUU?hKMpß,O}\gA_~ހQG ~wy~, oU1=-?ڟl4nٕf]jƐ!esp?W$F3J)!. uU Mf 'yR HooyS SB G0@D<2SqjZpmgEIb:u[c>nQجҲ7{zi?g?N‹~޴=?fz̘9#Kz@Ы㠉 oŖ;{' F?@ s>F}~ &F ?Jy A<49uۜՎZwy/ECW7V~/~!?4Ot9]R"TPGkg\zȜ1U ~ABRމxkq9g}Գ#?ל3~nj Klf1Oi6v;S=/.V3^0nNB_d3p`UO̫ gI`B >`ȑC~]jչ[8m:D@D}l|pZ}S`Zeyޯ~ZAq_ 0 @nTfq݌_W7nu7ý~_u3/fYO?2)+ :uJv݌㘲)/^[(~#p|F3^A>Q dqw}ŗ:|ܨaj3;Q. ~_;X:N~F/AkOaMs[s*5 ֎6mJi3)!R2gb% L\57KwHn~kٗw}|磊O qp.~> u]|Qը 8i^s Pgln6nޥOR?V :}~S}skgAyg\j8L/-u/g츑^bB s%PrT.LG+OeF@mꃏ>0#Ql5sUmKQͺ;u uz_4K X{umx U̦}حk zL4RaqmQiSrv}'vH2 pP+RX%\y<㑿2!#LTj!j4~< yϥzujx_yU+9gij8N߲!3g^TV[9]*bO*IsJXA4=Z_AAqxɅx!F2-Q >X}W[C5fw”LPo;Ǣ߿|燆#6R(_w ׅmzOC_{MmexK%WX1y>\]&Q3AfehC`nso:dX)*1π)ɦ#|uGUe;4HDZ(E,T]WA*kٵ,+ K"E&T,HHdZ}g&Lɼoڛs[nIɴZ4_; eԼSgiC8Qp͞zwTC^Z3_}Q]־~3C_zUMzժ~>,oZݴiMh&stW_BҌ̈́;ﺯpxY +H@vtWt/zIi z6W 'm}#0 7wR6!`~^1iid-n=会 ߱C{Y6s'c[\G?Of]/{=W["S(eS^ҵ<~g 0tDL0H|Ϟ}v=;0,pH /~VHj7_/m[Ro>]$2yMP0']_;zS^T`Q0g?Y/59ާӏC D$1-o1k֔w}R|U׿D|7⃦)CF#hf$x4?*;݆-ژs d^~Q[_@o-dJ5 mħEP..2m18s3{ ~>"pd"0djӦiƌ(c`F+P Ϛ|&dFN +&=E $O* nЁVzzϠ.XVʤ >:c섗dOu%gݥp93M B2+_}5^<.@axL"y1B@2!TuӍ5rќ[am2& f&'q€ϕ>xGvZLmD=(.2Q]H  c*/.5]$&c]֠A͟;aBbGW Λ``|v9vmk23Gg+"+Ufά&Sd<\-0(93eV#ū^Qr0{y)ds^/x0X+~0!"%{7_Ȩxq O.oғ:j&?@ϣؽ'}G1?p% `nzR;UzSw L"(Sw,S#xZ‚i I4#p?\V!Cy7^crBfL!XO̫W xK2b7@CG66*|25*5>I6ؾczot >Dt<-\6@!g=F="8֫ݵXAyw?dkdHAa Y3G-};DZ/b?4g@etrM9O?{ d/4/*H5 L. <<L$qG dj<ZC˺&,~YW2xD5?3Y ozB?''gd]ƮX(9002TהzuZϛu` 0ݕ>~DOߍ}G͛#̹ǽ6i6Mu{X?`Ȱg0b߇e(a8_u"dp}>Op__=]x Oȁ,DfxBǠk?Zzɓ'{`V1 g~܎ݻMgxMI ]f _dN?gw:?teL>2(@0@m$С4^=Ooӣ>x^x.3+ Y|E @m v0;Ob\WrX:`@+W.'Cb C7$&*."ٸAo;mW0tͣ6ytƜo8+ ȱW<bē-$  mW7_ff:C) ~"pB ږUsLg |f16$-828,+!*72 8ep~^T 0ϗ$ 2t/ޘxYwuU'!ӥsaj{^ع[ g(#ܱv՚i̞U͔!j8 0<;vplX*uV9:")lr؄j PZw9OZ)3]n!Du^_w^ύCxo&siE1G ppZ ٺN0IqC t5~.!/P2 S\ƍm~B7CFCseM)τ6޴Es^RG]ezw,C )z:x:t5GA𣻈Js8lj%v{g? w~ 9`Ch*a+\zpiv֑n`V\?@ĩ BT\OkZ^g^p__ۯoAπ/wI'+Wx7h"&_=rqZJZ6 ff2Ubg̜n/ fήA8Sx| o_իWCR/$L 6Z3%Tv"BegsYRk P̱jg&:{N5D?shnCk=|yvCb8nRYY9%ƒy};|Zvcى8Ot|ܙ_N2 alܡL7Pdn o/Nsi%Nv,=z^!.>v66V`,]f7__8}g/D`)bnK8 ?BO);N OO>D\L剠`!•H&}IE,]9YknY.} NrN|dRh>ľ;Feꪮ ?|ԴQXц.;Wjk 0:zвe3_zoz.x 9G0Eb"Kο>Lau$3KC0z SWC:l ߒ[|Iv6l1{}5a pZO Zs[ 0=Hp2Fan[X(\ [s { @wLK!kN/xsvl޿|ĈQ_yͰxw|T8&k$'I@CG䧉!ވ=o_'AC/5"]|91Jr3E,4{i1p E?oXJ&b ı{@8.]5)9yh*!+Ɣu!]H5T3/m*'N zKpҟh)0h=G -]pZV籜/)8h@ Q3B$-A5e޼QFeddwaw`N R3/\˕2IޠMU=@Xb -pno3YkzzS 4VQDi}C+AZL=JsLO?s` ڗ`Hx)z̜d-h0A z}}?# X񼏞8~fgg78)@6L~DBE OA@ܲfzדlbI5bg0K5 IDAT@j`5| aA@гl7M*!5 ~ր4u,Ǹq/&fds5G`LUmn (4BVW2t§Os#>en׮ u&d?=#~#%FpW4oljgkf֞*M֐\g8,ܹۅ(B%+!5k WTetTe3* BT‡XeZc0%:T_ ﹖-/^_b׃(H'GP^|Py@_ DnMʒ;vR\l;_P歐vsc$V@=>SP } .dQ1ѳ lc4I_s֔fpɳuThC*-3pJ` ';'L|ɳjS.H &CjNrH5䀏9usBMWWUޜGm8ہًl7[r߽ws>߂/3%\|! CXS 79ЯA`lʔ{ܓ'a.Ć7;\S|[T?4T=trQL~'tlɭ[^{ϰ;ClU8Z9x4U(U ǰa{3gxIC&ޛT##fbh`(' R>Ȝu3yYGrO,zWnG^7X>w429DQ([Шqn mق|'@=.s0H*7K(;/g5#$UP0 ^l \Z >J"n36k lE6hi.WdC۫={qH6iN?xH 'G)' jLt"Wݽknsc;rOvKH־zĆ('̏ `fZiqaܿ4J:B{:6% #1);3"l}޴Y:uMWuׯXYLRJ iJ/ҿ}gF83:[A Jr$LVr`/þΏ>dZf3 %:&V~)6쬏F)?Yځ@1 \?v(^PO ʻssk(ͤ>xWnnd܃+8m{;thׯjҘڵ$?wњ.w)] 94SB0WQpȮ9Ddv~>4mgϷٿG^2\<@%j좵g$ wr0ѷH;_!-x쁺pR@q0UൺzRmZY޽kj߮yttѪ'D.Pm$FQPAXf?} K2=Nedq8pгuWjO;=5/i_+ԁ$RwVޜl>d X*_Z%R x)aF) }ׇqM6އm~A"﹨aղE su3+<(D`hӲQpn6?Y,Hp2,Np,?s=z{wnj:zϡC<ĉD|kZU5V ZX(ixrV Y#OqMݟX-f{Fƍ4Mo}b t&L:}Z1懷̃6L` HVyN橓'N]ğHj/f^\RP`%  ٍ9׽JIVi:ۮ/  yȱԴZv,U)ɪAUKT 8`mŰ@ mTL0a<%d1.5~~H D@ER4u{1k@w H0)(h6ɓF8deCK2o(ChC( g5k[r):dkx~ls)΅P^@ 2H?V;D Y%`Зir˟g |%G.X8IENDB`(0` 8}}Zkedu^WW]VU^WVlfesW5(e^^z/&%  2)(kdcs"M/%$   "&&#  "!  3*)D;%           +"!3H?? !   JABohj:11!    ! SKJ&!   >550''    ! ˽>    d]_A99      解0A     ngi  7..  𥠠20!  ibcxqt7..    굲$   &/&%rkmx{2))   7//  ztv2((  F>>|vvZ!   KBCzsu3**  !H  LDExqs0''  !iccp  #MEFwqs0''   xss_%MDExrt1((    #Q!  !!#' PHHwpr.%%   ??76  !#$$%& ) QIJvoq.$$    NGF   "$&'()()"+!  PHHvoq.%%  ;!  "%'* ,"!.$#.$#.$#,"!+! #+!  RJKsln,""    *pjjk! !$'+! .$#2('4*)5+*4*)1'&.$#,"!#+!  QJJ|~rkm*!! "~~WOGF   #&* .$#3)(8.-<21=32<218.-3)(.$#+! ") NFG|qkl)   `YX~:10 !$(,"!2('8.-?54F<;I?>F<;?548.-1'&,"!) 'PGH{}kdf$  IAA-$#  !%).$#4*)<21G=43KA@\RQh^]ZPOJ@?=325+*.$#)%##KCD}vy~\UV|~800 6.-+"!  !%).$#4*)=32G=43<218.-3)(.$#* &#   F>??66"! TLL_XX  !$'+! /%$2('4*)5+*4*)2('.$#+! '$!  qkjkR!  "%'* -#".$#/%$.$#,"!* '%"    !?!   "$&()))(&$"     (   !#$%%%$#!  4,+c]\y   !!"!!  uooe$   >76   KDC3    &D=<   TMM   O"  ">WQP "  #f`_o>65 "  #LEE<43 #    #JCBRKJ     _XWy~xwW  !    !錆I6.-            >55?.$# !    !! 4*)65KDC   QJI/RHGH>=:0/1'&#-#"rlm{}PII $  #)2('>43SIHe[ZRHG=321'&* )rkm|~]UV  #(0&%;10J@?SIHI?>:0/0&%($&qjl)    !&,"!4*);10>43:0/3)(,"!&! $iceWPP>553**+"!6-- #(-#"0&%2('0&%,"!'#    @88`YY   #&()(&#  #nhg~G  !###!   :#  +#"tont   }}e   ( K#  ">f`_$ %tnmsTLL$    $`YXd]\        ohhzO !     ! ᡝEiba   pjiy ZNFF'    (QJIT *.¿)(0 RXQP.%$0'&XQPNY&  *!    )ܘV KCB $ # $ PHG 2** #  ^WXA99H@A  80/ F?> #  F>?¾#  ! JCB~~k#  mfh"  c  jcd"  $ g   )kdf!$_C<;  $(&.$# kdf HA@   $+! 2('5+*.$#1'& leg$'" !(2('@65J@?@65/$#.$#kde' + !) 5+*KA@bXWJ@?5+*&' hab=55 % !(2('A76KA@@652('(# g`b#$+! 2('5+*2('+! $ )  911  $(* ($     @98vqp{  !!!  ~yxr"    ga`   !nih (     ,$#&  !      ! "%%       )! ! bZZ e^] 'jcc/&%   0'&mff$9A8(  ibb*!  ,##ked[ d]_ysu  U`  #KCDaZ["Z) YQRWPQ "#[UT  " b[\VNOa[Z!  $+"!h`bZST &4  &4*)=327-,f_`WPP C  )@65[QP<21,"! aYZ8  &4*)@654*)$!PHISKL   &(&  NGG  TMM; "     4{vu}#     "}}v{ut  {zy>> a = Sine(freq=1000) >>> print len(a) 1 A Sine object with four streams: >>> a = Sine(freq=[250,500,750,100]) >>> print len(a) 4 The first stream of this object contains the samples from the 250Hz waveform. The second stream contains the samples from the 500Hz waveform, and so on. User can call a specific stream of an object by giving the position of the stream between brackets, beginning at 0. To retrieve only the third stream of our object: >>> a[2].out() The method getStreamObject() can be called on a Stream object to retrieve the XXX_base object associated with this Stream. This method can be used by developers who are debugging their programs! pyo/doc-sphinx/source/api/classes/map.rst0000644000175000017500000000146612652732202017756 0ustar tiagotiagoValue Converters (SLMap) =================================== .. module:: pyo These objects are used to convert values between different ranges. *Map* ----------------------------------- .. autoclass:: Map :members: *SLMap* ----------------------------------- .. autoclass:: SLMap :members: *SLMapFreq* ----------------------------------- .. autoclass:: SLMapFreq :members: *SLMapMul* ----------------------------------- .. autoclass:: SLMapMul :members: *SLMapPhase* ----------------------------------- .. autoclass:: SLMapPhase :members: *SLMapQ* ----------------------------------- .. autoclass:: SLMapQ :members: *SLMapDur* ----------------------------------- .. autoclass:: SLMapDur :members: *SLMapPan* ----------------------------------- .. autoclass:: SLMapPan :members: pyo/doc-sphinx/source/api/classes/triggers.rst0000644000175000017500000000504012652732202021017 0ustar tiagotiagoSample Accurate Timing (Triggers) =================================== .. module:: pyo Set of objects to manage triggers streams. A trigger is an audio signal with a value of 1 surrounded by 0s. TrigXXX objects use this kind of signal to generate different processes with sample rate timing accuracy. *Beat* ----------------------------------- .. autoclass:: Beat :members: *Change* ----------------------------------- .. autoclass:: Change :members: *Cloud* ----------------------------------- .. autoclass:: Cloud :members: *Count* ----------------------------------- .. autoclass:: Count :members: *Counter* ----------------------------------- .. autoclass:: Counter :members: *Euclide* ----------------------------------- .. autoclass:: Euclide :members: *Iter* ----------------------------------- .. autoclass:: Iter :members: *Metro* ----------------------------------- .. autoclass:: Metro :members: *NextTrig* ----------------------------------- .. autoclass:: NextTrig :members: *Percent* ----------------------------------- .. autoclass:: Percent :members: *Select* ----------------------------------- .. autoclass:: Select :members: *Seq* ----------------------------------- .. autoclass:: Seq :members: *Thresh* ----------------------------------- .. autoclass:: Thresh :members: *Timer* ----------------------------------- .. autoclass:: Timer :members: *Trig* ----------------------------------- .. autoclass:: Trig :members: *TrigBurst* ----------------------------------- .. autoclass:: TrigBurst :members: *TrigChoice* ----------------------------------- .. autoclass:: TrigChoice :members: *TrigEnv* ----------------------------------- .. autoclass:: TrigEnv :members: *TrigExpseg* ----------------------------------- .. autoclass:: TrigExpseg :members: *TrigFunc* ----------------------------------- .. autoclass:: TrigFunc :members: *TrigLinseg* ----------------------------------- .. autoclass:: TrigLinseg :members: *TrigRand* ----------------------------------- .. autoclass:: TrigRand :members: *TrigRandInt* ----------------------------------- .. autoclass:: TrigRandInt :members: *TrigTableRec* ----------------------------------- .. autoclass:: TrigTableRec :members: *TrigVal* ----------------------------------- .. autoclass:: TrigVal :members: *TrigXnoise* ----------------------------------- .. autoclass:: TrigXnoise :members: *TrigXnoiseMidi* ----------------------------------- .. autoclass:: TrigXnoiseMidi :members: pyo/doc-sphinx/source/api/classes/server.rst0000644000175000017500000000022512652732202020477 0ustar tiagotiagoAudio Server =================================== .. module:: pyo *Server* ----------------------------------- .. autoclass:: Server :members: pyo/doc-sphinx/source/api/classes/get_templates.py0000644000175000017500000000057712652732202021660 0ustar tiagotiagofrom pyo import * cats = OBJECTS_TREE['PyoObjectBase']['PyoTableObject'] cats.sort() module = """%s =================================== .. module:: pyo """ template = """*%s* ----------------------------------- .. autoclass:: %s :members: """ with open("tables.rst", "w") as f: f.write(module % "Tables") for obj in cats: f.write(template % (obj, obj)) pyo/doc-sphinx/source/api/classes/opensndctrl.rst0000644000175000017500000000154612652732202021533 0ustar tiagotiagoOpen Sound Control =================================== .. module:: pyo Objects to manage values on an Open Sound Control port. OscSend takes the first value of each buffersize and send it on an OSC port. OscReceive creates and returns audio streams from the value in its input port. The audio streams of these objects are essentially intended to be controls and can't be sent to the output soundcard. *OscDataReceive* ----------------------------------- .. autoclass:: OscDataReceive :members: *OscDataSend* ----------------------------------- .. autoclass:: OscDataSend :members: *OscListReceive* ----------------------------------- .. autoclass:: OscListReceive :members: *OscReceive* ----------------------------------- .. autoclass:: OscReceive :members: *OscSend* ----------------------------------- .. autoclass:: OscSend :members: pyo/doc-sphinx/source/api/classes/tables.rst0000644000175000017500000000351612652732202020451 0ustar tiagotiagoTables =================================== .. module:: pyo Tables are one-dimension containers to keep samples (sounds, envelopes, algorithmic patterns, etc.) in memory and access them quickly. *ChebyTable* ----------------------------------- .. autoclass:: ChebyTable :members: *CosLogTable* ----------------------------------- .. autoclass:: CosLogTable :members: *CosTable* ----------------------------------- .. autoclass:: CosTable :members: *CurveTable* ----------------------------------- .. autoclass:: CurveTable :members: *DataTable* ----------------------------------- .. autoclass:: DataTable :members: *ExpTable* ----------------------------------- .. autoclass:: ExpTable :members: *HannTable* ----------------------------------- .. autoclass:: HannTable :members: *HarmTable* ----------------------------------- .. autoclass:: HarmTable :members: *LinTable* ----------------------------------- .. autoclass:: LinTable :members: *LogTable* ----------------------------------- .. autoclass:: LogTable :members: *NewTable* ----------------------------------- .. autoclass:: NewTable :members: *ParaTable* ----------------------------------- .. autoclass:: ParaTable :members: *PartialTable* ----------------------------------- .. autoclass:: PartialTable :members: *SawTable* ----------------------------------- .. autoclass:: SawTable :members: *SincTable* ----------------------------------- .. autoclass:: SincTable :members: *SndTable* ----------------------------------- .. autoclass:: SndTable :members: *SquareTable* ----------------------------------- .. autoclass:: SquareTable :members: *WinTable* ----------------------------------- .. autoclass:: WinTable :members: *AtanTable* ----------------------------------- .. autoclass:: AtanTable :members: pyo/doc-sphinx/source/api/classes/index.rst0000644000175000017500000000061112652732202020277 0ustar tiagotiagoClasses by category =============================== .. toctree:: :maxdepth: 2 server listener _core analysis arithmetic controls dynamics effects expression filters fourier pvoc generators internals matrixprocess midi opensndctrl pan pattern players randoms tableprocess triggers utils tables matrices map pyo/doc-sphinx/source/api/classes/matrices.rst0000644000175000017500000000045212652732202021002 0ustar tiagotiagoMatrices =================================== .. module:: pyo Matrices are two-dimensions containers to keep samples (sounds, envelopes, algorithmic patterns, images, etc.) in memory and access them quickly. *NewMatrix* ----------------------------------- .. autoclass:: NewMatrix :members: pyo/doc-sphinx/source/api/classes/fourier.rst0000644000175000017500000000170612652732202020651 0ustar tiagotiagoFast Fourier Transform =================================== .. module:: pyo A Fast Fourier Transform (FFT) is an efficient algorithm to compute the discrete Fourier transform (DFT) and its inverse (IFFT). The objects below can be used to perform sound processing in the spectral domain. *FFT* ----------------------------------- .. autoclass:: FFT :members: *IFFT* ----------------------------------- .. autoclass:: IFFT :members: *PolToCar* ----------------------------------- .. autoclass:: PolToCar :members: *CarToPol* ----------------------------------- .. autoclass:: CarToPol :members: *FrameAccum* ----------------------------------- .. autoclass:: FrameAccum :members: *FrameDelta* ----------------------------------- .. autoclass:: FrameDelta :members: *CvlVerb* ----------------------------------- .. autoclass:: CvlVerb :members: *Vectral* ----------------------------------- .. autoclass:: Vectral :members: pyo/doc-sphinx/source/api/classes/expression.rst0000644000175000017500000001657712652732202021411 0ustar tiagotiagoPrefix expression evaluators ============================= .. module:: pyo Prefix audio expression evaluator. This family implements a tiny functional programming language that can be used to write synthesis or signal processing algorithms. **API documentation** --------------------- This API is in alpha stage and subject to future changes! Builtin functions ----------------- **Arithmetic operators** - (+ x y) : returns the sum of two values. - (- x y) : substracts the second value to the first and returns the result. - (* x y) : returns the multiplication of two values. - (/ x y) : returns the quotient of x/y. - (^ x y) : returns x to the power y. - (% x y) : returns the floating-point remainder of x/y. - (neg x) : returns the negative of x. **Moving phase operators** - (++ x y) : increments its internal state by x and wrap around 0.0 and y. - (-- x y) : decrements its internal state by x and wrap around 0.0 and y. - (~ x y) : generates a periodic ramp from 0 to 1 with frequency x and phase y. **Conditional operators** - (< x y) : returns 1 if x is less than y, otherwise returns 0. - (<= x y) : returns 1 if x is less than or equal to y, otherwise returns 0. - (> x y) : returns 1 if x is greater than y, otherwise returns 0. - (>= x y) : returns 1 if x is greater than or equal to y, otherwise returns 0. - (== x y) : returns 1 if x is equal to y, otherwise returns 0. - (!= x y) : returns 1 if x is not equal to y, otherwise returns 0. - (if (cond) (then) (else)) : returns then for any non-zero value of cond, otherwise returns else. - (and x y) : returns 1 if both x and y are not 0, otherwise returns 0. - (or x y) : returns 1 if one of x or y are not 0, otherwise returns 0. **Trigonometric functions** - (sin x) : returns the sine of an angle of x radians. - (cos x) : returns the cosine of an angle of x radians. - (tan x) : returns the tangent of x radians. - (tanh x) : returns the hyperbolic tangent of x radians. - (atan x) : returns the principal value of the arc tangent of x, expressed in radians. - (atan2 x y) : returns the principal value of the arc tangent of y/x, expressed in radians. **Power and logarithmic functions** - (sqrt x) : returns the square root of x. - (log x) : returns the natural logarithm of x. - (log2 x) : returns the binary (base-2) logarithm of x. - (log10 x) : returns the common (base-10) logarithm of x. - (pow x y) : returns x to the power y. **Clipping functions** - (abs x) : returns the absolute value of x. - (floor x) : rounds x downward, returning the largest integral value that is not greater than x. - (ceil x) : rounds x upward, returning the smallest integral value that is not less than x. - (exp x) : returns the constant e to the power x. - (round x) : returns the integral value that is nearest to x. - (min x y) : returns the smaller of its arguments: either x or y. - (max x y) : returns the larger of its arguments: either x or y. - (wrap x) : wraps x between 0 and 1. **Random fuctions** - (randf x y) : returns a pseudo-random floating-point number in the range between x and y. - (randi x y) : returns a pseudo-random integral number in the range between x and y. **Filter functions** - (sah x y) : samples and holds x value whenever y is smaller than its previous state. - (rpole x y) : real one-pole recursive filter. returns x + last_out * y. - (rzero x y) : real one-zero non-recursive filter. returns x - last_x * y. **Constants** - (const x) : returns x. - (pi) : returns an approximated value of pi. - (twopi) : returns a constant with value pi*2. - \(e\) : returns an approximated value of e. Comments -------- A comment start with two slashs ( // ) and ends at the end of the line:: // This is a comment! Input and Output signals ------------------------ User has access to the last buffer size of input and output samples. To use samples from past input, use $x[n] notation, where n is the position from the current time. $x[0] is the current input, $x[-1] is the previous one and $x[-buffersize] is the last available input sample. To use samples from past output, use $y[n] notation, where n is the position from the current time. $y[-1] is the previous output and $y[-buffersize] is the last available output sample. Here an example of a first-order IIR lowpass filter expression:: // A first-order IIR lowpass filter + $x[0] (* (- $y[-1] $x[0]) 0.99) Defining custom functions ------------------------- The define keyword starts the definition of a custom function:: (define funcname (body)) funcname is the name used to call the function in the expression and body is the sequence of functions to execute. Arguments of the function are extracted directly from the body. They must be named $1, $2, $3, ..., $9. Example of a sine wave function:: (define osc ( sin (* (twopi) (~ $1)) ) ) // play a sine wave * (osc 440) 0.3 State variables --------------- User can create state variable with the keyword "let". This is useful to set an intermediate state to be used in multiple places in the processing chain. The syntax is:: (let #var (body)) The variable name must begin with a "#":: (let #sr 44100) (let #freq 1000) (let #coeff ( ^ (e) (/ (* (* -2 (pi)) #freq) #sr) ) ) + $x[0] (* (- $y[-1] $x[0]) #coeff) The variable is private to a function if created inside a custom function:: (let #freq 250) // global #freq variable (define osc ( (let #freq (* $1 $2)) // local #freq variable sin (* (twopi) (~ #freq)) ) ) * (+ (osc 1 #freq) (osc 2 #freq)) 0.2 State variables can be used to do 1 sample feedback if used before created. Undefined variables are initialized to 0:: (define oscloop ( (let #xsin (sin (+ (* (~ $1) (twopi)) (* #xsin $2))) // #xsin used before... ) // ... "let" statement finished! #xsin // oscloop function outputs #xsin variable ) ) * (oscloop 200 0.7) 0.3 User variables -------------- User variables are created with the keyword "var":: (var #var (init)) The variable name must begin with a "#". They are computed only at initialization, but can be changed from the python script with method calls (varname is a string and value is a float):: obj.setVar(varname, value) Library importation ------------------- Custom functions can be defined in an external file and imported with the "load" function:: (load path/to/the/file) The content of the file will be inserted where the load function is called and all functions defined inside the file will then be accessible. The path can be absolute or relative to the current working directory. Examples -------- Here is some expression examples. A first-order IIR lowpass filter:: (var #sr 44100) (var #cutoff 1000) (let #coeff (exp (/ (* (* -2 (pi)) #cutoff) #sr))) + $x[0] (* (- $y[-1] $x[0]) #coeff) A LFO'ed hyperbolic tangent distortion:: // $1 = lfo frequency, $2 = lfo depth (define lfo ( (+ (* (sin (* (twopi) (~ $1))) (- $2 1)) $2) ) ) tanh (* $x[0] (lfo .25 10)) A triangle waveform generator (use Sig(0) as input argument to bypass input):: (var #freq 440) // $1 = oscillator frequency (define triangle ( (let #ph (~ $1)) (- (* (min #ph (- 1 #ph)) 4) 1) ) ) triangle #freq **Objects** ----------- *Expr* ---------- .. autoclass:: Expr :members: pyo/doc-sphinx/source/api/classes/listener.rst0000644000175000017500000000062212652732202021017 0ustar tiagotiagoController listeners =================================== .. module:: pyo These objects can be used to create MIDI and/or OSC listeners without the need to boot ands start an audio server before receiving messages. *MidiListener* ----------------------------------- .. autoclass:: MidiListener :members: *OscListener* ----------------------------------- .. autoclass:: OscListener :members: pyo/doc-sphinx/source/api/classes/filters.rst0000644000175000017500000000502312652732202020642 0ustar tiagotiagoFilters ============================ .. module:: pyo Different kinds of audio filtering operations. An audio filter is designed to amplify, pass or attenuate (negative amplification) some frequency ranges. Common types include low-pass, which pass through frequencies below their cutoff frequencies, and progressively attenuates frequencies above the cutoff frequency. A high-pass filter does the opposite, passing high frequencies above the cutoff frequency, and progressively attenuating frequencies below the cutoff frequency. A bandpass filter passes frequencies between its two cutoff frequencies, while attenuating those outside the range. A band-reject filter, attenuates frequencies between its two cutoff frequencies, while passing those outside the 'reject' range. An all-pass filter, passes all frequencies, but affects the phase of any given sinusoidal component according to its frequency. *Biquad* ---------- .. autoclass:: Biquad :members: *Biquadx* ------------ .. autoclass:: Biquadx :members: *Biquada* ------------ .. autoclass:: Biquada :members: *EQ* ------------ .. autoclass:: EQ :members: *Tone* ------------ .. autoclass:: Tone :members: *Atone* ------------ .. autoclass:: Atone :members: *Port* ------------ .. autoclass:: Port :members: *DCBlock* ------------ .. autoclass:: DCBlock :members: *BandSplit* ------------ .. autoclass:: BandSplit :members: *FourBand* ------------ .. autoclass:: FourBand :members: *Hilbert* ------------ .. autoclass:: Hilbert :members: *Allpass* ------------ .. autoclass:: Allpass :members: *Allpass2* ------------ .. autoclass:: Allpass2 :members: *Phaser* ------------ .. autoclass:: Phaser :members: *Vocoder* ------------ .. autoclass:: Vocoder :members: *IRWinSinc* ------------ .. autoclass:: IRWinSinc :members: *IRAverage* ------------ .. autoclass:: IRAverage :members: *IRPulse* ------------ .. autoclass:: IRPulse :members: *IRFM* ------------ .. autoclass:: IRFM :members: *SVF* ------------ .. autoclass:: SVF :members: *Average* ------------ .. autoclass:: Average :members: *Reson* ------------ .. autoclass:: Reson :members: *Resonx* ------------ .. autoclass:: Resonx :members: *ButLP* ------------ .. autoclass:: ButLP :members: *ButHP* ------------ .. autoclass:: ButHP :members: *ButBP* ------------ .. autoclass:: ButBP :members: *ButBR* ------------ .. autoclass:: ButBR :members: *ComplexRes* ------------ .. autoclass:: ComplexRes :members: pyo/doc-sphinx/source/api/classes/controls.rst0000644000175000017500000000122012652732202021030 0ustar tiagotiagoControl Signals ============================ .. module:: pyo Objects designed to create parameter's control at audio rate. These objects can be used to create envelopes, line segments and conversion from python number to audio signal. The audio streams of these objects can't be sent to the output soundcard. *Fader* ---------- .. autoclass:: Fader :members: *Adsr* ------------ .. autoclass:: Adsr :members: *Linseg* ------------ .. autoclass:: Linseg :members: *Expseg* ------------ .. autoclass:: Expseg :members: *Sig* ------------ .. autoclass:: Sig :members: *SigTo* ------------ .. autoclass:: SigTo :members: pyo/doc-sphinx/source/api/constants.rst0000644000175000017500000000075712652732202017562 0ustar tiagotiagoConstants =============================== - **PYO_VERSION** : string. Current version of pyo, as a string in the format "major.minor.change". - **USE_DOUBLE** : boolean. True if using double precision (64-bit), False for single precision (32-bit). - **WITH_EXTERNALS** : boolean. True if pyo was compiled with external classes. See :ref:`compilation-flags-label`. - **SNDS_PATH** : string. Path to the pyo sound folder (located in the site-packages folder of the current Python installation. pyo/doc-sphinx/source/api/alphabetical.rst0000644000175000017500000004624212652732202020156 0ustar tiagotiagoAlphabetical class reference ======================================= .. module:: pyo - :py:class:`AToDB` : Returns the decibel equivalent of an amplitude value. - :py:class:`Abs` : Performs an absolute function on audio signal. - :py:class:`Adsr` : Attack - Decay - Sustain - Release envelope generator. - :py:class:`Allpass2` : Second-order phase shifter allpass. - :py:class:`AllpassWG` : Out of tune waveguide model with a recursive allpass network. - :py:class:`Allpass` : Delay line based allpass filter. - :py:class:`Atan2` : Computes the principal value of the arc tangent of b/a. - :py:class:`AtanTable` : Generates an arctangent transfert function. - :py:class:`Atone` : A first-order recursive high-pass filter with variable frequency response. - :py:class:`AttackDetector` : Audio signal onset detection. - :py:class:`Average` : Moving average filter. - :py:class:`Balance` : Adjust rms power of an audio signal according to the rms power of another. - :py:class:`BandSplit` : Splits an input signal into multiple frequency bands. - :py:class:`Beat` : Generates algorithmic trigger patterns. - :py:class:`Bendin` : Get the current value of the pitch bend controller. - :py:class:`Between` : Informs when an input signal is contained in a specified range. - :py:class:`Biquad` : A sweepable general purpose biquadratic digital filter. - :py:class:`Biquada` : A general purpose biquadratic digital filter (floating-point arguments). - :py:class:`Biquadx` : A multi-stages sweepable general purpose biquadratic digital filter. - :py:class:`Blit` : Band limited impulse train synthesis. - :py:class:`BrownNoise` : A brown noise generator. - :py:class:`ButBP` : A second-order Butterworth bandpass filter. - :py:class:`ButBR` : A second-order Butterworth band-reject filter. - :py:class:`ButHP` : A second-order Butterworth highpass filter. - :py:class:`ButLP` : A second-order Butterworth lowpass filter. - :py:class:`CallAfter` : Calls a Python function after a given time. - :py:class:`CarToPol` : Performs the cartesian to polar conversion. - :py:class:`Ceil` : Rounds to smallest integral value greater than or equal to the input signal. - :py:class:`Centroid` : Computes the spectral centroid of an input signal. - :py:class:`CentsToTranspo` : Returns the transposition factor equivalent of a given cents value. - :py:class:`Change` : Sends trigger that informs when input value has changed. - :py:class:`ChebyTable` : Chebyshev polynomials of the first kind. - :py:class:`Choice` : Periodically choose a new value from a user list. - :py:class:`Chorus` : 8 modulated delay lines chorus processor. - :py:class:`Clean_objects` : Stops and deletes PyoObjects after a given time. - :py:class:`Clip` : Clips a signal to a predefined limit. - :py:class:`Cloud` : Generates random triggers. - :py:class:`Compare` : Comparison object. - :py:class:`ComplexRes` : Complex one-pole resonator filter. - :py:class:`Compress` : Reduces the dynamic range of an audio signal. - :py:class:`ControlRead` : Reads control values previously stored in text files. - :py:class:`ControlRec` : Records control values and writes them in a text file. - :py:class:`Convolve` : Implements filtering using circular convolution. - :py:class:`CosLogTable` : Construct a table from logarithmic-cosine segments in breakpoint fashion. - :py:class:`CosTable` : Construct a table from cosine interpolated segments. - :py:class:`Cos` : Performs a cosine function on audio signal. - :py:class:`Count` : Counts integers at audio rate. - :py:class:`Counter` : Integer count generator. - :py:class:`CrossFM` : Cross frequency modulation generator. - :py:class:`CtlScan2` : Scan the Midi channel and controller number in input. - :py:class:`CtlScan` : Scan the Midi controller's number in input. - :py:class:`CurveTable` : Construct a table from curve interpolated segments. - :py:class:`CvlVerb` : Convolution based reverb. - :py:class:`DBToA` : Returns the amplitude equivalent of a decibel value. - :py:class:`DCBlock` : Implements the DC blocking filter. - :py:class:`DataTable` : Create an empty table ready for data recording. - :py:class:`Degrade` : Signal quality reducer. - :py:class:`Delay1` : Delays a signal by one sample. - :py:class:`Delay` : Sweepable recursive delay. - :py:class:`Denorm` : Mixes low level noise to an input signal. - :py:class:`Disto` : Arc tangent distortion. - :py:class:`Dummy` : Dummy object used to perform arithmetics on PyoObject. - :py:class:`EQ` : Equalizer filter. - :py:class:`Euclide` : Euclidean rhythm generator. - :py:class:`ExpTable` : Construct a table from exponential interpolated segments. - :py:class:`Expr` : Prefix audio expression evaluator. - :py:class:`Expr` : Prefix audio expression evaluator. - :py:class:`Expseg` : Trace a series of exponential segments between specified break-points. - :py:class:`FFT` : Fast Fourier Transform. - :py:class:`FM` : A simple frequency modulation generator. - :py:class:`FToM` : Returns the midi note equivalent to a frequency in Hz. - :py:class:`Fader` : Fadein - fadeout envelope generator. - :py:class:`Floor` : Rounds to largest integral value not greater than audio signal. - :py:class:`Follower2` : Envelope follower with different attack and release times. - :py:class:`Follower` : Envelope follower. - :py:class:`FourBand` : Splits an input signal into four frequency bands. - :py:class:`FrameAccum` : Accumulates the phase differences between successive frames. - :py:class:`FrameDelta` : Computes the phase differences between successive frames. - :py:class:`Freeverb` : Implementation of Jezar's Freeverb. - :py:class:`FreqShift` : Frequency shifting using single sideband amplitude modulation. - :py:class:`Gate` : Allows a signal to pass only when its amplitude is above a set threshold. - :py:class:`Granulator` : Granular synthesis generator. - :py:class:`Granule` : Another granular synthesis generator. - :py:class:`HannTable` : Generates Hanning window function. - :py:class:`HarmTable` : Harmonic waveform generator. - :py:class:`Harmonizer` : Generates harmonizing voices in synchrony with its audio input. - :py:class:`Hilbert` : Hilbert transform. - :py:class:`IFFT` : Inverse Fast Fourier Transform. - :py:class:`IRAverage` : Moving average filter using circular convolution. - :py:class:`IRFM` : Filters a signal with a frequency modulation spectrum using circular convolution. - :py:class:`IRPulse` : Comb-like filter using circular convolution. - :py:class:`IRWinSinc` : Windowed-sinc filter using circular convolution. - :py:class:`InputFader` : Audio streams crossfader. - :py:class:`Input` : Read from a numbered channel in an external audio signal. - :py:class:`Interp` : Interpolates between two signals. - :py:class:`Iter` : Triggers iterate over a list of values. - :py:class:`LFO` : Band-limited Low Frequency Oscillator with different wave shapes. - :py:class:`LinTable` : Construct a table from segments of straight lines in breakpoint fashion. - :py:class:`Linseg` : Trace a series of line segments between specified break-points. - :py:class:`Log10` : Performs a base 10 log function on audio signal. - :py:class:`Log2` : Performs a base 2 log function on audio signal. - :py:class:`LogTable` : Construct a table from logarithmic segments in breakpoint fashion. - :py:class:`Log` : Performs a natural log function on audio signal. - :py:class:`Lookup` : Uses table to do waveshaping on an audio signal. - :py:class:`Looper` : Crossfading looper. - :py:class:`Lorenz` : Chaotic attractor for the Lorenz system. - :py:class:`MToF` : Returns the frequency (Hz) equivalent to a midi note. - :py:class:`MToT` : Returns the transposition factor equivalent to a midi note. - :py:class:`MatrixMorph` : Morphs between multiple PyoMatrixObjects. - :py:class:`MatrixPointer` : Matrix reader with control on the 2D pointer position. - :py:class:`MatrixRecLoop` : MatrixRecLoop records samples in loop into a previously created NewMatrix. - :py:class:`MatrixRec` : MatrixRec records samples into a previously created NewMatrix. - :py:class:`Max` : Outputs the maximum of two values. - :py:class:`Metro` : Generates isochronous trigger signals. - :py:class:`MidiAdsr` : Midi triggered ADSR envelope generator. - :py:class:`MidiDelAdsr` : Midi triggered ADSR envelope generator with pre-delay. - :py:class:`Midictl` : Get the current value of a Midi controller. - :py:class:`Min` : Outputs the minimum of two values. - :py:class:`Mirror` : Reflects the signal that exceeds the `min` and `max` thresholds. - :py:class:`Mix` : Mix audio streams to arbitrary number of streams. - :py:class:`Mixer` : Audio mixer. - :py:class:`NewMatrix` : Create a new matrix ready for recording. - :py:class:`NewTable` : Create an empty table ready for recording. - :py:class:`NextTrig` : A trigger in the second stream opens a gate only for the next one in the first stream. - :py:class:`Noise` : A white noise generator. - :py:class:`NoteinRead` : Reads Notein values previously stored in text files. - :py:class:`NoteinRec` : Records Notein inputs and writes them in a text file. - :py:class:`Notein` : Generates Midi note messages. - :py:class:`OscBank` : Any number of oscillators reading a waveform table. - :py:class:`OscDataReceive` : Receives data values over a network via the Open Sound Control protocol. - :py:class:`OscDataSend` : Sends data values over a network via the Open Sound Control protocol. - :py:class:`OscListReceive` : Receives list of values over a network via the Open Sound Control protocol. - :py:class:`OscLoop` : A simple oscillator with feedback reading a waveform table. - :py:class:`OscReceive` : Receives values over a network via the Open Sound Control protocol. - :py:class:`OscSend` : Sends values over a network via the Open Sound Control protocol. - :py:class:`OscTrig` : An oscillator reading a waveform table with sample accurate reset signal. - :py:class:`Osc` : A simple oscillator reading a waveform table. - :py:class:`PVAddSynth` : Phase Vocoder additive synthesis object. - :py:class:`PVAmpMod` : Performs frequency independent amplitude modulations. - :py:class:`PVAnal` : Phase Vocoder analysis object. - :py:class:`PVBufLoops` : Phase vocoder buffer with bin independent speed playback. - :py:class:`PVBufTabLoops` : Phase vocoder buffer with bin independent speed playback. - :py:class:`PVBuffer` : Phase vocoder buffer and playback with transposition. - :py:class:`PVCross` : Performs cross-synthesis between two phase vocoder streaming object. - :py:class:`PVDelay` : Spectral delays. - :py:class:`PVFilter` : Spectral filter. - :py:class:`PVFreqMod` : Performs frequency independent frequency modulations. - :py:class:`PVGate` : Spectral gate. - :py:class:`PVMix` : Mix the most prominent components from two phase vocoder streaming objects. - :py:class:`PVMorph` : Performs spectral morphing between two phase vocoder streaming object. - :py:class:`PVMult` : Multiply magnitudes from two phase vocoder streaming object. - :py:class:`PVShift` : Spectral domain frequency shifter. - :py:class:`PVSynth` : Phase Vocoder synthesis object. - :py:class:`PVTranspose` : Transpose the frequency components of a pv stream. - :py:class:`PVVerb` : Spectral domain reverberation. - :py:class:`Pan` : Cosinus panner with control on the spread factor. - :py:class:`ParaTable` : Generates parabola window function. - :py:class:`PartialTable` : Inharmonic waveform generator. - :py:class:`Particle` : A full control granular synthesis generator. - :py:class:`Pattern` : Periodically calls a Python function. - :py:class:`PeakAmp` : Peak amplitude follower. - :py:class:`Percent` : Lets pass a certain percentage of the input triggers. - :py:class:`Phaser` : Multi-stages second-order phase shifter allpass filters. - :py:class:`Phasor` : A simple phase incrementor. - :py:class:`PinkNoise` : A pink noise generator. - :py:class:`Pointer2` : High quality table reader with control on the pointer position. - :py:class:`Pointer` : Table reader with control on the pointer position. - :py:class:`PolToCar` : Performs the polar to cartesian conversion. - :py:class:`Port` : Exponential portamento. - :py:class:`Pow` : Performs a power function on audio signal. - :py:class:`Print` : Print PyoObject's current value. - :py:class:`Programin` : Get the current value of a program change Midi controller. - :py:class:`Pulsar` : Pulsar synthesis oscillator. - :py:class:`RCOsc` : Waveform aproximation of a RC circuit. - :py:class:`RandDur` : Recursive time varying pseudo-random generator. - :py:class:`RandInt` : Periodic pseudo-random integer generator. - :py:class:`Randh` : Periodic pseudo-random generator. - :py:class:`Randi` : Periodic pseudo-random generator with interpolation. - :py:class:`RawMidi` : Raw Midi handler. - :py:class:`Record` : Writes input sound in an audio file on the disk. - :py:class:`Resample` : Realtime upsampling or downsampling of an audio signal. - :py:class:`Reson` : A second-order resonant bandpass filter. - :py:class:`Resonx` : A multi-stages second-order resonant bandpass filter. - :py:class:`Rossler` : Chaotic attractor for the Rossler system. - :py:class:`Round` : Rounds to the nearest integer value in a floating-point format. - :py:class:`SDelay` : Simple delay without interpolation. - :py:class:`SLMapDur` : SLMap with normalized values for a 'dur' slider. - :py:class:`SLMapFreq` : SLMap with normalized values for a 'freq' slider. - :py:class:`SLMapMul` : SLMap with normalized values for a 'mul' slider. - :py:class:`SLMapPan` : SLMap with normalized values for a 'pan' slider. - :py:class:`SLMapPhase` : SLMap with normalized values for a 'phase' slider. - :py:class:`SLMapQ` : SLMap with normalized values for a 'q' slider. - :py:class:`SPan` : Simple equal power panner. - :py:class:`STRev` : Stereo reverb. - :py:class:`SVF` : Fourth-order state variable filter allowing continuous change of the filter type. - :py:class:`SampHold` : Performs a sample-and-hold operation on its input. - :py:class:`SawTable` : Sawtooth waveform generator. - :py:class:`Scale` : Maps an input range of audio values to an output range. - :py:class:`Scope` : Oscilloscope - audio waveform display. - :py:class:`Score` : Calls functions by incrementation of a preformatted name. - :py:class:`Select` : Sends trigger on matching integer values. - :py:class:`Selector` : Audio selector. - :py:class:`Seq` : Generates a rhythmic sequence of trigger signals. - :py:class:`SfMarkerLooper` : AIFF with markers soundfile looper. - :py:class:`SfMarkerShuffler` : AIFF with markers soundfile shuffler. - :py:class:`SfPlayer` : Soundfile player. - :py:class:`SigTo` : Convert numeric value to PyoObject signal with portamento. - :py:class:`Sig` : Convert numeric value to PyoObject signal. - :py:class:`Sin` : Performs a sine function on audio signal. - :py:class:`SincTable` : Generates sinc window function. - :py:class:`SineLoop` : A simple sine wave oscillator with feedback. - :py:class:`Sine` : A simple sine wave oscillator. - :py:class:`SmoothDelay` : Artifact free sweepable recursive delay. - :py:class:`Snap` : Snap input values on a user's defined midi scale. - :py:class:`SndTable` : Transfers data from a soundfile into a function table. - :py:class:`Spectrum` : Spectrum analyzer and display. - :py:class:`Sqrt` : Performs a square-root function on audio signal. - :py:class:`SquareTable` : Square waveform generator. - :py:class:`SumOsc` : Discrete summation formulae to produce complex spectra. - :py:class:`SuperSaw` : Roland JP-8000 Supersaw emulator. - :py:class:`Switch` : Audio switcher. - :py:class:`TableIndex` : Table reader by sample position without interpolation. - :py:class:`TableMorph` : Morphs between multiple PyoTableObjects. - :py:class:`TablePut` : Writes values, without repetitions, from an audio stream into a DataTable. - :py:class:`TableRead` : Simple waveform table reader. - :py:class:`TableRec` : TableRec is for writing samples into a previously created NewTable. - :py:class:`TableScale` : Scales all the values contained in a PyoTableObject. - :py:class:`TableWrite` : TableWrite writes samples into a previously created NewTable. - :py:class:`Tan` : Performs a tangent function on audio signal. - :py:class:`Tanh` : Performs a hyperbolic tangent function on audio signal. - :py:class:`Thresh` : Informs when a signal crosses a threshold. - :py:class:`Timer` : Reports elapsed time between two trigs. - :py:class:`Tone` : A first-order recursive low-pass filter with variable frequency response. - :py:class:`Touchin` : Get the current value of an after-touch Midi controller. - :py:class:`TrackHold` : Performs a track-and-hold operation on its input. - :py:class:`TranspoToCents` : Returns the cents value equivalent of a transposition factor. - :py:class:`TrigBurst` : Generates a time/amplitude expandable trigger pattern. - :py:class:`TrigChoice` : Random generator from user's defined values. - :py:class:`TrigEnv` : Envelope reader generator. - :py:class:`TrigExpseg` : Exponential segments trigger. - :py:class:`TrigFunc` : Python function callback. - :py:class:`TrigLinseg` : Line segments trigger. - :py:class:`TrigRandInt` : Pseudo-random integer generator. - :py:class:`TrigRand` : Pseudo-random number generator. - :py:class:`TrigTableRec` : TrigTableRec is for writing samples into a previously created NewTable. - :py:class:`TrigVal` : Outputs a previously defined value on a trigger signal. - :py:class:`TrigXnoiseMidi` : Triggered X-class midi notes pseudo-random generator. - :py:class:`TrigXnoise` : Triggered X-class pseudo-random generator. - :py:class:`Trig` : Sends one trigger. - :py:class:`Urn` : Periodic pseudo-random integer generator without duplicates. - :py:class:`VarPort` : Convert numeric value to PyoObject signal with portamento. - :py:class:`Vectral` : Performs magnitude smoothing between successive frames. - :py:class:`Vocoder` : Applies the spectral envelope of a first sound to the spectrum of a second sound. - :py:class:`VoiceManager` : Polyphony voice manager. - :py:class:`WGVerb` : 8 delay lines mono FDN reverb. - :py:class:`Waveguide` : Basic waveguide model. - :py:class:`WinTable` : Generates different kind of windowing functions. - :py:class:`Wrap` : Wraps-around the signal that exceeds the `min` and `max` thresholds. - :py:class:`XnoiseDur` : Recursive time varying X-class pseudo-random generator. - :py:class:`XnoiseMidi` : X-class midi notes pseudo-random generator. - :py:class:`Xnoise` : X-class pseudo-random generator. - :py:class:`Yin` : Pitch tracker using the Yin algorithm. - :py:class:`ZCross` : Zero-crossing counter. pyo/doc-sphinx/source/api/index.rst0000644000175000017500000000022212652732202016640 0ustar tiagotiagoAPI Documentation =============================== .. toctree:: :maxdepth: 2 constants functions/index alphabetical classes/index pyo/doc-sphinx/source/about.rst0000644000175000017500000000257712652732202016111 0ustar tiagotiagoAbout Pyo ================= Pyo is a Python module written in C to help digital signal processing script creation. Pyo is a Python module written in C to help DSP script creation. Pyo contains classes for a wide variety of audio signal processing. With pyo, the user will be able to include signal processing chains directly in Python scripts or projects, and to manipulate them in real time through the interpreter. Tools in the pyo module offer primitives, like mathematical operations on audio signals, basic signal processing (filters, delays, synthesis generators, etc.), but also complex algorithms to create sound granulation and other creative audio manipulations. pyo supports the OSC protocol (Open Sound Control) to ease communications between softwares, and the MIDI protocol for generating sound events and controlling process parameters. pyo allows the creation of sophisticated signal processing chains with all the benefits of a mature and widely used general programming language. Pyo is developed by Olivier Bélanger < belangeo@gmail.com > For questions and comments, please subscribe to the `pyo-discuss `_ mailing list. To report a bug or to request a feature, use the `issues tracker `_ on github. Sources and binaries can be downloaded at: http://ajaxsoundstudio.com/software/pyo/ pyo/doc-sphinx/source/index.rst0000644000175000017500000000111012652732202016064 0ustar tiagotiago.. Pyo documentation master file, created by sphinx-quickstart on Thu May 16 15:35:44 2013. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Welcome to the Pyo 0.7.8 documentation =================================================== Pyo is a Python module written in C to help digital signal processing script creation. .. toctree:: :maxdepth: 1 about download compiling gettingstarted tutorials/index api/index Indices and tables ================== * :ref:`genindex` * :ref:`search` pyo/doc-sphinx/source/gettingstarted.rst0000644000175000017500000001100512652732202020011 0ustar tiagotiagoGetting Started ================================= Here is quick introduction to Pyo. It assumes you already know Python and basics about Object-oriented programming. The Pyo Server and GUI ----------------------- The first thing you need to do to use Pyo is import the pyo python module and boot the server. This audio server will open audio and midi interfaces and will be ready to send to them the audio and MIDI produced by other pyo objects. You then need to make some sound: >>> from pyo import * >>> s = Server().boot() >>> s.start() >>> a = Sine(mul=0.01).out() The `s` variable holds the Server instance, which has been booted, using the boot function. Booting the server includes opening audio and MIDI interfaces, and setting up the sample rate and number of channels, but the server will not be processing audio until its start() method is called. Then we create a Sine object, and store it in variable a, after calling its out method. The Sine class defines a Sine wave oscillator. The out method from this class connects the output of the oscillator to the server audio outputs. I have set the mul attribute of the Sine object to make sure you don't blow your ears when you play this, as the default amplitude multiplier is 1, i.e. a sine wave at the maximum amplitude before clipping! (But I'll talk about attributes later...) You can stop the server with: >>> s.stop() To interact or not to interact -------------------------------- If you tried the above script from an interactive python shell you would have heard a sine tone, but if you ran it from a python script non-interactively, you are probably asking yourself why you haven't heard anything. The reason is that the script has finished before the server has sent any audio to the outputs! So if you are using python non-interactively, the way to hear this example is: .. code-block:: python from pyo import * s = Server().boot() s.start() a = Sine(mul=0.01).out() s.gui(locals()) In the last line, you can see a very handy method from the Server class, which creates a small control GUI for the current instance. The gui method for the Server object, keeps a script running and allows you to start and stop the server, control the output volume and record to an audio file the sound generated in the server. A handy feature of the server GUI is the interpreter text box in the bottom. From it you can send commands interactively to the interpreter, to start and stop objects, create or destroy them, etc. Changing Object Characteristics ---------------------------------- The Sine class constructor is defined as: .. code-block:: python Sine(self, freq=1000, phase=0, mul=1, add=0) So you can give it a frequency, starting phase, multiplier and DC offset value when you create it. Also, if you want to do without the server gui, you can use the server method start() from your script, but you might need to use the sleep function from the time module to have your script run the server for a while if you are running Python non-interactively: .. code-block:: python from pyo import * import time s = Server().boot() a = Sine(440, 0, 0.1).out() s.start() time.sleep(1) s.stop() Notice that you can set the parameters for Sine in the order in which they are defined, but you can also give the parameters a name if you want to leave the rest at their default: .. code-block:: python a = Sine(mul=0.1).out() Once the object has been created, you can modify its attributes using the access methods. For example, to modify the frequency of the a oscillator object after it has been created you can use: .. code-block:: python a.setFreq(1000) But you can also set the attributes directly: .. code-block:: python a.freq = 1000 Chaining objects ----------------- Oscillators like the Sine class can be used as inputs to other classes, for example for frequency modulation: .. code-block:: python from pyo import * s = Server().boot() mod = Sine(freq=6, mul=50) a = Sine(freq=mod + 440, mul=0.1).out() s.gui(locals()) You can create an envelope for a sine wave like this: .. code-block:: python from pyo import * s = Server().boot() f = Adsr(attack=.01, decay=.2, sustain=.5, release=.1, dur=5, mul=.5) a = Sine(mul=f).out() f.play() s.gui(locals()) Class examples ---------------- All Classes in Pyo come with an example which shows how it can be used. To execute the example you can do: >>> from pyo import * >>> example(Harmonizer) This will show and execute the example for the Harmonizer class. pyo/embedded/0000755000175000017500000000000012652732202012407 5ustar tiagotiagopyo/embedded/puredata/0000755000175000017500000000000012652732202014214 5ustar tiagotiagopyo/embedded/puredata/pyo~-help.pd0000644000175000017500000003042612652732202016501 0ustar tiagotiago#N canvas 249 157 1013 410 10; #X obj 28 118 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 144 118 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 13 244 *~; #X obj 51 244 *~; #X obj 13 266 dac~; #X obj 72 223 hsl 128 15 0 1 0 1 empty empty master_gain -2 -8 0 10 -262144 -1 -1 12700 1; #X obj 274 233 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1; #X msg 274 253 \; pd dsp \$1; #X obj 13 69 r msg_to_pyo; #X text 161 117 play; #X obj 13 176 pyo~ 2; #X text 66 178 argument sets the number of audio ins/outs (defaults to 2).; #N canvas 1 75 824 583 resonators_example 0; #X obj 35 103 hsl 128 15 0.01 30 1 0 empty empty resonance -2 -8 0 10 -262144 -1 -1 0 0; #X floatatom 32 120 5 0 0 0 - - -, f 5; #X obj 21 530 s msg_to_pyo; #X obj 98 387 hsl 128 15 0 1 0 0 empty empty delay_time -2 -8 0 10 -262144 -1 -1 0 0; #X floatatom 95 403 5 0 0 0 - - -, f 5; #X msg 95 418 value deltime \$1; #X obj 111 454 hsl 128 15 0 1 0 0 empty empty delay_feedback -2 -8 0 10 -262144 -1 -1 0 0; #X floatatom 108 470 5 0 0 0 - - -, f 5; #X msg 108 485 value delfeed \$1; #X msg 32 136 value reson \$1; #X obj 52 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144 -1 -1 0 0; #X obj 71 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144 -1 -1 0 0; #X obj 91 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144 -1 -1 0 0; #X obj 110 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144 -1 -1 0 0; #X obj 130 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144 -1 -1 0 0; #X obj 149 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144 -1 -1 0 0; #X obj 169 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144 -1 -1 0 0; #X obj 189 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144 -1 -1 0 0; #X msg 52 306 value freqs \$1 \$2 \$3 \$4 \$5 \$6 \$7 \$8; #X obj 52 264 bondo 8 ____________; #X obj 52 285 pack f f f f f f f f; #X msg 21 66 read examples/resonators.py; #X msg 73 351 read -a examples/resonators_add_delays.py; #X text 52 159 resonator frequencies; #X text 20 30 load pyo processing file (audio signal must be given in pyo~ inputs).; #X text 168 103 adjust resonance in seconds; #X text 214 209 play with resonator frequencies; #X text 380 352 add a stereo delay taking resonator outputs as its input; #X text 234 387 adjust delay time; #X text 246 453 adjust delay feedback; #X connect 0 0 1 0; #X connect 1 0 9 0; #X connect 3 0 4 0; #X connect 4 0 5 0; #X connect 5 0 2 0; #X connect 6 0 7 0; #X connect 7 0 8 0; #X connect 8 0 2 0; #X connect 9 0 2 0; #X connect 10 0 19 0; #X connect 11 0 19 1; #X connect 12 0 19 2; #X connect 13 0 19 3; #X connect 14 0 19 4; #X connect 15 0 19 5; #X connect 16 0 19 6; #X connect 17 0 19 7; #X connect 18 0 2 0; #X connect 19 0 20 0; #X connect 19 1 20 1; #X connect 19 2 20 2; #X connect 19 3 20 3; #X connect 19 4 20 4; #X connect 19 5 20 5; #X connect 19 6 20 6; #X connect 19 7 20 7; #X connect 20 0 18 0; #X connect 21 0 2 0; #X connect 22 0 2 0; #X restore 531 36 pd resonators_example; #X msg 553 171 clear; #X obj 531 199 s msg_to_pyo; #X text 598 172 shutdown and reboot the server; #N canvas 1 75 450 300 synthesis_example 0; #N canvas 1 75 375 358 choose_sines 0; #X obj 57 77 metro 125; #X obj 78 109 hsl 128 15 0 36 0 0 empty empty empty -2 -8 0 10 -262144 -1 -1 4233 1; #X obj 127 144 hsl 128 15 0 36 0 0 empty empty empty -2 -8 0 10 -262144 -1 -1 4233 1; #X floatatom 75 125 5 0 0 0 - - -, f 5; #X floatatom 124 160 5 0 0 0 - - -, f 5; #X obj 124 209 +; #X obj 124 179 t b f; #X obj 75 144 t f f; #X obj 57 240 int; #X obj 124 232 int; #X msg 57 288 call choose \$1 \$2; #X obj 57 311 outlet; #X obj 57 54 inlet; #X obj 57 265 pack 24 24; #X text 7 3 Choose a random midi pitch between x and x+y; #X text 213 109 x; #X text 263 142 y; #X obj 224 42 loadbang; #X msg 224 64 12; #X obj 117 54 inlet speed; #X connect 0 0 8 0; #X connect 1 0 3 0; #X connect 2 0 4 0; #X connect 3 0 7 0; #X connect 4 0 6 0; #X connect 5 0 9 0; #X connect 6 0 5 0; #X connect 6 1 5 1; #X connect 7 0 8 1; #X connect 7 1 5 0; #X connect 8 0 13 0; #X connect 9 0 13 1; #X connect 10 0 11 0; #X connect 12 0 0 0; #X connect 13 0 10 0; #X connect 17 0 18 0; #X connect 18 0 1 0; #X connect 18 0 2 0; #X connect 19 0 0 1; #X restore 53 130 pd choose_sines; #X obj 41 246 s msg_to_pyo; #X obj 53 96 tgl 25 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 ; #X obj 67 172 hsl 128 15 0 0.25 0 0 empty empty brightness -2 -8 0 10 -262144 -1 -1 0 0; #X floatatom 64 188 5 0 0 0 - - -, f 5; #X msg 64 203 value feed \$1; #X obj 158 75 hsl 128 15 50 500 0 0 empty empty metro_speed -2 -8 0 10 -262144 -1 -1 0 1; #X floatatom 155 93 5 0 0 0 - - -, f 5; #X floatatom 222 186 5 0 0 0 - - -, f 5; #X msg 222 216 set amp.fadeout \$1; #X msg 281 184 set amp.dur \$1; #X floatatom 281 165 5 0 0 0 - - -, f 5; #X obj 222 132 * 0.001; #X obj 221 111 - 20; #X obj 222 165 - 0.005; #X msg 41 33 read -a examples/random_waves.py; #X text 54 80 GO!; #X connect 0 0 1 0; #X connect 2 0 0 0; #X connect 3 0 4 0; #X connect 4 0 5 0; #X connect 5 0 1 0; #X connect 6 0 7 0; #X connect 7 0 0 1; #X connect 7 0 13 0; #X connect 8 0 9 0; #X connect 9 0 1 0; #X connect 10 0 1 0; #X connect 11 0 10 0; #X connect 12 0 11 0; #X connect 12 0 14 0; #X connect 13 0 12 0; #X connect 14 0 8 0; #X connect 15 0 1 0; #X restore 531 60 pd synthesis_example; #N canvas 2 85 629 295 loop_soundfile 0; #X obj 43 42 openpanel; #X obj 43 64 t a b; #X obj 43 172 soundfiler; #X obj 236 80 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 43 20 inlet open file; #X obj 419 16 inlet start; #X obj 236 52 sel 1; #X obj 236 205 outlet~; #X obj 366 163 spigot 1; #X obj 43 128 pack s s s; #X obj 76 86 symbol \$0-table_l; #X obj 110 106 symbol \$0-table_r; #X msg 43 150 read -resize \$1 \$2 \$3; #X obj 44 200 table \$0-table_l; #X obj 44 223 table \$0-table_r; #X obj 442 206 outlet~; #X obj 236 140 tabplay~ \$0-table_l; #X obj 443 140 tabplay~ \$0-table_r; #X connect 0 0 1 0; #X connect 1 0 9 0; #X connect 1 1 10 0; #X connect 1 1 11 0; #X connect 3 0 16 0; #X connect 3 0 17 0; #X connect 4 0 0 0; #X connect 5 0 6 0; #X connect 5 0 8 1; #X connect 6 0 3 0; #X connect 8 0 16 0; #X connect 8 0 17 0; #X connect 9 0 12 0; #X connect 10 0 9 1; #X connect 11 0 9 2; #X connect 12 0 2 0; #X connect 16 0 7 0; #X connect 16 1 8 0; #X connect 17 0 15 0; #X restore 28 136 pd loop_soundfile; #X text 44 118 load file; #N canvas 302 92 532 224 conv_reverb_example 0; #X obj 24 110 hsl 128 15 0 1 0 0 empty empty balance -2 -8 0 10 -262144 -1 -1 0 0; #X floatatom 21 127 5 0 0 0 - - -, f 5; #X msg 21 143 value bal \$1; #X obj -3 170 s msg_to_pyo; #X msg -3 74 read examples/cvlverb.py; #X text -5 38 load pyo processing file (audio signal must be given in pyo~ inputs).; #X text 162 110 balance between dry and wet signal; #X connect 0 0 1 0; #X connect 1 0 2 0; #X connect 2 0 3 0; #X connect 4 0 3 0; #X restore 531 12 pd conv_reverb_example; #X text 26 96 play a soundfile to send audio signals to pyo; #N canvas 193 300 450 300 README 0; #X text 14 33 Author : Olivier Belanger; #X text 14 81 Last update : October 2015; #X text 14 57 Version : 0.7.8; #X text 15 108 pyo website : http://ajaxsoundstudio.com/software/pyo/ ; #X text 15 10 pyo~ : Embedded pyo scripting inside puredata.; #X text 15 135 pyo sources : https://github.com/belangeo/pyo; #X text 15 163 For more details about how pyo can be embedded inside an host program \, see m_pyo.h in the "embedded" folder of pyo sources. ; #X restore 406 237 pd README; #N canvas 182 106 1046 508 MESSAGES 0; #X text 20 53 read [-a] path/to/python/script; #X text 37 74 The message "read" executes the commands contained in the specified python script into the object's internal interpreter. If the "-a" flag is given \, new commands will be added to previously executed ones. Without the flag \, the server is shut down (this will erase actual processing) before the execution of the script.; #X text 18 164 value varname \$1 [\$2 \$3 ...]; #X text 19 250 set varname.attribute \$1 [\$2 \$3 ...]; #X text 19 379 call function [arg1 arg2 ...]; #X text 498 250 clear; #X text 515 271 Shutdown and reboot pyo's server. This message will erase the current processing loaded into the object.; #X text 36 185 The messsage "value" sends value(s) to a pyo's Sig or SigTo object (with variable name "varname"). Values can be pyo's variables (already created in the loaded file) \, float or list (composed of floats and/or pyo objects).; #X text 36 399 The message "call" executes the function (or object's method) with optional arguments. If the callable is a method \, the syntax will looks like:; #X text 35 439 call varname.method [arg1 arg2 ...]; #X text 36 351 set frequencies 100 200 300 400 500 600; #X text 499 56 create varname object [\$1 \$2 ...]; #X text 513 75 The message "create" creates a new python object of the class "object" \, stored in variable "varname" \, with optional initialization arguments. Arguments can be of the form freq=500 or mul=0.3 \, without spaces. Named arguments can't be followed by unamed arguments.; #X text 36 272 The messsage "set" sends value(s) to an attribute of any pyo object (with variable name "varname"). Values can be pyo's variables (already created in the loaded file) \, float or list (composed of floats and/or pyo objects). This message can be used to create a standard python variable like (to create a list of floats in variable "frequencies"):; #X text 498 312 debug \$1; #X text 515 333 If \$1 is positive \, messages to pyo will be sent through an Exception handler. This is safer and can help to debug messages to pyo but it is slower. For a faster execution \, turn off debug mode. ; #X text 498 161 midi \$1 [\$2 \$3]; #X text 512 180 The message "midi" sends a MIDI event to the object processing. Arguments are the status byte (\$1) \, the first data byte (\$2) and the second data byte (\$3). Data bytes can be ommited and defaults to 0; #X text 7 3 Here are the messages that can be used to control the internal processing of the pyo~ object.; #X text 4 31 -------------------------------------------------------- ; #X restore 406 258 pd MESSAGES; #X msg 567 321 call b.out; #X text 11 7 pyo~ object allows to execute processing with pyo (python dsp module) inside a puredata patch \, with any number of audio in/out channels.; #X obj 531 121 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 531 144 debug \$1; #X text 549 113 Verbose mode. If on \, error messages from pyo will be printed to the Pd window.; #X obj 532 347 s msg_to_pyo; #X msg 567 258 set pits 0.001 0.002 0.003 0.004; #X msg 567 279 create fr Rossler pitch=pits chaos=0.9 mul=250 add=500 ; #X msg 567 300 create b SumOsc freq=fr ratio=0.499 index=0.4 mul=0.2 ; #N canvas 669 129 722 427 midi_synth_example 0; #X obj 34 365 s msg_to_pyo; #X msg 34 56 read examples/midi_synth.py; #X msg 97 108 midi 144 72 127; #X obj 129 172 hsl 128 15 0 127 0 0 empty empty empty -2 -8 0 10 -262144 -1 -1 700 1; #X msg 126 195 midi 176 1 \$1; #X obj 448 43 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 448 63 metro 125; #X obj 448 249 makenote 127 100; #X obj 448 271 pack; #X msg 448 293 midi 144 \$1 \$2; #X msg 111 130 midi 144 72 0; #X text 212 108 note on; #X text 213 131 note off; #X text 228 196 control change (mod wheel); #X floatatom 448 228 5 0 0 0 - - -, f 5; #X obj 448 183 int; #X obj 448 161 + 0.5; #X obj 448 139 * 1.76; #X obj 448 115 random 8; #X obj 448 85 t b b; #X obj 526 115 random 3; #X obj 526 137 + 5; #X obj 526 159 * 12; #X obj 448 206 +; #X text 467 43 random melody; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 4 0; #X connect 4 0 0 0; #X connect 5 0 6 0; #X connect 6 0 19 0; #X connect 7 0 8 0; #X connect 7 1 8 1; #X connect 8 0 9 0; #X connect 9 0 0 0; #X connect 10 0 0 0; #X connect 14 0 7 0; #X connect 15 0 23 0; #X connect 16 0 15 0; #X connect 17 0 16 0; #X connect 18 0 17 0; #X connect 19 0 18 0; #X connect 19 1 20 0; #X connect 20 0 21 0; #X connect 21 0 22 0; #X connect 22 0 23 1; #X connect 23 0 14 0; #X restore 531 84 pd midi_synth_example; #X text 563 238 Create a pyo script from scratch!; #X connect 0 0 17 0; #X connect 1 0 17 1; #X connect 2 0 4 0; #X connect 3 0 4 1; #X connect 5 0 3 1; #X connect 5 0 2 1; #X connect 6 0 7 0; #X connect 8 0 10 0; #X connect 10 0 2 0; #X connect 10 1 3 0; #X connect 13 0 14 0; #X connect 17 0 10 0; #X connect 17 1 10 1; #X connect 23 0 28 0; #X connect 25 0 26 0; #X connect 26 0 14 0; #X connect 29 0 28 0; #X connect 30 0 28 0; #X connect 31 0 28 0; pyo/embedded/puredata/Makefile0000644000175000017500000004274512652732202015670 0ustar tiagotiago## Pd library template version 1.0.13 # For instructions on how to use this template, see: # http://puredata.info/docs/developer/MakefileTemplate LIBRARY_NAME = pyo~ # add your .c source files, one object per file, to the SOURCES # variable, help files will be included automatically, and for GUI # objects, the matching .tcl file too SOURCES = pyo~.c # list all pd objects (i.e. myobject.pd) files here, and their helpfiles will # be included automatically PDOBJECTS = pyo~.pd # example patches and related files, in the 'examples' subfolder EXAMPLES = # manuals and related files, in the 'manual' subfolder MANUAL = manual.txt # if you want to include any other files in the source and binary tarballs, # list them here. This can be anything from header files, test patches, # documentation, etc. README.txt and LICENSE.txt are required and therefore # automatically included EXTRA_DIST = m_pyo.h # unit tests and related files here, in the 'unittests' subfolder UNITTESTS = # added to support the multiple shared source files SHARED_SOURCE = SHARED_LIB = lib$(LIBRARY_NAME).$(SHARED_EXTENSION) #------------------------------------------------------------------------------# # # things you might need to edit if you are using other C libraries # #------------------------------------------------------------------------------# UNAME := $(shell uname -s) ifeq (MINGW,$(findstring MINGW,$(UNAME))) ALL_CFLAGS = -I"$(PD_INCLUDE)" -I.. -Wno-unused-parameter -I/c/Python27/include ALL_LDFLAGS = -lpython27 SHARED_LDFLAGS = ALL_LIBS = -L/c/Python27/libs endif ifeq ($(UNAME),Darwin) MAC_SDK = # put the path to your base SDK if you have problem to compile with the one given by python (ex: /Developer/SDKs/MacOSX10.6.sdk) ARCH_TYPE = i386 # can put multiple architectures if they are available with your environment (ex: ppc i386) ifeq ($(MAC_SDK),) PYTHONFLAGS = $(shell python-config --cflags) else PYTHONFLAGS = $(patsubst /%, $(MAC_SDK), $(shell python-config --cflags)) endif ALL_CFLAGS = -I"$(PD_INCLUDE)" -I.. -Wno-unused-parameter $(PYTHONFLAGS) ALL_LDFLAGS = $(shell python-config --ldflags) SHARED_LDFLAGS = # ALL_LIBS = $(shell python-config --libs) ALL_LIBS = -ldl -framework CoreFoundation -framework Python endif ifeq ($(UNAME),Linux) ALL_CFLAGS = -I"$(PD_INCLUDE)" -I.. -Wno-unused-parameter $(shell python-config --cflags) ALL_LDFLAGS = $(shell python-config --ldflags) SHARED_LDFLAGS = ALL_LIBS = $(shell python-config --libs) endif #------------------------------------------------------------------------------# # # you shouldn't need to edit anything below here, if we did it right :) # #------------------------------------------------------------------------------# # these can be set from outside without (usually) breaking the build CFLAGS = -Wall -W -g LDFLAGS = LIBS = # get library version from meta file LIBRARY_VERSION = $(shell sed -n 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' $(LIBRARY_NAME)-meta.pd) ALL_CFLAGS += -DPD -DVERSION='"$(LIBRARY_VERSION)"' PD_INCLUDE = $(PD_PATH)/include/pd # where to install the library, overridden below depending on platform prefix = /usr/local libdir = $(prefix)/lib pkglibdir = $(libdir)/pd-externals objectsdir = $(pkglibdir) INSTALL = install INSTALL_PROGRAM = $(INSTALL) -p -m 644 INSTALL_DATA = $(INSTALL) -p -m 644 INSTALL_DIR = $(INSTALL) -p -m 755 -d ALLSOURCES := $(SOURCES) $(SOURCES_android) $(SOURCES_cygwin) $(SOURCES_macosx) \ $(SOURCES_iphoneos) $(SOURCES_linux) $(SOURCES_windows) DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION) ORIGDIR=pd-$(LIBRARY_NAME:~=)_$(LIBRARY_VERSION) UNAME := $(shell uname -s) ifeq ($(UNAME),Darwin) CPU := $(shell uname -p) ifeq ($(CPU),arm) # iPhone/iPod Touch SOURCES += $(SOURCES_iphoneos) EXTENSION = pd_darwin SHARED_EXTENSION = dylib OS = iphoneos PD_PATH = /Applications/Pd-extended.app/Contents/Resources IPHONE_BASE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin CC=$(IPHONE_BASE)/gcc CPP=$(IPHONE_BASE)/cpp CXX=$(IPHONE_BASE)/g++ ISYSROOT = -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk IPHONE_CFLAGS = -miphoneos-version-min=3.0 $(ISYSROOT) -arch armv6 OPT_CFLAGS = -fast -funroll-loops -fomit-frame-pointer ALL_CFLAGS := $(IPHONE_CFLAGS) $(ALL_CFLAGS) ALL_LDFLAGS += -arch armv6 -bundle -undefined dynamic_lookup $(ISYSROOT) SHARED_LDFLAGS += -arch armv6 -dynamiclib -undefined dynamic_lookup $(ISYSROOT) ALL_LIBS += -lc $(LIBS_iphoneos) STRIP = strip -x DISTBINDIR=$(DISTDIR)-$(OS) else # Mac OS X SOURCES += $(SOURCES_macosx) EXTENSION = pd_darwin SHARED_EXTENSION = dylib OS = macosx PD_PATH = /Applications/Pd-extended.app/Contents/Resources OPT_CFLAGS = -ftree-vectorize -ftree-vectorizer-verbose=2 -fast # build universal 32-bit on 10.4 and 32/64 on newer ifeq ($(shell uname -r | sed 's|\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*|\1|'), 8) # FAT_FLAGS = -arch ppc -arch i386 -mmacosx-version-min=10.5 ARCHWITHOUT64 := $(filter-out x86_64,$(ARCH_TYPE)) FAT_FLAGS = $(patsubst %,-arch %, $(ARCHWITHOUT64)) -mmacosx-version-min=10.5 else # FAT_FLAGS = -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.5 FAT_FLAGS = $(patsubst %,-arch %, $(ARCH_TYPE)) -mmacosx-version-min=10.5 SOURCES += $(SOURCES_iphoneos) endif ALL_CFLAGS += $(FAT_FLAGS) -fPIC -I/sw/include # if the 'pd' binary exists, check the linking against it to aid with stripping BUNDLE_LOADER = $(shell test ! -e $(PD_PATH)/bin/pd || echo -bundle_loader $(PD_PATH)/bin/pd) ALL_LDFLAGS += $(FAT_FLAGS) -headerpad_max_install_names -bundle $(BUNDLE_LOADER) \ -undefined dynamic_lookup -L/sw/lib SHARED_LDFLAGS += $(FAT_FLAGS) -dynamiclib -undefined dynamic_lookup \ -install_name @loader_path/$(SHARED_LIB) -compatibility_version 1 -current_version 1.0 ALL_LIBS += -lc $(LIBS_macosx) STRIP = strip -x DISTBINDIR=$(DISTDIR)-$(OS) # install into ~/Library/Pd on Mac OS X since /usr/local isn't used much pkglibdir=$(HOME)/Library/Pd endif endif # Tho Android uses Linux, we use this fake uname to provide an easy way to # setup all this things needed to cross-compile for Android using the NDK ifeq ($(UNAME),ANDROID) CPU := arm SOURCES += $(SOURCES_android) EXTENSION = pd_linux SHARED_EXTENSION = so OS = android PD_PATH = /usr NDK_BASE := /usr/local/android-ndk NDK_PLATFORM_VERSION := 5 NDK_SYSROOT=$(NDK_BASE)/platforms/android-$(NDK_PLATFORM_VERSION)/arch-arm NDK_UNAME := $(shell uname -s | tr '[A-Z]' '[a-z]') NDK_TOOLCHAIN_BASE=$(NDK_BASE)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/$(NDK_UNAME)-x86 CC := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-gcc --sysroot=$(NDK_SYSROOT) OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer CFLAGS += LDFLAGS += -rdynamic -shared SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared LIBS += -lc $(LIBS_android) STRIP := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-strip \ --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),Linux) CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),GNU) # GNU/Hurd, should work like GNU/Linux for basically all externals CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),GNU/kFreeBSD) # Debian GNU/kFreeBSD, should work like GNU/Linux for basically all externals CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME))) CPU := $(shell uname -m) SOURCES += $(SOURCES_cygwin) EXTENSION = dll SHARED_EXTENSION = dll OS = cygwin PD_PATH = $(shell cygpath $$PROGRAMFILES)/pd OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += ALL_LDFLAGS += -rdynamic -shared -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc -lpd $(LIBS_cygwin) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS) endif ifeq (MINGW,$(findstring MINGW,$(UNAME))) CPU := $(shell uname -m) SOURCES += $(SOURCES_windows) EXTENSION = dll SHARED_EXTENSION = dll OS = windows PD_PATH = $(shell cd "$$PROGRAMFILES/pd" && pwd) # MinGW doesn't seem to include cc so force gcc CC=gcc OPT_CFLAGS = -O3 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -mms-bitfields ALL_LDFLAGS += -s -shared -Wl,--enable-auto-import SHARED_LDFLAGS += -shared ALL_LIBS += -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" \ -lpd -lwsock32 -lkernel32 -luser32 -lgdi32 -liberty $(LIBS_windows) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS) endif # in case somebody manually set the HELPPATCHES above HELPPATCHES ?= $(SOURCES:.c=-help.pd) $(PDOBJECTS:.pd=-help.pd) ALL_CFLAGS := $(ALL_CFLAGS) $(CFLAGS) $(OPT_CFLAGS) ALL_LDFLAGS := $(LDFLAGS) $(ALL_LDFLAGS) ALL_LIBS := $(LIBS) $(ALL_LIBS) SHARED_SOURCE ?= $(wildcard lib$(LIBRARY_NAME).c) SHARED_HEADER ?= $(shell test ! -e $(LIBRARY_NAME).h || echo $(LIBRARY_NAME).h) SHARED_LIB ?= $(SHARED_SOURCE:.c=.$(SHARED_EXTENSION)) SHARED_TCL_LIB = $(wildcard lib$(LIBRARY_NAME).tcl) .PHONY = install libdir_install single_install install-doc install-examples install-manual install-unittests clean distclean dist etags $(LIBRARY_NAME) all: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) %.o: %.c $(CC) $(ALL_CFLAGS) -o "$*.o" -c "$*.c" %.$(EXTENSION): %.o $(SHARED_LIB) $(CC) $(ALL_LDFLAGS) -o "$*.$(EXTENSION)" "$*.o" $(ALL_LIBS) $(SHARED_LIB) chmod a-x "$*.$(EXTENSION)" # this links everything into a single binary file $(LIBRARY_NAME): $(SOURCES:.c=.o) $(LIBRARY_NAME).o lib$(LIBRARY_NAME).o $(CC) $(ALL_LDFLAGS) -o $(LIBRARY_NAME).$(EXTENSION) $(SOURCES:.c=.o) \ $(LIBRARY_NAME).o lib$(LIBRARY_NAME).o $(ALL_LIBS) chmod a-x $(LIBRARY_NAME).$(EXTENSION) $(SHARED_LIB): $(SHARED_SOURCE:.c=.o) $(CC) $(SHARED_LDFLAGS) -o $(SHARED_LIB) $(SHARED_SOURCE:.c=.o) $(ALL_LIBS) install: single_install # The meta and help files are explicitly installed to make sure they are # actually there. Those files are not optional, then need to be there. libdir_install: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) install-doc install-examples install-manual install-unittests $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(SOURCES))" || (\ $(INSTALL_PROGRAM) $(SOURCES:.c=.$(EXTENSION)) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) && \ $(STRIP) $(addprefix $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/,$(SOURCES:.c=.$(EXTENSION)))) test -z "$(strip $(SHARED_LIB))" || \ $(INSTALL_DATA) $(SHARED_LIB) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(wildcard $(SOURCES:.c=.tcl)))" || \ $(INSTALL_DATA) $(wildcard $(SOURCES:.c=.tcl)) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(PDOBJECTS))" || \ $(INSTALL_DATA) $(PDOBJECTS) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(SHARED_TCL_LIB))" || \ $(INSTALL_DATA) $(SHARED_TCL_LIB) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) # install library linked as single binary single_install: $(LIBRARY_NAME) install-doc install-examples install-manual install-unittests $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_PROGRAM) $(LIBRARY_NAME).$(EXTENSION) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(STRIP) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/$(LIBRARY_NAME).$(EXTENSION) install-doc: $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(SOURCES) $(PDOBJECTS))" || \ $(INSTALL_DATA) $(HELPPATCHES) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_DATA) README.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/README.txt $(INSTALL_DATA) LICENSE.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/LICENSE.txt install-examples: test -z "$(strip $(EXAMPLES))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples && \ for file in $(EXAMPLES); do \ $(INSTALL_DATA) examples/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples; \ done install-manual: test -z "$(strip $(MANUAL))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual && \ for file in $(MANUAL); do \ $(INSTALL_DATA) manual/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual; \ done install-unittests: test -z "$(strip $(UNITTESTS))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests && \ for file in $(UNITTESTS); do \ $(INSTALL_DATA) unittests/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests; \ done clean: -rm -f -- $(SOURCES:.c=.o) $(SOURCES_LIB:.c=.o) $(SHARED_SOURCE:.c=.o) -rm -f -- $(SOURCES:.c=.$(EXTENSION)) -rm -f -- $(LIBRARY_NAME).o -rm -f -- $(LIBRARY_NAME).$(EXTENSION) -rm -f -- $(SHARED_LIB) distclean: clean -rm -f -- $(DISTBINDIR).tar.gz -rm -rf -- $(DISTBINDIR) -rm -f -- $(DISTDIR).tar.gz -rm -rf -- $(DISTDIR) -rm -f -- $(ORIGDIR).tar.gz -rm -rf -- $(ORIGDIR) $(DISTBINDIR): $(INSTALL_DIR) $(DISTBINDIR) libdir: all $(DISTBINDIR) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTBINDIR) $(INSTALL_DATA) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) $(DISTBINDIR) $(INSTALL_DATA) $(HELPPATCHES) $(DISTBINDIR) test -z "$(strip $(EXTRA_DIST))" || \ $(INSTALL_DATA) $(EXTRA_DIST) $(DISTBINDIR) # tar --exclude-vcs -czpf $(DISTBINDIR).tar.gz $(DISTBINDIR) $(DISTDIR): $(INSTALL_DIR) $(DISTDIR) $(ORIGDIR): $(INSTALL_DIR) $(ORIGDIR) dist: $(DISTDIR) $(INSTALL_DATA) Makefile $(DISTDIR) $(INSTALL_DATA) README.txt $(DISTDIR) $(INSTALL_DATA) LICENSE.txt $(DISTDIR) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTDIR) test -z "$(strip $(ALLSOURCES))" || \ $(INSTALL_DATA) $(ALLSOURCES) $(DISTDIR) test -z "$(strip $(wildcard $(ALLSOURCES:.c=.tcl)))" || \ $(INSTALL_DATA) $(wildcard $(ALLSOURCES:.c=.tcl)) $(DISTDIR) test -z "$(strip $(wildcard $(LIBRARY_NAME).c))" || \ $(INSTALL_DATA) $(LIBRARY_NAME).c $(DISTDIR) test -z "$(strip $(SHARED_HEADER))" || \ $(INSTALL_DATA) $(SHARED_HEADER) $(DISTDIR) test -z "$(strip $(SHARED_SOURCE))" || \ $(INSTALL_DATA) $(SHARED_SOURCE) $(DISTDIR) test -z "$(strip $(SHARED_TCL_LIB))" || \ $(INSTALL_DATA) $(SHARED_TCL_LIB) $(DISTDIR) test -z "$(strip $(PDOBJECTS))" || \ $(INSTALL_DATA) $(PDOBJECTS) $(DISTDIR) test -z "$(strip $(HELPPATCHES))" || \ $(INSTALL_DATA) $(HELPPATCHES) $(DISTDIR) test -z "$(strip $(EXTRA_DIST))" || \ $(INSTALL_DATA) $(EXTRA_DIST) $(DISTDIR) test -z "$(strip $(EXAMPLES))" || \ $(INSTALL_DIR) $(DISTDIR)/examples && \ for file in $(EXAMPLES); do \ $(INSTALL_DATA) examples/$$file $(DISTDIR)/examples; \ done test -z "$(strip $(MANUAL))" || \ $(INSTALL_DIR) $(DISTDIR)/manual && \ for file in $(MANUAL); do \ $(INSTALL_DATA) manual/$$file $(DISTDIR)/manual; \ done test -z "$(strip $(UNITTESTS))" || \ $(INSTALL_DIR) $(DISTDIR)/unittests && \ for file in $(UNITTESTS); do \ $(INSTALL_DATA) unittests/$$file $(DISTDIR)/unittests; \ done tar --exclude-vcs -czpf $(DISTDIR).tar.gz $(DISTDIR) # make a Debian source package dpkg-source: debclean make distclean dist mv $(DISTDIR) $(ORIGDIR) tar --exclude-vcs -czpf ../$(ORIGDIR).orig.tar.gz $(ORIGDIR) rm -f -- $(DISTDIR).tar.gz rm -rf -- $(DISTDIR) $(ORIGDIR) cd .. && dpkg-source -b $(LIBRARY_NAME) etags: TAGS TAGS: $(wildcard $(PD_INCLUDE)/*.h) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) etags $(wildcard $(PD_INCLUDE)/*.h) etags -a *.h $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) etags -a --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl showsetup: @echo "CC: $(CC)" @echo "CFLAGS: $(CFLAGS)" @echo "LDFLAGS: $(LDFLAGS)" @echo "LIBS: $(LIBS)" @echo "ALL_CFLAGS: $(ALL_CFLAGS)" @echo "ALL_LDFLAGS: $(ALL_LDFLAGS)" @echo "ALL_LIBS: $(ALL_LIBS)" @echo "PD_INCLUDE: $(PD_INCLUDE)" @echo "PD_PATH: $(PD_PATH)" @echo "objectsdir: $(objectsdir)" @echo "LIBRARY_NAME: $(LIBRARY_NAME)" @echo "LIBRARY_VERSION: $(LIBRARY_VERSION)" @echo "SOURCES: $(SOURCES)" @echo "SHARED_HEADER: $(SHARED_HEADER)" @echo "SHARED_SOURCE: $(SHARED_SOURCE)" @echo "SHARED_LIB: $(SHARED_LIB)" @echo "SHARED_TCL_LIB: $(SHARED_TCL_LIB)" @echo "PDOBJECTS: $(PDOBJECTS)" @echo "ALLSOURCES: $(ALLSOURCES)" @echo "ALLSOURCES TCL: $(wildcard $(ALLSOURCES:.c=.tcl))" @echo "UNAME: $(UNAME)" @echo "CPU: $(CPU)" @echo "pkglibdir: $(pkglibdir)" @echo "DISTDIR: $(DISTDIR)" @echo "ORIGDIR: $(ORIGDIR)" pyo/embedded/puredata/pyo~-meta.pd0000644000175000017500000000026312652732202016473 0ustar tiagotiago#N canvas 15 49 200 200 10; #N canvas 25 49 420 300 META 1; #X text 13 41 NAME pyo~; #X text 10 25 AUTHOR belangeo@gmail.com; #X text 10 10 VERSION 0.1; #X restore 10 10 pd META; pyo/embedded/puredata/pyo~.c0000644000175000017500000002063112652732202015367 0ustar tiagotiago#include #include #include "Python.h" #include "m_pyo.h" static t_class *pyo_tilde_class; typedef struct _pyo_tilde { t_object obj; t_sample f; int debug; int bs; int add; int chnls; float sr; char *file; t_sample **in; t_sample **out; int id; /* pyo server id */ float *inbuf; /* pyo input buffer */ float *outbuf; /* pyo output buffer */ char *msg; /* preallocated string to construct message for pyo */ void (*callback)(int); /* pointer to pyo embedded server callback */ PyThreadState *interp; /* Python thread state linked to this sub interpreter */ } t_pyo_tilde; t_int *pyo_tilde_perform(t_int *w) { int i, j, n; t_pyo_tilde *x = (t_pyo_tilde *)(w[1]); /* pointer to instance struct */ n = (int)(w[2]); /* vector size */ t_sample **in = x->in; t_sample **out = x->out; for (i=0; ichnls; j++) { x->inbuf[i*x->chnls+j] = in[j][i]; } } (*x->callback)(x->id); for (i=0; ichnls; j++) { out[j][i] = x->outbuf[i*x->chnls+j]; } } return (w+3); } void pyo_tilde_dsp(t_pyo_tilde *x, t_signal **sp) { int i, err; t_sample **dummy = x->in; for (i=0; ichnls; i++) *dummy++ = sp[i]->s_vec; dummy = x->out; for (i=x->chnls; ichnls*2; i++) *dummy++ = sp[i]->s_vec; /* reset pyo only if sampling rate or buffer size have changed */ if ((float)sp[0]->s_sr != x->sr || (int)sp[0]->s_n != x->bs) { x->sr = (float)sp[0]->s_sr; x->bs = (int)sp[0]->s_n; pyo_set_server_params(x->interp, x->sr, x->bs); if (x->file != NULL) { err = pyo_exec_file(x->interp, x->file, x->msg, x->add); if (err) { post("Unable to open file < %s >", x->file); x->file = NULL; } } } dsp_add(pyo_tilde_perform, 2, x, sp[0]->s_n); } void *pyo_tilde_new(t_floatarg f) { int i; t_pyo_tilde *x = (t_pyo_tilde *)pd_new(pyo_tilde_class); x->chnls = (f) ? f : 2; x->bs = 64; x->sr = 44100.0; x->file = NULL; x->add = 0; x->debug = 0; /* create signal inlets (first is done in pyo_tilde_setup) */ for (i=1; ichnls; i++) inlet_new(&x->obj, &x->obj.ob_pd, &s_signal, &s_signal); /* create signal outlets */ for (i=0; ichnls; i++) outlet_new(&x->obj, &s_signal); x->in = (t_sample **)getbytes(x->chnls * sizeof(t_sample **)); x->out = (t_sample **)getbytes(x->chnls * sizeof(t_sample **)); x->msg = (char *)getbytes(262144 * sizeof(char *)); for (i=0; ichnls; i++) x->in[i] = x->out[i] = 0; x->interp = pyo_new_interpreter(x->sr, x->bs, x->chnls); x->inbuf = (float *)pyo_get_input_buffer_address(x->interp); x->outbuf = (float *)pyo_get_output_buffer_address(x->interp); x->callback = (void *)pyo_get_embedded_callback_address(x->interp); x->id = pyo_get_server_id(x->interp); return (void *)x; } void pyo_tilde_free(t_pyo_tilde *x) { freebytes(x->in, sizeof(x->in)); freebytes(x->out, sizeof(x->out)); freebytes(x->msg, sizeof(x->msg)); pyo_end_interpreter(x->interp); } void pyo_tilde_set_value(t_pyo_tilde *x, char *att, int argc, t_atom *argv) { int err, bracket = 0; char fchar[32]; t_symbol *c = atom_getsymbol(argv); argc--; argv++; sprintf(x->msg, "%s%s=", c->s_name, att); if (argc > 1) { strcat(x->msg, "["); bracket = 1; } while (argc-- > 0) { if (argv->a_type == A_SYMBOL) { strcat(x->msg, atom_getsymbol(argv)->s_name); } else if (argv->a_type == A_FLOAT) { sprintf(fchar, "%.6f", atom_getfloat(argv)); strcat(x->msg, fchar); } if (argc > 0) strcat(x->msg, ","); argv++; } if (bracket) strcat(x->msg, "]"); err = pyo_exec_statement(x->interp, x->msg, x->debug); if (err) post("pyo~: %s", x->msg); } void pyo_tilde_value(t_pyo_tilde *x, t_symbol *s, int argc, t_atom *argv) { char *att = ".value"; pyo_tilde_set_value(x, att, argc, argv); } void pyo_tilde_set(t_pyo_tilde *x, t_symbol *s, int argc, t_atom *argv) { char *att = ""; pyo_tilde_set_value(x, att, argc, argv); } void pyo_tilde_create(t_pyo_tilde *x, t_symbol *s, int argc, t_atom *argv) { int err; char *varname, *object; char fchar[32]; t_symbol *c = atom_getsymbol(argv); varname = c->s_name; argc--; argv++; c = atom_getsymbol(argv); object = c->s_name; argc--; argv++; sprintf(x->msg, "%s=%s(", varname, object); while (argc-- > 0) { if (argv->a_type == A_SYMBOL) { strcat(x->msg, atom_getsymbol(argv)->s_name); } else if (argv->a_type == A_FLOAT) { sprintf(fchar, "%f", atom_getfloat(argv)); strcat(x->msg, fchar); } if (argc > 0) strcat(x->msg, ","); argv++; } strcat(x->msg, ")"); err = pyo_exec_statement(x->interp, x->msg, x->debug); if (err) post("pyo~: %s", x->msg); } void pyo_tilde_midi_event(t_pyo_tilde *x, t_symbol *s, int argc, t_atom *argv) { int status, data1 = 0, data2 = 0; if (argc > 0) status = (int)atom_getfloat(argv); if (argc > 1) data1 = (int)atom_getfloat(++argv); if (argc > 2) data2 = (int)atom_getfloat(++argv); pyo_add_midi_event(x->interp, status, data1, data2); } void pyo_tilde_clear(t_pyo_tilde *x) { pyo_server_reboot(x->interp); } void pyo_tilde_debug(t_pyo_tilde *x, t_float debug) { x->debug = debug <= 0 ? 0 : 1; } void pyo_tilde_read(t_pyo_tilde *x, t_symbol *s, int argc, t_atom *argv) { int err; switch (argc) { case 1: x->add = 0; x->file = atom_getsymbol(argv)->s_name; break; case 2: x->add = strcmp(atom_getsymbol(argv++)->s_name, "-a") == 0 ? 1 : 0; x->file = atom_getsymbol(argv)->s_name; break; } if (pyo_is_server_started(x->interp)) { err = pyo_exec_file(x->interp, x->file, x->msg, x->add); if (err) { post("Unable to open file < %s >", x->file); x->file = NULL; } } } void pyo_tilde_call(t_pyo_tilde *x, t_symbol *s, int argc, t_atom *argv) { int err; char fchar[32]; sprintf(x->msg, "%s(", atom_getsymbol(argv)->s_name); argc--; argv++; while (argc-- > 0) { if (argv->a_type == A_SYMBOL) { strcat(x->msg, atom_getsymbol(argv)->s_name); } else if (argv->a_type == A_FLOAT) { sprintf(fchar, "%f", atom_getfloat(argv)); strcat(x->msg, fchar); } if (argc > 0) strcat(x->msg, ", "); argv++; } strcat(x->msg, ")"); err = pyo_exec_statement(x->interp, x->msg, x->debug); if (err) post("pyo~: %s", x->msg); } void pyo_tilde_setup(void) { pyo_tilde_class = class_new(gensym("pyo~"), (t_newmethod)pyo_tilde_new, (t_method)pyo_tilde_free, sizeof(t_pyo_tilde), CLASS_DEFAULT, A_DEFFLOAT, 0); class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_dsp, gensym("dsp"), 0); class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_clear, gensym("clear"), 0); class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_value, gensym("value"), A_GIMME, 0); /* send value(s) to a Sig or SigTo object */ class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_set, gensym("set"), A_GIMME, 0); /* send value(s) to any object's attribute */ class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_read, gensym("read"), A_GIMME, 0); /* read a script file */ class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_call, gensym("call"), A_GIMME, 0); /* call a function or a method */ class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_create, gensym("create"), A_GIMME, 0); /* create a python object */ class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_midi_event, gensym("midi"), A_GIMME, 0); /* create a python object */ class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_debug, gensym("debug"), A_DEFFLOAT, 0); /* set the debug (verbose) mode */ CLASS_MAINSIGNALIN(pyo_tilde_class, t_pyo_tilde, f); } pyo/embedded/puredata/examples/0000755000175000017500000000000012652732202016032 5ustar tiagotiagopyo/embedded/puredata/examples/resonators.py0000644000175000017500000000027412652732202020606 0ustar tiagotiagoreson = SigTo(2, 0.005, 2) freqs = SigTo([50,100,150,200,250,300,350,400], time=0.2) ins = Input([0,1]) wgs = Waveguide(ins, freq=freqs, dur=reson, mul=0.1) wgss = wgs.mix(2) wgss.out() pyo/embedded/puredata/examples/random_waves.py0000644000175000017500000000060012652732202021065 0ustar tiagotiagoimport random feed = SigTo(0.05, 0.05, 0.05) amp = Fader(fadein=0.005, fadeout=0.12, dur=0.125) syn = SineLoop(freq=[500,510], feedback=feed, mul=amp*amp) rev = WGVerb(syn, feedback=0.85, cutoff=4500, bal=0.1).out() def choose(a, b): x = random.randint(a, b) deg = [0,2,3,5,7,8,11][x%7] hz = midiToHz(deg + (x / 7 * 12 + 36)) syn.freq = [hz,hz*1.005] amp.play() pyo/embedded/puredata/examples/cvlverb.py0000644000175000017500000000014712652732202020051 0ustar tiagotiagobal = SigTo(0.25, 0.005, 0.25) ins = Input([0,1]) dist = CvlVerb(ins, size=512, bal=bal, mul=0.3).out()pyo/embedded/puredata/examples/resonators_add_delays.py0000644000175000017500000000017412652732202022756 0ustar tiagotiagodeltime = SigTo(.25, 0.005, 0.25) delfeed = SigTo(.25, 0.005, 0.25) dd = Delay(wgs, delay=deltime, feedback=delfeed).out(0) pyo/embedded/puredata/examples/midi_synth.py0000644000175000017500000000063312652732202020555 0ustar tiagotiagonotein = Notein(scale=1) modwheel = Midictl(1, maxscale=0.2) amp = MidiAdsr(notein["velocity"], 0.001, 0.01, 0.7, 0.05) lfo = Sine(5, mul=modwheel, add=1) synth1 = RCOsc(freq=notein["pitch"]*lfo, sharp=0.75, mul=amp) synth2 = RCOsc(freq=notein["pitch"]*lfo*1.01, sharp=0.74, mul=amp) stereo = Mix([synth1.mix(1), synth2.mix(1)], voices=2) rev = STRev(stereo, inpos=[0,1], revtime=2, bal=0.25, mul=0.2).out() pyo/embedded/m_pyo.h0000644000175000017500000002664112652732202013714 0ustar tiagotiago#include #include "Python.h" #ifndef __m_pyo_h_ #if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) extern "C" { #endif /* ** Creates a new python interpreter and starts a pyo server in it. ** Each instance of pyo, in order to be fully independent of other ** instances, must be started in its own interpreter. An instance ** can be an object in a programming language or a plugin in a daw. ** ** arguments: ** sr : float, host sampling rate. ** bufsize : int, host buffer size. ** chnls : int, number of in/out channels of the pyo server. ** ** returns the new python thread's interpreter state. */ inline PyThreadState * pyo_new_interpreter(float sr, int bufsize, int chnls) { char msg[64]; PyThreadState *interp; if(!Py_IsInitialized()) { Py_Initialize(); PyEval_InitThreads(); PyEval_ReleaseLock(); } PyEval_AcquireLock(); /* get the GIL */ interp = Py_NewInterpreter(); /* add a new sub-interpreter */ PyRun_SimpleString("from pyo import *"); sprintf(msg, "_s_ = Server(%f, %d, %d, 1, 'embedded')", sr, chnls, bufsize); PyRun_SimpleString(msg); PyRun_SimpleString("_s_.boot()\n_s_.start()\n_s_.setServer()"); PyRun_SimpleString("_in_address_ = _s_.getInputAddr()"); PyRun_SimpleString("_out_address_ = _s_.getOutputAddr()"); PyRun_SimpleString("_server_id_ = _s_.getServerID()"); PyRun_SimpleString("_emb_callback_ = _s_.getEmbedICallbackAddr()"); PyEval_ReleaseThread(interp); return interp; } /* ** Returns the address, as unsigned long, of the pyo input buffer. ** Used this function if pyo's audio samples resolution is 32-bit. ** ** arguments: ** interp : pointer, pointer to the targeted Python thread state. ** ** returns an "unsigned long" that should be recast to a float pointer. */ inline unsigned long pyo_get_input_buffer_address(PyThreadState *interp) { PyObject *module, *obj; char *address; unsigned long uadd; PyEval_AcquireThread(interp); module = PyImport_AddModule("__main__"); obj = PyObject_GetAttrString(module, "_in_address_"); address = PyString_AsString(obj); uadd = strtoul(address, NULL, 0); PyEval_ReleaseThread(interp); return uadd; } /* ** Returns the address, as unsigned long long, of the pyo input buffer. ** Used this function if pyo's audio samples resolution is 64-bit. ** ** arguments: ** interp : pointer, pointer to the targeted Python thread state. ** ** returns an "unsigned long long" that should be recast to a double pointer. */ inline unsigned long long pyo_get_input_buffer_address_64(PyThreadState *interp) { PyObject *module, *obj; char *address; unsigned long long uadd; PyEval_AcquireThread(interp); module = PyImport_AddModule("__main__"); obj = PyObject_GetAttrString(module, "_in_address_"); address = PyString_AsString(obj); uadd = strtoull(address, NULL, 0); PyEval_ReleaseThread(interp); return uadd; } /* ** Returns the address, as unsigned long, of the pyo output buffer. ** Used this function if pyo's audio samples resolution is 32-bit. ** ** arguments: ** interp : pointer, pointer to the targeted Python thread state. ** ** returns an "unsigned long" that should be recast to a float pointer. */ inline unsigned long pyo_get_output_buffer_address(PyThreadState *interp) { PyObject *module, *obj; char *address; unsigned long uadd; PyEval_AcquireThread(interp); module = PyImport_AddModule("__main__"); obj = PyObject_GetAttrString(module, "_out_address_"); address = PyString_AsString(obj); uadd = strtoul(address, NULL, 0); PyEval_ReleaseThread(interp); return uadd; } /* ** Returns the address, as unsigned long, of the pyo embedded callback. ** This callback must be called in the host's perform routine whenever ** pyo has to compute a new buffer of samples. ** ** arguments: ** interp : pointer, pointer to the targeted Python thread state. ** ** returns an "unsigned long" that should be recast to a void pointer. ** ** The callback should be called with the server id (int) as argument. ** ** Prototype: ** void (*callback)(int); */ inline unsigned long pyo_get_embedded_callback_address(PyThreadState *interp) { PyObject *module, *obj; char *address; unsigned long uadd; PyEval_AcquireThread(interp); module = PyImport_AddModule("__main__"); obj = PyObject_GetAttrString(module, "_emb_callback_"); address = PyString_AsString(obj); uadd = strtoul(address, NULL, 0); PyEval_ReleaseThread(interp); return uadd; } /* ** Returns the pyo server id of this thread, as an integer. ** The id must be pass as argument to the callback function. ** ** arguments: ** interp : pointer, pointer to the targeted Python thread state. ** ** returns an integer. */ inline int pyo_get_server_id(PyThreadState *interp) { PyObject *module, *obj; int id; PyEval_AcquireThread(interp); module = PyImport_AddModule("__main__"); obj = PyObject_GetAttrString(module, "_server_id_"); id = PyInt_AsLong(obj); PyEval_ReleaseThread(interp); return id; } /* ** Closes the interpreter linked to the thread state given as argument. ** ** arguments: ** interp : pointer, pointer to the targeted Python thread state. */ inline void pyo_end_interpreter(PyThreadState *interp) { /* Old method (causing segfault) */ //PyEval_AcquireThread(interp); //Py_EndInterpreter(interp); //PyEval_ReleaseLock(); /* New method (seems to be ok) */ PyThreadState_Swap(interp); PyThreadState_Swap(NULL); PyThreadState_Clear(interp); PyThreadState_Delete(interp); } /* ** Shutdown and reboot the pyo server while keeping current in/out buffers. ** ** arguments: ** interp : pointer, pointer to the targeted Python thread state. */ inline void pyo_server_reboot(PyThreadState *interp) { PyEval_AcquireThread(interp); PyRun_SimpleString("_s_.setServer()\n_s_.stop()\n_s_.shutdown()"); PyRun_SimpleString("_s_.boot(newBuffer=False).start()"); PyEval_ReleaseThread(interp); } /* ** Reboot the pyo server with new sampling rate and buffer size. ** ** arguments: ** interp : pointer, pointer to the targeted Python thread state. ** sr : float, host sampling rate. ** bufsize : int, host buffer size. */ inline void pyo_set_server_params(PyThreadState *interp, float sr, int bufsize) { char msg[64]; PyEval_AcquireThread(interp); PyRun_SimpleString("_s_.setServer()\n_s_.stop()\n_s_.shutdown()"); sprintf(msg, "_s_.setSamplingRate(%f)", sr); PyRun_SimpleString(msg); sprintf(msg, "_s_.setBufferSize(%d)", bufsize); PyRun_SimpleString(msg); PyRun_SimpleString("_s_.boot(newBuffer=False).start()"); PyEval_ReleaseThread(interp); } /* ** Add a MIDI event in the pyo server processing chain. When used in ** an embedded framework, pyo can't open MIDI ports by itself. MIDI ** inputs must be handled by the host program and sent to pyo with ** the pyo_add_midi_event function. ** ** arguments: ** interp : pointer, pointer to the targeted Python thread state. ** status : int, status byte. ** data1 : int, first data byte. ** data2 : int, second data byte. */ inline void pyo_add_midi_event(PyThreadState *interp, int status, int data1, int data2) { char msg[64]; PyEval_AcquireThread(interp); sprintf(msg, "_s_.addMidiEvent(%d, %d, %d)", status, data1, data2); PyRun_SimpleString(msg); PyEval_ReleaseThread(interp); } /* ** Returns 1 if the pyo server is started for the given thread, ** Otherwise returns 0. ** ** arguments: ** interp : pointer, pointer to the targeted Python thread state. */ inline int pyo_is_server_started(PyThreadState *interp) { int started; PyObject *module, *obj; PyEval_AcquireThread(interp); PyRun_SimpleString("started = _s_.getIsStarted()"); module = PyImport_AddModule("__main__"); obj = PyObject_GetAttrString(module, "started"); started = PyInt_AsLong(obj); PyEval_ReleaseThread(interp); return started; } /* ** Execute a python script "file" in the given thread's interpreter (interp). ** A pre-allocated string "msg" must be given to create the python command ** used for error handling. An integer "add" is needed to indicate if the ** pyo server should be reboot or not. ** ** arguments: ** interp : pointer, pointer to the targeted Python thread state. ** file : char *, filename to execute as a python script. The file is first ** searched in the current working directory. If not found, ** the module will try to open it as an absolute path. ** msg : char *, pre-allocated string used to create the python command ** used for error handling. ** add, int, if positive, the commands in the file will be added to whatever ** is already running in the pyo server. If 0, the server will be ** shutdown and reboot before executing the file. */ inline int pyo_exec_file(PyThreadState *interp, const char *file, char *msg, int add) { int ok, err = 0; PyObject *module, *obj; PyEval_AcquireThread(interp); sprintf(msg, "import os\n_ok_ = os.path.isfile('./%s')", file); PyRun_SimpleString(msg); sprintf(msg, "if not _ok_:\n _ok_ = os.path.isfile('%s')", file); PyRun_SimpleString(msg); module = PyImport_AddModule("__main__"); obj = PyObject_GetAttrString(module, "_ok_"); ok = PyInt_AsLong(obj); if (ok) { sprintf(msg, "try:\n execfile('./%s')\nexcept:\n execfile('%s')", file, file); if (!add) { PyRun_SimpleString("_s_.setServer()\n_s_.stop()\n_s_.shutdown()"); PyRun_SimpleString("_s_.boot(newBuffer=False).start()"); } PyRun_SimpleString(msg); } else err = 1; PyEval_ReleaseThread(interp); return err; } /* ** Execute a python statement "msg" in the thread's interpreter "interp". ** If "debug" is true, the statement will be executed in a try - except ** block. The error message, if any, will be write back in the *msg ** pointer and the function will return 1. If no error occured, the ** function returned 0. If debug is false, the statement is executed ** without any error checking (unsafe but faster). ** ** arguments: ** interp : pointer, pointer to the targeted Python thread state. ** msg : char *, pointer to a string containing the statement to execute. ** In debug mode, if an error occured, the output log will ** be write back in this string. ** debug, int, if positive, the commands will be executed in a try-except ** statement. If 0, there will be no error checking, which is ** much faster. */ inline int pyo_exec_statement(PyThreadState *interp, char *msg, int debug) { int err = 0; if (debug) { PyObject *module, *obj; char pp[26] = "_error_=None\ntry:\n "; memmove(msg + strlen(pp), msg, strlen(msg)+1); memmove(msg, pp, strlen(pp)); strcat(msg, "\nexcept Exception, _e_:\n _error_=str(_e_)"); PyEval_AcquireThread(interp); PyRun_SimpleString(msg); module = PyImport_AddModule("__main__"); obj = PyObject_GetAttrString(module, "_error_"); if (obj != Py_None) { strcpy(msg, PyString_AsString(obj)); err = 1; } PyEval_ReleaseThread(interp); } else { PyEval_AcquireThread(interp); PyRun_SimpleString(msg); PyEval_ReleaseThread(interp); } return err; } #if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) } #endif #define __m_pyo_h_ #endif /* __m_pyo_h_ */ pyo/embedded/juceplugin/0000755000175000017500000000000012652732202014554 5ustar tiagotiagopyo/embedded/juceplugin/PyoClass.h0000644000175000017500000000235712652732202016471 0ustar tiagotiago#ifndef PYOCLASS_H_INCLUDED #define PYOCLASS_H_INCLUDED #include "m_pyo.h" #include "../JuceLibraryCode/JuceHeader.h" typedef int callPtr(int); class Pyo { public: ~Pyo(); void setup(int nChannels, int bufferSize, int sampleRate); void process(AudioSampleBuffer& buffer); void clear(); int loadfile(const char *file, int add); int loadfile(const String &file, int add); int exec(const char *msg); int exec(const String &msg); int value(const char *name, float value); int value(const String &name, float value); int value(const char *name, float *value, int len); int value(const String &name, float *value, int len); int set(const char *name, float value); int set(const String &name, float value); int set(const char *name, float *value, int len); int set(const String &name, float *value, int len); private: int nChannels; int bufferSize; int sampleRate; PyThreadState *interpreter; float *pyoInBuffer; float *pyoOutBuffer; callPtr *pyoCallback; int pyoId; char pyoMsg[262144]; }; #endif // PYOCLASS_H_INCLUDED pyo/embedded/juceplugin/test.py0000644000175000017500000000051712652732202016110 0ustar tiagotiagoimport random # Get the input sound and apply a stereo delay on it. feed = SigTo(0, 0.05, 0) freq = SigTo(0.1, 0.05, 0.1) freq_sc = Scale(freq, 0, 1, 100, 10000, 4) st_input = Input([0,1]) st_filter = ButBP(st_input, freq_sc) st_delay = Delay(st_filter, delay=[random.uniform(.1, .9) for i in range(2)], feedback=feed).out() pyo/embedded/juceplugin/README0000644000175000017500000001324212652732202015436 0ustar tiagotiagoIntroduction on how to use pyo inside a Juce audio plugin. ========================================================== To use pyo inside a Juce audio plugin, first you need a working install of pyo on your system. After installing pyo, you can move on and create a Juce audio plugin project. ------------------------------------------------------------------------------ Step 1 - Create an Audio Plug-In project with the Introjucer. ------------------------------------------------------------------------------ Step 2 - Add pyo files to your project. You only need to copy these files in your project "Source" folder: - from this folder: PyoClass.cpp PyoClass.h - from the folder "embedded": m_pyo.h ------------------------------------------------------------------------------ Step 3 - Make sure that your project includes flags for compiling and linking against Python. Within the Introjucer, you can set extra flags in the "Config" tab. For example, on linux, if you select "Linux Makefile", you can add extra compiler and linker flags. Add these in the specific fields: Extra linker flags : `python-config --ldflags` Extra compiler flags : `python-config --cflags` ------------------------------------------------------------------------------ Step 4 - Make sure that your project links to the Steinberg's VST SDK. VST SDK can be freely downloaded from Steinberg web site: http://www.steinberg.net/en/company/developers/ Enter the path in the field "VST Folder" in the export configuration. ------------------------------------------------------------------------------ Step 5 - Create a python file, named "stereoDelay.py", with these lines in it: # Retrieve the stereo input of the plugin. st_input = Input([0,1]) # Parameters to change. dtime = SigTo(.5, 0.05, .5) feed = SigTo(.5, 0.05, .5) # Simple process. Stereo delay -> reverb. st_delay = SmoothDelay(st_input, delay=dtime, feedback=feed) st_rev = WGVerb(st_delay, feedback=0.8, cutoff=4000, bal=0.25).out() Save "stereoDelay.py" in the "Source" folder, add it to the project in the Introjucer and ensure that the option "Add to Binary Resources" is checked. Save your project. This should add two files, "BinaryData.h" and "BinaryData.cpp", in the "JuceLibraryCode" folder. ------------------------------------------------------------------------------ Step 6 - Edit Source/PluginProcessor.h - Include PyoClass definition: #include "PyoClass.h" - Add a Pyo object to the public attributes of the XXXAudioProcessor class: Pyo pyo; ------------------------------------------------------------------------------ Step 7 - Edit Source/PluginProcessor.cpp - Add these line to XXXAudioProcessor::prepareToPlay method: pyo.setup(getNumOutputChannels(), samplesPerBlock, sampleRate); pyo.exec(BinaryData::stereoDelay_py); - Replace the content of XXXAudioProcessor::processBlock method with this line: pyo.process(buffer); ------------------------------------------------------------------------------ Here you go! Compile, Run and Enjoy! Adding GUI controls to your plugin ================================== Now, we will add two sliders to control the delay time and the feedback of our process. ------------------------------------------------------------------------------ Step 8 - Edit Source/PluginEditor.h - Add the inheritance to Slider::Listener to your XXXAudioProcessorEditor class definition: class XXXAudioProcessorEditor : public AudioProcessorEditor, private Slider::Listener - Add the default callback function in the public attributes of the class: void sliderValueChanged(Slider* slider) override; - Create two sliders in the public attributes of the class: Slider p1; Slider p2; ------------------------------------------------------------------------------ Step 9 - Edit Source/PluginEditor.cpp - Set the sliders properties in the editor constructor function named XXXAudioProcessorEditor::XXXAudioProcessorEditor (this is the first function in the PluginEditor.cpp file). Add these lines at the end of the function: // these define the parameters of our slider object p1.setSliderStyle(Slider::LinearBarVertical); p1.setRange(0.0, 1.0, 0.01); p1.setTextBoxStyle(Slider::NoTextBox, false, 90, 0); p1.setPopupDisplayEnabled(true, this); p1.setTextValueSuffix(" Delay Time"); p1.setValue(0.5); p1.addListener(this); // this function adds the slider to the editor addAndMakeVisible(&p1); p2.setSliderStyle(Slider::LinearBarVertical); p2.setRange(0.0, 1.0, 0.01); p2.setTextBoxStyle(Slider::NoTextBox, false, 90, 0); p2.setPopupDisplayEnabled(true, this); p2.setTextValueSuffix(" Delay Feedback"); p2.setValue(0.5); p2.addListener(this); addAndMakeVisible(&p2); - Set the size and position of the sliders. Add these lines in XXXAudioProcessorEditor::resized() function: p1.setBounds(40, 30, 20, getHeight() - 60); p2.setBounds(70, 30, 20, getHeight() - 60); ------------------------------------------------------------------------------ Step 10 - Connect the sliders to the audio proces - At the end of the file PluginEditor.cpp, create the slider's callback function which will pass the values to the audio processing objects: void XXXAudioProcessorEditor::sliderValueChanged (Slider* slider) { processor.pyo.value("dtime", p1.getValue()); processor.pyo.value("feed", p2.getValue()); } ------------------------------------------------------------------------------ That's it! Compile and Run... Documentation ============= For a complete description of functions used to communicate with the pyo embedded processes, see documentation comments in the file PyoClass.cpp. (c) 2015 - belangeo pyo/embedded/juceplugin/PyoClass.cpp0000644000175000017500000001736112652732202017025 0ustar tiagotiago#include "PyoClass.h" /* ** Creates a python interpreter and initialize a pyo server inside it. ** This function must be called, once per Pyo object, before any other ** calls. ** ** arguments: ** nChannels : int, number of in/out channels. ** bufferSize : int, number of samples per buffer. ** sampleRate : int, sample rate frequency. ** ** All arguments should be equal to the host audio settings. */ void Pyo::setup(int _nChannels, int _bufferSize, int _sampleRate) { nChannels = _nChannels; bufferSize = _bufferSize; sampleRate = _sampleRate; interpreter = pyo_new_interpreter(sampleRate, bufferSize, nChannels); pyoInBuffer = reinterpret_cast(pyo_get_input_buffer_address(interpreter)); pyoOutBuffer = reinterpret_cast(pyo_get_output_buffer_address(interpreter)); pyoCallback = reinterpret_cast(pyo_get_embedded_callback_address(interpreter)); pyoId = pyo_get_server_id(interpreter); pyo_set_server_params(interpreter, sampleRate, bufferSize); } /* ** Terminates this object's interpreter. */ Pyo::~Pyo() { pyo_end_interpreter(interpreter); } /* ** This function fills pyo's input buffers with new samples, tells pyo to ** process a buffer of samples and fills the host's output buffer with new ** samples. Should be called once per process block, inside the host's ** processBlock function. ** ** arguments: ** buffer : AudioSampleBuffer&, Juce's audio buffer object. */ void Pyo::process(AudioSampleBuffer& buffer) { for (int channel = 0; channel < nChannels; ++channel) { float *channelData = buffer.getWritePointer(channel); for (int sample = 0; sample < bufferSize; sample++) { pyoInBuffer[sample*nChannels+channel] = channelData[sample]; } } pyoCallback(pyoId); for (int channel = 0; channel < nChannels; ++channel) { float *channelData = buffer.getWritePointer(channel); for (int sample = 0; sample < bufferSize; sample++) { channelData[sample] = pyoOutBuffer[sample*nChannels+channel]; } } } /* ** Execute a python script "file" in the objectès thread's interpreter. ** An integer "add" is needed to indicate if the pyo server should be ** reboot or not. ** ** arguments: ** file : const char * or const String &, ** filename to execute as a python script. The file is first ** searched in the current working directory. If not found, ** the module will try to open it as an absolute path. ** add, int, if positive, the commands in the file will be added to whatever ** is already running in the pyo server. If 0, the server will be ** cleared before executing the file. */ int Pyo::loadfile(const char *file, int add) { return pyo_exec_file(interpreter, file, pyoMsg, add); } int Pyo::loadfile(const String &file, int add) { return pyo_exec_file(interpreter, file.getCharPointer(), pyoMsg, add); } /* ** Sends a numerical value to an existing Sig or SigTo object. ** ** arguments: ** name : const char * or const String &, ** variable name of the object. ** value : float, value to be assigned. ** ** Example: ** ** inside the script file: ** ** freq = SigTo(value=440, time=0.1, init=440) ** ** Inside OpenFrameworks (for a Pyo object named `pyo`): ** ** pyo.value("freq", 880); */ int Pyo::value(const char *name, float value) { sprintf(pyoMsg, "%s.value=%f", name, value); return pyo_exec_statement(interpreter, pyoMsg, 0); } int Pyo::value(const String &name, float value) { const char * _name = name.getCharPointer(); sprintf(pyoMsg, "%s.value=%f", _name, value); return pyo_exec_statement(interpreter, pyoMsg, 0); } /* ** Sends an array of numerical values to an existing Sig or SigTo object. ** ** arguments: ** name : const char * or const String &, ** variable name of the object. ** value : float *, array of floats. ** len : int, number of elements in the array. ** ** Example: ** ** inside the script file: ** ** freq = SigTo(value=[100,200,300,400], time=0.1, init=[100,200,300,400]) ** ** Inside OpenFrameworks (for a Pyo object named `pyo`): ** ** float frequencies[4] = {150, 250, 350, 450}; ** pyo.value("freq", frequencies, 4); */ int Pyo::value(const char *name, float *value, int len) { char fchar[32]; sprintf(pyoMsg, "%s.value=[", name); for (int i=0; i(pyo_get_input_buffer_address(interpreter)); pyoOutBuffer = reinterpret_cast(pyo_get_output_buffer_address(interpreter)); pyoCallback = reinterpret_cast(pyo_get_embedded_callback_address(interpreter)); pyoId = pyo_get_server_id(interpreter); } /* ** Terminates this object's interpreter. */ Pyo::~Pyo() { pyo_end_interpreter(interpreter); } /* ** This function fills pyo's input buffers with new samples. Should be called ** once per process block, inside the host's audioIn function. ** ** arguments: ** *buffer : float *, float pointer pointing to the host's input buffers. */ void Pyo::fillin(float *buffer) { for (int i=0; i<(bufferSize*nChannels); i++) pyoInBuffer[i] = buffer[i]; } /* ** This function tells pyo to process a buffer of samples and fills the host's ** output buffer with new samples. Should be called once per process block, ** inside the host's audioOut function. ** ** arguments: ** *buffer : float *, float pointer pointing to the host's output buffers. */ void Pyo::process(float *buffer) { pyoCallback(pyoId); for (int i=0; i<(bufferSize*nChannels); i++) buffer[i] = pyoOutBuffer[i]; } /* ** Execute a python script "file" in the objectès thread's interpreter. ** An integer "add" is needed to indicate if the pyo server should be ** reboot or not. ** ** arguments: ** file : char *, filename to execute as a python script. The file is first ** searched in the current working directory. If not found, ** the module will try to open it as an absolute path. ** add, int, if positive, the commands in the file will be added to whatever ** is already running in the pyo server. If 0, the server will be ** cleared before executing the file. */ int Pyo::loadfile(const char *file, int add) { return pyo_exec_file(interpreter, file, pyoMsg, add); } /* ** Sends a numerical value to an existing Sig or SigTo object. ** ** arguments: ** name : const char *, variable name of the object. ** value : float, value to be assigned. ** ** Example: ** ** inside the script file: ** ** freq = SigTo(value=440, time=0.1, init=440) ** ** Inside OpenFrameworks (for a Pyo object named `pyo`): ** ** pyo.value("freq", 880); */ int Pyo::value(const char *name, float value) { sprintf(pyoMsg, "%s.value=%f", name, value); return pyo_exec_statement(interpreter, pyoMsg, 0); } /* ** Sends an array of numerical values to an existing Sig or SigTo object. ** ** arguments: ** name : const char *, variable name of the object. ** value : float *, array of floats. ** len : int, number of elements in the array. ** ** Example: ** ** inside the script file: ** ** freq = SigTo(value=[100,200,300,400], time=0.1, init=[100,200,300,400]) ** ** Inside OpenFrameworks (for a Pyo object named `pyo`): ** ** float frequencies[4] = {150, 250, 350, 450}; ** pyo.value("freq", frequencies, 4); */ int Pyo::value(const char *name, float *value, int len) { char fchar[32]; sprintf(pyoMsg, "%s.value=[", name); for (int i=0; i Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . pyo/src/0000755000175000017500000000000012652732202011445 5ustar tiagotiagopyo/src/engine/0000755000175000017500000000000012652732202012712 5ustar tiagotiagopyo/src/engine/servermodule.c0000644000175000017500000031611712652732202015603 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include #include #include #include #include #include #include "structmember.h" #include "portaudio.h" #include "portmidi.h" #include "porttime.h" #include "sndfile.h" #include "streammodule.h" #include "pyomodule.h" #include "servermodule.h" #define MAX_NBR_SERVER 256 static Server *my_server[MAX_NBR_SERVER]; static int serverID = 0; static PyObject *Server_shut_down(Server *self); static PyObject *Server_stop(Server *self); static void Server_process_gui(Server *server); static void Server_process_time(Server *server); static inline void Server_process_buffers(Server *server); static int Server_start_rec_internal(Server *self, char *filename); /* random objects count and multiplier to assign different seed to each instance. */ #define num_rnd_objs 29 int rnd_objs_count[num_rnd_objs] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int rnd_objs_mult[num_rnd_objs] = {1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069, 2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,2153,2161,2179,2203,2207}; #ifdef USE_COREAUDIO static int coreaudio_stop_callback(Server *self); #endif void Server_error(Server *self, char * format, ...) { // Errors should indicate failure to execute a request if (self->verbosity & 1) { char buffer[256]; va_list args; va_start (args, format); vsprintf (buffer,format, args); va_end (args); printf("%s",buffer); } } void Server_message(Server *self, char * format, ...) { // Messages should print useful or relevant information, or information requested by the user if (self->verbosity & 2) { char buffer[256]; va_list args; va_start (args, format); vsprintf (buffer,format, args); va_end (args); printf("%s",buffer); } } void Server_warning(Server *self, char * format, ...) { // Warnings should be used when an unexpected or unusual choice was made by pyo #ifndef NO_MESSAGES if (self->verbosity & 4) { char buffer[256]; va_list args; va_start (args, format); vsprintf (buffer,format, args); va_end (args); printf("%s",buffer); } #endif } void Server_debug(Server *self, char * format, ...) { // Debug messages should print internal information which might be necessary for debugging internal conditions. if (self->verbosity & 8) { char buffer[256]; va_list args; va_start (args, format); vsprintf (buffer,format, args); va_end (args); printf("%s",buffer); } } /* Portmidi get input events */ static void portmidiGetEvents(Server *self) { int i; PmError result; PmEvent buffer; for (i=0; imidiin_count; i++) { do { result = Pm_Poll(self->midiin[i]); if (result) { if (Pm_Read(self->midiin[i], &buffer, 1) == pmBufferOverflow) continue; self->midiEvents[self->midi_count++] = buffer; } } while (result); } } /* Portaudio stuff */ static void portaudio_assert(PaError ecode, const char* cmdName) { if (ecode != paNoError) { const char* eText = Pa_GetErrorText(ecode); if (!eText) { eText = "???"; } printf("portaudio error in %s: %s\n", cmdName, eText); Pa_Terminate(); } } /* Portaudio callback function */ static int pa_callback_interleaved( const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *arg ) { float *out = (float *)outputBuffer; Server *server = (Server *) arg; assert(framesPerBuffer == server->bufferSize); int i, j, bufchnls, index1, index2; /* avoid unused variable warnings */ (void) timeInfo; (void) statusFlags; if (server->withPortMidi == 1) { portmidiGetEvents(server); } if (server->duplex == 1) { float *in = (float *)inputBuffer; bufchnls = server->ichnls + server->input_offset; for (i=0; ibufferSize; i++) { index1 = i * server->ichnls; index2 = i * bufchnls + server->input_offset; for (j=0; jichnls; j++) { server->input_buffer[index1+j] = (MYFLT)in[index2+j]; } } } Server_process_buffers(server); bufchnls = server->nchnls + server->output_offset; for (i=0; ibufferSize; i++) { index1 = i * server->nchnls; index2 = i * bufchnls + server->output_offset; for (j=0; jnchnls; j++) { out[index2+j] = (float) server->output_buffer[index1+j]; } } server->midi_count = 0; #ifdef _OSX_ if (server->server_stopped == 1) return paComplete; else #endif return paContinue; } static int pa_callback_nonInterleaved( const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *arg ) { float **out = (float **)outputBuffer; Server *server = (Server *) arg; assert(framesPerBuffer == server->bufferSize); int i, j; /* avoid unused variable warnings */ (void) timeInfo; (void) statusFlags; if (server->withPortMidi == 1) { portmidiGetEvents(server); } if (server->duplex == 1) { float **in = (float **)inputBuffer; for (i=0; ibufferSize; i++) { for (j=0; jichnls; j++) { server->input_buffer[(i*server->ichnls)+j] = (MYFLT)in[j+server->input_offset][i]; } } } Server_process_buffers(server); for (i=0; ibufferSize; i++) { for (j=0; jnchnls; j++) { out[j+server->output_offset][i] = (float) server->output_buffer[(i*server->nchnls)+j]; } } server->midi_count = 0; #ifdef _OSX_ if (server->server_stopped == 1) return paComplete; else #endif return paContinue; } #ifdef USE_JACK /* Jack callbacks */ static int jack_callback (jack_nframes_t nframes, void *arg) { int i, j; Server *server = (Server *) arg; assert(nframes == server->bufferSize); jack_default_audio_sample_t *in_buffers[server->ichnls], *out_buffers[server->nchnls]; if (server->withPortMidi == 1) { portmidiGetEvents(server); } PyoJackBackendData *be_data = (PyoJackBackendData *) server->audio_be_data; for (i = 0; i < server->ichnls; i++) { in_buffers[i] = jack_port_get_buffer (be_data->jack_in_ports[i+server->input_offset], server->bufferSize); } for (i = 0; i < server->nchnls; i++) { out_buffers[i] = jack_port_get_buffer (be_data->jack_out_ports[i+server->output_offset], server->bufferSize); } /* jack audio data is not interleaved */ if (server->duplex == 1) { for (i=0; ibufferSize; i++) { for (j=0; jichnls; j++) { server->input_buffer[(i*server->ichnls)+j] = (MYFLT) in_buffers[j][i]; } } } Server_process_buffers(server); for (i=0; ibufferSize; i++) { for (j=0; jnchnls; j++) { out_buffers[j][i] = (jack_default_audio_sample_t) server->output_buffer[(i*server->nchnls)+j]; } } server->midi_count = 0; return 0; } static int jack_srate_cb (jack_nframes_t nframes, void *arg) { Server *s = (Server *) arg; s->samplingRate = (double) nframes; Server_debug(s, "The sample rate is now %lu.\n", (unsigned long) nframes); return 0; } static int jack_bufsize_cb (jack_nframes_t nframes, void *arg) { Server *s = (Server *) arg; s->bufferSize = (int) nframes; Server_debug(s, "The buffer size is now %lu.\n", (unsigned long) nframes); return 0; } static void jack_error_cb (const char *desc) { printf("JACK error: %s\n", desc); } static void jack_shutdown_cb (void *arg) { Server *s = (Server *) arg; Server_shut_down(s); Server_warning(s, "JACK server shutdown. Pyo Server shut down.\n"); } #endif #ifdef USE_COREAUDIO /* Coreaudio callbacks */ OSStatus coreaudio_input_callback(AudioDeviceID device, const AudioTimeStamp* inNow, const AudioBufferList* inInputData, const AudioTimeStamp* inInputTime, AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime, void* defptr) { int i, j, bufchnls, servchnls, off1chnls, off2chnls; Server *server = (Server *) defptr; (void) outOutputData; const AudioBuffer* inputBuf = inInputData->mBuffers; float *bufdata = (float*)inputBuf->mData; bufchnls = inputBuf->mNumberChannels; servchnls = server->ichnls < bufchnls ? server->ichnls : bufchnls; for (i=0; ibufferSize; i++) { off1chnls = i*bufchnls+server->input_offset; off2chnls = i*servchnls; for (j=0; jinput_buffer[off2chnls+j] = (MYFLT)bufdata[off1chnls+j]; } } return kAudioHardwareNoError; } OSStatus coreaudio_output_callback(AudioDeviceID device, const AudioTimeStamp* inNow, const AudioBufferList* inInputData, const AudioTimeStamp* inInputTime, AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime, void* defptr) { int i, j, bufchnls, servchnls, off1chnls, off2chnls; Server *server = (Server *) defptr; (void) inInputData; if (server->withPortMidi == 1) { portmidiGetEvents(server); } Server_process_buffers(server); AudioBuffer* outputBuf = outOutputData->mBuffers; bufchnls = outputBuf->mNumberChannels; servchnls = server->nchnls < bufchnls ? server->nchnls : bufchnls; float *bufdata = (float*)outputBuf->mData; for (i=0; ibufferSize; i++) { off1chnls = i*bufchnls+server->output_offset; off2chnls = i*servchnls; for(j=0; joutput_buffer[off2chnls+j]; } } server->midi_count = 0; return kAudioHardwareNoError; } int coreaudio_stop_callback(Server *self) { OSStatus err = kAudioHardwareNoError; if (self->duplex == 1) { err = AudioDeviceStop(self->input, coreaudio_input_callback); if (err != kAudioHardwareNoError) { Server_error(self, "Input AudioDeviceStop failed %d\n", (int)err); return -1; } } err = AudioDeviceStop(self->output, coreaudio_output_callback); if (err != kAudioHardwareNoError) { Server_error(self, "Output AudioDeviceStop failed %d\n", (int)err); return -1; } self->server_started = 0; return 0; } #endif static int offline_process_block(Server *arg) { Server *server = (Server *) arg; Server_process_buffers(server); return 0; } /* Server audio backend init functions */ int Server_pa_init(Server *self) { PaError err; PaStreamParameters outputParameters; PaStreamParameters inputParameters; PaDeviceIndex n, inDevice, outDevice; const PaDeviceInfo *deviceInfo; PaHostApiIndex hostIndex; const PaHostApiInfo *hostInfo; PaHostApiTypeId hostId; PaSampleFormat sampleFormat; PaStreamCallback *streamCallback; err = Pa_Initialize(); portaudio_assert(err, "Pa_Initialize"); n = Pa_GetDeviceCount(); if (n < 0) { portaudio_assert(n, "Pa_GetDeviceCount"); } PyoPaBackendData *be_data = (PyoPaBackendData *) malloc(sizeof(PyoPaBackendData *)); self->audio_be_data = (void *) be_data; if (self->output == -1) outDevice = Pa_GetDefaultOutputDevice(); /* default output device */ else outDevice = (PaDeviceIndex) self->output; /* selected output device */ if (self->input == -1) inDevice = Pa_GetDefaultInputDevice(); /* default input device */ else inDevice = (PaDeviceIndex) self->input; /* selected input device */ /* Retrieve host api id and define sample and callback format*/ deviceInfo = Pa_GetDeviceInfo(outDevice); hostIndex = deviceInfo->hostApi; hostInfo = Pa_GetHostApiInfo(hostIndex); hostId = hostInfo->type; if (hostId == paASIO) { Server_debug(self, "Portaudio uses non-interleaved callback.\n"); sampleFormat = paFloat32 | paNonInterleaved; streamCallback = pa_callback_nonInterleaved; } else if (hostId == paALSA) { Server_debug(self, "Portaudio uses interleaved callback.\n"); Server_debug(self, "Using ALSA, if no input/output devices are specified, force to devices 0.\n"); if (self->input == -1 && self->output == -1) { self->input = self->output = 0; inDevice = outDevice = (PaDeviceIndex) 0; } sampleFormat = paFloat32; streamCallback = pa_callback_interleaved; } else { Server_debug(self, "Portaudio uses interleaved callback.\n"); sampleFormat = paFloat32; streamCallback = pa_callback_interleaved; } /* setup output and input streams */ memset(&outputParameters, 0, sizeof(outputParameters)); outputParameters.device = outDevice; outputParameters.channelCount = self->nchnls + self->output_offset; outputParameters.sampleFormat = sampleFormat; outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; if (self->duplex == 1) { memset(&inputParameters, 0, sizeof(inputParameters)); inputParameters.device = inDevice; inputParameters.channelCount = self->ichnls + self->input_offset; inputParameters.sampleFormat = sampleFormat; inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency ; inputParameters.hostApiSpecificStreamInfo = NULL; } if (self->input == -1 && self->output == -1) { if (self->duplex == 1) err = Pa_OpenDefaultStream(&be_data->stream, self->ichnls + self->input_offset, self->nchnls + self->output_offset, sampleFormat, self->samplingRate, self->bufferSize, streamCallback, (void *) self); else err = Pa_OpenDefaultStream(&be_data->stream, 0, self->nchnls + self->output_offset, sampleFormat, self->samplingRate, self->bufferSize, streamCallback, (void *) self); } else { if (self->duplex == 1) err = Pa_OpenStream(&be_data->stream, &inputParameters, &outputParameters, self->samplingRate, self->bufferSize, paNoFlag, streamCallback, (void *) self); else err = Pa_OpenStream(&be_data->stream, (PaStreamParameters *) NULL, &outputParameters, self->samplingRate, self->bufferSize, paNoFlag, streamCallback, (void *) self); } portaudio_assert(err, "Pa_OpenStream"); if (err < 0) { Server_error(self, "Portaudio error: %s", Pa_GetErrorText(err)); return -1; } return 0; } int Server_pa_deinit(Server *self) { PaError err; PyoPaBackendData *be_data = (PyoPaBackendData *) self->audio_be_data; if (Pa_IsStreamActive(be_data->stream) || ! Pa_IsStreamStopped(be_data->stream)) { self->server_started = 0; err = Pa_AbortStream(be_data->stream); portaudio_assert(err, "Pa_AbortStream"); } err = Pa_CloseStream(be_data->stream); portaudio_assert(err, "Pa_CloseStream"); err = Pa_Terminate(); portaudio_assert(err, "Pa_Terminate"); free(self->audio_be_data); return err; } int Server_pa_start(Server *self) { PaError err; PyoPaBackendData *be_data = (PyoPaBackendData *) self->audio_be_data; if (Pa_IsStreamActive(be_data->stream) || ! Pa_IsStreamStopped(be_data->stream)) { err = Pa_AbortStream(be_data->stream); portaudio_assert(err, "Pa_AbortStream"); } err = Pa_StartStream(be_data->stream); portaudio_assert(err, "Pa_StartStream"); return err; } int Server_pa_stop(Server *self) { PaError err; PyoPaBackendData *be_data = (PyoPaBackendData *) self->audio_be_data; if (Pa_IsStreamActive(be_data->stream) || ! Pa_IsStreamStopped(be_data->stream)) { #ifndef _OSX_ err = Pa_AbortStream(be_data->stream); portaudio_assert(err, "Pa_AbortStream"); #endif } self->server_started = 0; self->server_stopped = 1; return 0; } #ifdef USE_JACK int Server_jack_autoconnect (Server *self) { const char **ports; int i, j, num = 0, ret = 0; PyoJackBackendData *be_data = (PyoJackBackendData *) self->audio_be_data; if (self->jackautoin) { if ((ports = jack_get_ports (be_data->jack_client, "system", NULL, JackPortIsOutput)) == NULL) { Server_error(self, "Jack: Cannot find any physical capture ports called 'system'\n"); ret = -1; } i=0; while(ports[i]!=NULL && be_data->jack_in_ports[i] != NULL){ if (jack_connect (be_data->jack_client, ports[i], jack_port_name(be_data->jack_in_ports[i]))) { Server_error(self, "Jack: cannot connect input ports to 'system'\n"); ret = -1; } i++; } free (ports); } if (self->jackautoout) { if ((ports = jack_get_ports (be_data->jack_client, "system", NULL, JackPortIsInput)) == NULL) { Server_error(self, "Jack: Cannot find any physical playback ports called 'system'\n"); ret = -1; } i=0; while(ports[i]!=NULL && be_data->jack_out_ports[i] != NULL){ if (jack_connect (be_data->jack_client, jack_port_name (be_data->jack_out_ports[i]), ports[i])) { Server_error(self, "Jack: cannot connect output ports to 'system'\n"); ret = -1; } i++; } free (ports); } num = PyList_Size(self->jackAutoConnectInputPorts); if (num > 0) { for (j=0; jjack_client, PyString_AsString(PyList_GetItem(self->jackAutoConnectInputPorts, j)), NULL, JackPortIsOutput)) == NULL) { Server_error(self, "Jack: cannot connect input ports to %s\n", PyString_AsString(PyList_GetItem(self->jackAutoConnectInputPorts, j))); } else { i = 0; while(ports[i] != NULL && be_data->jack_in_ports[i] != NULL){ if (jack_connect (be_data->jack_client, ports[i], jack_port_name (be_data->jack_in_ports[i]))) { Server_error(self, "Jack: cannot connect input ports\n"); ret = -1; } i++; } free (ports); } } } num = PyList_Size(self->jackAutoConnectOutputPorts); if (num > 0) { for (j=0; jjack_client, PyString_AsString(PyList_GetItem(self->jackAutoConnectOutputPorts, j)), NULL, JackPortIsInput)) == NULL) { Server_error(self, "Jack: cannot connect output ports to %s\n", PyString_AsString(PyList_GetItem(self->jackAutoConnectOutputPorts, j))); } else { i = 0; while(ports[i] != NULL && be_data->jack_out_ports[i] != NULL){ if (jack_connect (be_data->jack_client, jack_port_name (be_data->jack_out_ports[i]), ports[i])) { Server_error(self, "Jack: cannot connect output ports\n"); ret = -1; } i++; } free (ports); } } } return ret; } int Server_jack_init (Server *self) { char client_name[32]; char name[16]; const char *server_name = "server"; jack_options_t options = JackNullOption; jack_status_t status; int sampleRate = 0; int bufferSize = 0; int nchnls = 0; int total_nchnls = 0; int index = 0; int ret = 0; assert(self->audio_be_data == NULL); PyoJackBackendData *be_data = (PyoJackBackendData *) malloc(sizeof(PyoJackBackendData *)); self->audio_be_data = (void *) be_data; be_data->jack_in_ports = (jack_port_t **) calloc(self->ichnls + self->input_offset, sizeof(jack_port_t *)); be_data->jack_out_ports = (jack_port_t **) calloc(self->nchnls + self->output_offset, sizeof(jack_port_t *)); strncpy(client_name,self->serverName, 32); be_data->jack_client = jack_client_open (client_name, options, &status, server_name); if (be_data->jack_client == NULL) { Server_error(self, "Jack error: Unable to create JACK client\n"); if (status & JackServerFailed) { Server_debug(self, "Jack error: jack_client_open() failed, " "status = 0x%2.0x\n", status); } return -1; } if (status & JackServerStarted) { Server_warning(self, "JACK server started.\n"); } if (strcmp(self->serverName, jack_get_client_name(be_data->jack_client)) ) { strcpy(self->serverName, jack_get_client_name(be_data->jack_client)); Server_warning(self, "Jack name `%s' assigned\n", self->serverName); } sampleRate = jack_get_sample_rate (be_data->jack_client); if (sampleRate != self->samplingRate) { self->samplingRate = (double)sampleRate; Server_warning(self, "Sample rate set to Jack engine sample rate: %" PRIu32 "\n", sampleRate); } else { Server_debug(self, "Jack engine sample rate: %" PRIu32 "\n", sampleRate); } if (sampleRate <= 0) { Server_error(self, "Invalid Jack engine sample rate."); jack_client_close (be_data->jack_client); return -1; } bufferSize = jack_get_buffer_size(be_data->jack_client); if (bufferSize != self->bufferSize) { self->bufferSize = bufferSize; Server_warning(self, "Buffer size set to Jack engine buffer size: %" PRIu32 "\n", bufferSize); } else { Server_debug(self, "Jack engine buffer size: %" PRIu32 "\n", bufferSize); } nchnls = total_nchnls = self->ichnls + self->input_offset; while (nchnls-- > 0) { index = total_nchnls - nchnls - 1; ret = sprintf(name, "input_%i", index + 1); if (ret > 0) { be_data->jack_in_ports[index] = jack_port_register (be_data->jack_client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); } if ((be_data->jack_in_ports[index] == NULL)) { Server_error(self, "Jack: no more JACK input ports available\n"); return -1; } } nchnls = total_nchnls = self->nchnls + self->output_offset; while (nchnls-- > 0) { index = total_nchnls - nchnls - 1; ret = sprintf(name, "output_%i", index + 1); if (ret > 0) { be_data->jack_out_ports[index] = jack_port_register (be_data->jack_client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); } if ((be_data->jack_out_ports[index] == NULL)) { Server_error(self, "Jack: no more JACK output ports available\n"); return -1; } } jack_set_error_function (jack_error_cb); jack_set_sample_rate_callback(be_data->jack_client, jack_srate_cb, (void *) self); jack_on_shutdown (be_data->jack_client, jack_shutdown_cb, (void *) self); jack_set_buffer_size_callback (be_data->jack_client, jack_bufsize_cb, (void *) self); return 0; } int Server_jack_deinit (Server *self) { int ret = 0; PyoJackBackendData *be_data = (PyoJackBackendData *) self->audio_be_data; ret = jack_client_close(be_data->jack_client); free(be_data->jack_in_ports); free(be_data->jack_out_ports); free(self->audio_be_data); return ret; } int Server_jack_start (Server *self) { PyoJackBackendData *be_data = (PyoJackBackendData *) self->audio_be_data; jack_set_process_callback(be_data->jack_client, jack_callback, (void *) self); if (jack_activate (be_data->jack_client)) { Server_error(self, "Jack error: cannot activate jack client.\n"); jack_client_close (be_data->jack_client); Server_shut_down(self); return -1; } Server_jack_autoconnect(self); return 0; } int Server_jack_stop (Server *self) { PyoJackBackendData *be_data = (PyoJackBackendData *) self->audio_be_data; int ret = jack_deactivate(be_data->jack_client); self->server_started = 0; return ret; } #endif #ifdef USE_COREAUDIO int Server_coreaudio_init(Server *self) { OSStatus err = kAudioHardwareNoError; UInt32 count, namelen, propertySize; int i, numdevices; char *name; AudioDeviceID mOutputDevice = kAudioDeviceUnknown; AudioDeviceID mInputDevice = kAudioDeviceUnknown; Boolean writable; AudioTimeStamp now; now.mFlags = kAudioTimeStampHostTimeValid; now.mHostTime = AudioGetCurrentHostTime(); /************************************/ /* List Coreaudio available devices */ /************************************/ err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &count, 0); AudioDeviceID *devices = (AudioDeviceID*) malloc(count); err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &count, devices); if (err != kAudioHardwareNoError) { Server_error(self, "Get kAudioHardwarePropertyDevices error %s\n", (char*)&err); free(devices); } numdevices = count / sizeof(AudioDeviceID); Server_debug(self, "Coreaudio : Number of devices: %i\n", numdevices); for (i=0; iduplex == 1) { if (self->input != -1) mInputDevice = devices[self->input]; if (mInputDevice==kAudioDeviceUnknown) { count = sizeof(mInputDevice); err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &count, (void *) &mInputDevice); if (err != kAudioHardwareNoError) { Server_error(self, "Get kAudioHardwarePropertyDefaultInputDevice error %s\n", (char*)&err); return -1; } } err = AudioDeviceGetPropertyInfo(mInputDevice, 0, false, kAudioDevicePropertyDeviceName, &namelen, 0); if (err != kAudioHardwareNoError) { Server_error(self, "Info kAudioDevicePropertyDeviceName error %s A %08X\n", (char*)&err, mInputDevice); } name = (char*)malloc(namelen); err = AudioDeviceGetProperty(mInputDevice, 0, false, kAudioDevicePropertyDeviceName, &namelen, name); if (err != kAudioHardwareNoError) { Server_error(self, "Get kAudioDevicePropertyDeviceName error %s A %08X\n", (char*)&err, mInputDevice); } Server_debug(self, "Coreaudio : Uses input device : \"%s\"\n", name); self->input = mInputDevice; free(name); } /* Acquire output audio device */ if (self->output != -1) mOutputDevice = devices[self->output]; if (mOutputDevice==kAudioDeviceUnknown) { count = sizeof(mOutputDevice); err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &count, (void *) &mOutputDevice); if (err != kAudioHardwareNoError) { Server_error(self, "Get kAudioHardwarePropertyDefaultOutputDevice error %s\n", (char*)&err); return -1; } } err = AudioDeviceGetPropertyInfo(mOutputDevice, 0, false, kAudioDevicePropertyDeviceName, &namelen, 0); if (err != kAudioHardwareNoError) { Server_error(self, "Info kAudioDevicePropertyDeviceName error %s A %08X\n", (char*)&err, mOutputDevice); } name = (char*)malloc(namelen); err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyDeviceName, &namelen, name); if (err != kAudioHardwareNoError) { Server_error(self, "Get kAudioDevicePropertyDeviceName error %s A %08X\n", (char*)&err, mOutputDevice); } Server_debug(self, "Coreaudio : Uses output device : \"%s\"\n", name); self->output = mOutputDevice; free(name); /*************************************************/ /* Get in/out buffer frame and buffer frame size */ /*************************************************/ UInt32 bufferSize; AudioValueRange range; Float64 sampleRate; /* Get input device buffer frame size and buffer frame size range */ if (self->duplex == 1) { count = sizeof(UInt32); err = AudioDeviceGetProperty(mInputDevice, 0, false, kAudioDevicePropertyBufferFrameSize, &count, &bufferSize); if (err != kAudioHardwareNoError) Server_error(self, "Get kAudioDevicePropertyBufferFrameSize error %s\n", (char*)&err); Server_debug(self, "Coreaudio : Coreaudio input device buffer size = %ld\n", bufferSize); count = sizeof(AudioValueRange); err = AudioDeviceGetProperty(mInputDevice, 0, false, kAudioDevicePropertyBufferSizeRange, &count, &range); if (err != kAudioHardwareNoError) Server_error(self, "Get kAudioDevicePropertyBufferSizeRange error %s\n", (char*)&err); Server_debug(self, "Coreaudio : Coreaudio input device buffer size range = %f -> %f\n", range.mMinimum, range.mMaximum); /* Get input device sampling rate */ count = sizeof(Float64); err = AudioDeviceGetProperty(mInputDevice, 0, false, kAudioDevicePropertyNominalSampleRate, &count, &sampleRate); if (err != kAudioHardwareNoError) Server_debug(self, "Get kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err); Server_debug(self, "Coreaudio : Coreaudio input device sampling rate = %.2f\n", sampleRate); } /* Get output device buffer frame size and buffer frame size range */ count = sizeof(UInt32); err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyBufferFrameSize, &count, &bufferSize); if (err != kAudioHardwareNoError) Server_error(self, "Get kAudioDevicePropertyBufferFrameSize error %s\n", (char*)&err); Server_debug(self, "Coreaudio : Coreaudio output device buffer size = %ld\n", bufferSize); count = sizeof(AudioValueRange); err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyBufferSizeRange, &count, &range); if (err != kAudioHardwareNoError) Server_error(self, "Get kAudioDevicePropertyBufferSizeRange error %s\n", (char*)&err); Server_debug(self, "Coreaudio : Coreaudio output device buffer size range = %.2f -> %.2f\n", range.mMinimum, range.mMaximum); /* Get output device sampling rate */ count = sizeof(Float64); err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyNominalSampleRate, &count, &sampleRate); if (err != kAudioHardwareNoError) Server_debug(self, "Get kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err); Server_debug(self, "Coreaudio : Coreaudio output device sampling rate = %.2f\n", sampleRate); /****************************************/ /********* Set audio properties *********/ /****************************************/ /* set/get the buffersize for the devices */ count = sizeof(UInt32); err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyBufferFrameSize, count, &self->bufferSize); if (err != kAudioHardwareNoError) { Server_error(self, "set kAudioDevicePropertyBufferFrameSize error %4.4s\n", (char*)&err); self->bufferSize = bufferSize; err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyBufferFrameSize, count, &self->bufferSize); if (err != kAudioHardwareNoError) Server_error(self, "set kAudioDevicePropertyBufferFrameSize error %4.4s\n", (char*)&err); else Server_debug(self, "pyo buffer size set to output device buffer size : %i\n", self->bufferSize); } else Server_debug(self, "Coreaudio : Changed output device buffer size successfully: %i\n", self->bufferSize); if (self->duplex == 1) { err = AudioDeviceSetProperty(mInputDevice, &now, 0, false, kAudioDevicePropertyBufferFrameSize, count, &self->bufferSize); if (err != kAudioHardwareNoError) { Server_error(self, "set kAudioDevicePropertyBufferFrameSize error %4.4s\n", (char*)&err); } } /* set/get the sampling rate for the devices */ count = sizeof(double); double pyoSamplingRate = self->samplingRate; err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyNominalSampleRate, count, &pyoSamplingRate); if (err != kAudioHardwareNoError) { Server_error(self, "set kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err); self->samplingRate = (double)sampleRate; err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyNominalSampleRate, count, &sampleRate); if (err != kAudioHardwareNoError) Server_error(self, "set kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err); else Server_debug(self, "pyo sampling rate set to output device sampling rate : %i\n", self->samplingRate); } else Server_debug(self, "Coreaudio : Changed output device sampling rate successfully: %.2f\n", self->samplingRate); if (self->duplex ==1) { pyoSamplingRate = self->samplingRate; err = AudioDeviceSetProperty(mInputDevice, &now, 0, false, kAudioDevicePropertyNominalSampleRate, count, &pyoSamplingRate); if (err != kAudioHardwareNoError) { Server_error(self, "set kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err); } } /****************************************/ /* Input and output stream descriptions */ /****************************************/ AudioStreamBasicDescription outputStreamDescription; AudioStreamBasicDescription inputStreamDescription; // Get input device stream configuration if (self->duplex == 1) { count = sizeof(AudioStreamBasicDescription); err = AudioDeviceGetProperty(mInputDevice, 0, true, kAudioDevicePropertyStreamFormat, &count, &inputStreamDescription); if (err != kAudioHardwareNoError) Server_debug(self, "Get kAudioDevicePropertyStreamFormat error %s\n", (char*)&err); /* inputStreamDescription.mSampleRate = (Float64)self->samplingRate; err = AudioDeviceSetProperty(mInputDevice, &now, 0, false, kAudioDevicePropertyStreamFormat, count, &inputStreamDescription); if (err != kAudioHardwareNoError) Server_debug(self, "-- Set kAudioDevicePropertyStreamFormat error %s\n", (char*)&err); // Print new input stream description err = AudioDeviceGetProperty(mInputDevice, 0, true, kAudioDevicePropertyStreamFormat, &count, &inputStreamDescription); if (err != kAudioHardwareNoError) Server_debug(self, "Get kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err); */ Server_debug(self, "Coreaudio : Coreaudio driver input stream sampling rate = %.2f\n", inputStreamDescription.mSampleRate); Server_debug(self, "Coreaudio : Coreaudio driver input stream bytes per frame = %i\n", inputStreamDescription.mBytesPerFrame); Server_debug(self, "Coreaudio : Coreaudio driver input stream number of channels = %i\n", inputStreamDescription.mChannelsPerFrame); } /* Get output device stream configuration */ count = sizeof(AudioStreamBasicDescription); err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyStreamFormat, &count, &outputStreamDescription); if (err != kAudioHardwareNoError) Server_debug(self, "Get kAudioDevicePropertyStreamFormat error %s\n", (char*)&err); /* outputStreamDescription.mSampleRate = (Float64)self->samplingRate; err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyStreamFormat, count, &outputStreamDescription); if (err != kAudioHardwareNoError) Server_debug(self, "Set kAudioDevicePropertyStreamFormat error %s\n", (char*)&err); // Print new output stream description err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyStreamFormat, &count, &outputStreamDescription); if (err != kAudioHardwareNoError) Server_debug(self, "Get kAudioDevicePropertyStreamFormat error %s\n", (char*)&err); */ Server_debug(self, "Coreaudio : Coreaudio driver output stream sampling rate = %.2f\n", outputStreamDescription.mSampleRate); Server_debug(self, "Coreaudio : Coreaudio driver output stream bytes per frame = %i\n", outputStreamDescription.mBytesPerFrame); Server_debug(self, "Coreaudio : Coreaudio driver output stream number of channels = %i\n", outputStreamDescription.mChannelsPerFrame); /**************************************************/ /********* Set input and output callbacks *********/ /**************************************************/ if (self->duplex == 1) { err = AudioDeviceAddIOProc(self->input, coreaudio_input_callback, (void *) self); // setup our device with an IO proc if (err != kAudioHardwareNoError) { Server_error(self, "Input AudioDeviceAddIOProc failed %d\n", (int)err); return -1; } err = AudioDeviceGetPropertyInfo(self->input, 0, true, kAudioDevicePropertyIOProcStreamUsage, &propertySize, &writable); AudioHardwareIOProcStreamUsage *input_su = (AudioHardwareIOProcStreamUsage*)malloc(propertySize); input_su->mIOProc = (void*)coreaudio_input_callback; err = AudioDeviceGetProperty(self->input, 0, true, kAudioDevicePropertyIOProcStreamUsage, &propertySize, input_su); for (i=0; imStreamIsOn[i] = 1; } err = AudioDeviceSetProperty(self->input, &now, 0, true, kAudioDevicePropertyIOProcStreamUsage, propertySize, input_su); } err = AudioDeviceAddIOProc(self->output, coreaudio_output_callback, (void *) self); // setup our device with an IO proc if (err != kAudioHardwareNoError) { Server_error(self, "Output AudioDeviceAddIOProc failed %d\n", (int)err); return -1; } err = AudioDeviceGetPropertyInfo(self->output, 0, false, kAudioDevicePropertyIOProcStreamUsage, &propertySize, &writable); AudioHardwareIOProcStreamUsage *output_su = (AudioHardwareIOProcStreamUsage*)malloc(propertySize); output_su->mIOProc = (void*)coreaudio_output_callback; err = AudioDeviceGetProperty(self->output, 0, false, kAudioDevicePropertyIOProcStreamUsage, &propertySize, output_su); for (i=0; imStreamIsOn[i] = 1; } err = AudioDeviceSetProperty(self->output, &now, 0, false, kAudioDevicePropertyIOProcStreamUsage, propertySize, output_su); return 0; } int Server_coreaudio_deinit(Server *self) { OSStatus err = kAudioHardwareNoError; if (self->duplex == 1) { err = AudioDeviceRemoveIOProc(self->input, coreaudio_input_callback); if (err != kAudioHardwareNoError) { Server_error(self, "Input AudioDeviceRemoveIOProc failed %d\n", (int)err); return -1; } } err = AudioDeviceRemoveIOProc(self->output, coreaudio_output_callback); if (err != kAudioHardwareNoError) { Server_error(self, "Output AudioDeviceRemoveIOProc failed %d\n", (int)err); return -1; } return 0; } int Server_coreaudio_start(Server *self) { OSStatus err = kAudioHardwareNoError; if (self->duplex == 1) { err = AudioDeviceStart(self->input, coreaudio_input_callback); if (err != kAudioHardwareNoError) { Server_error(self, "Input AudioDeviceStart failed %d\n", (int)err); return -1; } } err = AudioDeviceStart(self->output, coreaudio_output_callback); if (err != kAudioHardwareNoError) { Server_error(self, "Output AudioDeviceStart failed %d\n", (int)err); return -1; } return 0; } int Server_coreaudio_stop(Server *self) { coreaudio_stop_callback(self); self->server_stopped = 1; return 0; } #endif int Server_offline_init(Server *self) { return 0; } int Server_offline_deinit(Server *self) { return 0; } void *Server_offline_thread(void *arg) { int numBlocks; Server *self; self = (Server *)arg; if (self->recdur < 0) { Server_error(self,"Duration must be specified for Offline Server (see Server.recordOptions)."); } else { Server_message(self,"Offline Server rendering file %s dur=%f\n", self->recpath, self->recdur); numBlocks = ceil(self->recdur * self->samplingRate/self->bufferSize); Server_debug(self,"Number of blocks: %i\n", numBlocks); Server_start_rec_internal(self, self->recpath); while (numBlocks-- > 0 && self->server_stopped == 0) { offline_process_block((Server *) self); } self->server_started = 0; self->record = 0; sf_close(self->recfile); Server_message(self,"Offline Server rendering finished.\n"); } return NULL; } int Server_offline_nb_start(Server *self) { pthread_t offthread; pthread_create(&offthread, NULL, Server_offline_thread, self); return 0; } int Server_offline_start(Server *self) { int numBlocks; if (self->recdur < 0) { Server_error(self,"Duration must be specified for Offline Server (see Server.recordOptions)."); return -1; } Server_message(self,"Offline Server rendering file %s dur=%f\n", self->recpath, self->recdur); numBlocks = ceil(self->recdur * self->samplingRate/self->bufferSize); Server_debug(self,"Number of blocks: %i\n", numBlocks); Server_start_rec_internal(self, self->recpath); while (numBlocks-- > 0 && self->server_stopped == 0) { offline_process_block((Server *) self); } self->server_started = 0; self->server_stopped = 1; self->record = 0; sf_close(self->recfile); Server_message(self,"Offline Server rendering finished.\n"); return 0; } int Server_offline_stop(Server *self) { self->server_stopped = 1; return 0; } /******* Embedded Server *******/ int Server_embedded_init(Server *self) { return 0; } int Server_embedded_deinit(Server *self) { return 0; } /* interleaved embedded callback */ int Server_embedded_i_start(Server *self) { Server_process_buffers(self); self->midi_count = 0; return 0; } // To be easier to call without depending on the Server structure int Server_embedded_i_startIdx(int idx) { Server_embedded_i_start(my_server[idx]); return 0; } /* non-interleaved embedded callback */ int Server_embedded_ni_start(Server *self) { int i, j; Server_process_buffers(self); float *out = (float *)calloc(self->bufferSize * self->nchnls, sizeof(float)); for (i=0; i<(self->bufferSize*self->nchnls); i++){ out[i] = self->output_buffer[i]; } /* Non-Interleaved */ for (i=0; ibufferSize; i++) { for (j=0; j<=self->nchnls; j++) { /* TODO: This could probably be more efficient (ob) */ self->output_buffer[i+(self->bufferSize*(j+1))-self->bufferSize] = out[(i*self->nchnls)+j]; } } self->midi_count = 0; return 0; } int Server_embedded_ni_startIdx(int idx) { Server_embedded_ni_start(my_server[idx]); return 0; } void *Server_embedded_thread(void *arg) { Server *self; self = (Server *)arg; Server_process_buffers(self); self->midi_count = 0; return NULL; } int Server_embedded_nb_start(Server *self) { pthread_t offthread; pthread_create(&offthread, NULL, Server_embedded_thread, self); return 0; } /* this stop function is not very useful since the processing is stopped at the end of every processing callback, but function put to not break pyo */ int Server_embedded_stop(Server *self) { self->server_started = 0; self->server_stopped = 1; return 0; } /***************************************************/ /* Main Processing functions */ static inline void Server_process_buffers(Server *server) { float *out = server->output_buffer; MYFLT buffer[server->nchnls][server->bufferSize]; int i, j, chnl; int nchnls = server->nchnls; MYFLT amp = server->amp; Stream *stream_tmp; MYFLT *data; memset(&buffer, 0, sizeof(buffer)); PyGILState_STATE s = PyGILState_Ensure(); for (i=0; istream_count; i++) { stream_tmp = (Stream *)PyList_GET_ITEM(server->streams, i); if (Stream_getStreamActive(stream_tmp) == 1) { Stream_callFunction(stream_tmp); if (Stream_getStreamToDac(stream_tmp) != 0) { data = Stream_getData(stream_tmp); chnl = Stream_getStreamChnl(stream_tmp); for (j=0; j < server->bufferSize; j++) { buffer[chnl][j] += *data++; } } if (Stream_getDuration(stream_tmp) != 0) { Stream_IncrementDurationCount(stream_tmp); } } else if (Stream_getBufferCountWait(stream_tmp) != 0) Stream_IncrementBufferCount(stream_tmp); } if (server->withGUI == 1 && nchnls <= 8) { Server_process_gui(server); } if (server->withTIME == 1) { Server_process_time(server); } server->elapsedSamples += server->bufferSize; PyGILState_Release(s); if (amp != server->lastAmp) { server->timeCount = 0; server->stepVal = (amp - server->currentAmp) / server->timeStep; server->lastAmp = amp; } for (i=0; i < server->bufferSize; i++){ if (server->timeCount < server->timeStep) { server->currentAmp += server->stepVal; server->timeCount++; } for (j=0; jnchnls; j++) { out[(i*server->nchnls)+j] = (float)buffer[j][i] * server->currentAmp; } } if (server->record == 1) sf_write_float(server->recfile, out, server->bufferSize * server->nchnls); } static void Server_process_gui(Server *server) { float rms[server->nchnls]; float *out = server->output_buffer; float outAmp; int i,j; for (j=0; jnchnls; j++) { rms[j] = 0.0; for (i=0; ibufferSize; i++) { outAmp = out[(i*server->nchnls)+j]; outAmp *= outAmp; if (outAmp > rms[j]) rms[j] = outAmp; } } if (server->gcount <= server->numPass) { for (j=0; jnchnls; j++) { server->lastRms[j] = (rms[j] + server->lastRms[j]) * 0.5; } server->gcount++; } else { for (j=0; jnchnls; j++) { server->lastRms[j] = (rms[j] + server->lastRms[j]) * 0.5; } switch (server->nchnls) { case 1: PyObject_CallMethod((PyObject *)server->GUI, "setRms", "f", server->lastRms[0]); break; case 2: PyObject_CallMethod((PyObject *)server->GUI, "setRms", "ff", server->lastRms[0], server->lastRms[1]); break; case 3: PyObject_CallMethod((PyObject *)server->GUI, "setRms", "fff", server->lastRms[0], server->lastRms[1], server->lastRms[2]); break; case 4: PyObject_CallMethod((PyObject *)server->GUI, "setRms", "ffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3]); break; case 5: PyObject_CallMethod((PyObject *)server->GUI, "setRms", "fffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3], server->lastRms[4]); break; case 6: PyObject_CallMethod((PyObject *)server->GUI, "setRms", "ffffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3], server->lastRms[4], server->lastRms[5]); break; case 7: PyObject_CallMethod((PyObject *)server->GUI, "setRms", "fffffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3], server->lastRms[4], server->lastRms[5], server->lastRms[6]); break; case 8: PyObject_CallMethod((PyObject *)server->GUI, "setRms", "ffffffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3], server->lastRms[4], server->lastRms[5], server->lastRms[6], server->lastRms[7]); break; } server->gcount = 0; } } static void Server_process_time(Server *server) { int hours, minutes, seconds, milliseconds; float sr = server->samplingRate; double sampsToSecs; if (server->tcount <= server->timePass) { server->tcount++; } else { sampsToSecs = (double)(server->elapsedSamples / sr); seconds = (int)sampsToSecs; milliseconds = (int)((sampsToSecs - seconds) * 1000); minutes = seconds / 60; hours = minutes / 60; minutes = minutes % 60; seconds = seconds % 60; PyObject_CallMethod((PyObject *)server->TIME, "setTime", "iiii", hours, minutes, seconds, milliseconds); server->tcount = 0; } } /***************************************************/ /* Global function called by any new audio object to get a pointer to the server */ PyObject * PyServer_get_server() { return (PyObject *)my_server[serverID]; } static PyObject * Server_shut_down(Server *self) { int i; int ret = -1; if (self->server_booted == 0) { Server_error(self, "The Server must be booted!\n"); Py_INCREF(Py_None); return Py_None; } if (self->server_started == 1) { Server_stop((Server *)self); } for (i=0; iaudio_be_type) { case PyoPortaudio: ret = Server_pa_deinit(self); break; case PyoCoreaudio: #ifdef USE_COREAUDIO ret = Server_coreaudio_deinit(self); #endif break; case PyoJack: #ifdef USE_JACK ret = Server_jack_deinit(self); #endif break; case PyoOffline: ret = Server_offline_deinit(self); break; case PyoOfflineNB: ret = Server_offline_deinit(self); break; case PyoEmbedded: ret = Server_embedded_deinit(self); break; } self->server_booted = 0; if (ret < 0) { Server_error(self, "Error closing audio backend.\n"); } Py_INCREF(Py_None); return Py_None; } /* handling of PyObjects */ static int Server_traverse(Server *self, visitproc visit, void *arg) { /* GUI and TIME ? */ Py_VISIT(self->streams); Py_VISIT(self->jackAutoConnectInputPorts); Py_VISIT(self->jackAutoConnectOutputPorts); return 0; } static int Server_clear(Server *self) { Py_CLEAR(self->streams); Py_CLEAR(self->jackAutoConnectInputPorts); Py_CLEAR(self->jackAutoConnectOutputPorts); return 0; } static void Server_dealloc(Server* self) { if (self->server_booted == 1) Server_shut_down(self); Server_clear(self); free(self->input_buffer); free(self->output_buffer); free(self->serverName); my_server[self->thisServerID] = NULL; self->ob_type->tp_free((PyObject*)self); } static PyObject * Server_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { /* Unused variables to allow the safety check of the embeded audio backend. */ double samplingRate = 44100.0; int nchnls = 2; int ichnls = 2; int bufferSize = 256; int duplex = 0; char *audioType = "portaudio"; char *serverName = "pyo"; static char *kwlist[] = {"sr", "nchnls", "buffersize", "duplex", "audio", "jackname", "ichnls", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|diiissi", kwlist, &samplingRate, &nchnls, &bufferSize, &duplex, &audioType, &serverName, &ichnls)) { Py_INCREF(Py_False); return Py_False; } /* TODO: Need some testing to validate that there is no conflict when more than one server are running at the same time. */ /* if (strcmp(audioType, "embedded") != 0) { if (PyServer_get_server() != NULL) { PyErr_SetString(PyExc_RuntimeError, "Warning: Trying to create a new Server object while one is already created!\n"); Py_RETURN_NONE; } } */ /* find the first free serverID */ for(serverID = 0; serverID < MAX_NBR_SERVER; serverID++){ if(my_server[serverID] == NULL){ break; } } if(serverID == MAX_NBR_SERVER){ PyErr_SetString(PyExc_RuntimeError, "You are already using the maximum number of server allowed!\n"); Py_RETURN_NONE; } Server *self; self = (Server *)type->tp_alloc(type, 0); self->server_booted = 0; self->audio_be_data = NULL; self->serverName = (char *) calloc(32, sizeof(char)); self->jackautoin = 1; self->jackautoout = 1; self->jackAutoConnectInputPorts = PyList_New(0); self->jackAutoConnectOutputPorts = PyList_New(0); self->samplingRate = 44100.0; self->nchnls = 2; self->ichnls = 2; self->record = 0; self->bufferSize = 256; self->currentResampling = 1; self->lastResampling = 1; self->duplex = 0; self->input = -1; self->output = -1; self->input_offset = 0; self->output_offset = 0; self->midiin_count = 0; self->midiout_count = 0; self->midi_input = -1; self->midi_output = -1; self->midiActive = 1; self->amp = self->resetAmp = 1.; self->currentAmp = self->lastAmp = 0.; self->withGUI = 0; self->withTIME = 0; self->verbosity = 7; self->recdur = -1; self->recformat = 0; self->rectype = 0; self->startoffset = 0.0; self->globalSeed = 0; self->thisServerID = serverID; Py_XDECREF(my_server[serverID]); my_server[serverID] = (Server *)self; return (PyObject *)self; } static int Server_init(Server *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"sr", "nchnls", "buffersize", "duplex", "audio", "jackname", "ichnls", NULL}; char *audioType = "portaudio"; char *serverName = "pyo"; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|diiissi", kwlist, &self->samplingRate, &self->nchnls, &self->bufferSize, &self->duplex, &audioType, &serverName, &self->ichnls)) return -1; if (strcmp(audioType, "jack") == 0) { self->audio_be_type = PyoJack; } else if (strcmp(audioType, "portaudio") == 0 || strcmp(audioType, "pa") == 0 ) { self->audio_be_type = PyoPortaudio; } else if (strcmp(audioType, "coreaudio") == 0) { self->audio_be_type = PyoCoreaudio; } else if (strcmp(audioType, "offline") == 0) { self->audio_be_type = PyoOffline; } else if (strcmp(audioType, "offline_nb") == 0) { self->audio_be_type = PyoOfflineNB; } else if (strcmp(audioType, "embedded") == 0) { self->audio_be_type = PyoEmbedded; } else { Server_warning(self, "Unknown audio type. Using Portaudio\n"); self->audio_be_type = PyoPortaudio; } strncpy(self->serverName, serverName, 32); if (strlen(serverName) > 31) { self->serverName[31] = '\0'; } return 0; } static PyObject * Server_setDefaultRecPath(Server *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"path", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &self->recpath)) return PyInt_FromLong(-1); Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setInputOffset(Server *self, PyObject *arg) { if (self->server_booted) { Server_warning(self, "Can't change input offset for booted server.\n"); Py_INCREF(Py_None); return Py_None; } if (arg != NULL) { if (PyInt_Check(arg)) self->input_offset = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setOutputOffset(Server *self, PyObject *arg) { if (self->server_booted) { Server_warning(self, "Can't change output offset for booted server.\n"); Py_INCREF(Py_None); return Py_None; } if (arg != NULL) { if (PyInt_Check(arg)) self->output_offset = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setInputDevice(Server *self, PyObject *arg) { if (arg != NULL) { if (PyInt_Check(arg)) self->input = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setInOutDevice(Server *self, PyObject *arg) { if (arg != NULL) { if (PyInt_Check(arg)) self->input = PyInt_AsLong(arg); self->output = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setOutputDevice(Server *self, PyObject *arg) { if (arg != NULL) { if (PyInt_Check(arg)) self->output = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setMidiInputDevice(Server *self, PyObject *arg) { if (arg != NULL) { if (PyInt_Check(arg)) self->midi_input = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setMidiOutputDevice(Server *self, PyObject *arg) { if (arg != NULL) { if (PyInt_Check(arg)) self->midi_output = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_deactivateMidi(Server *self) { self->midiActive = 0; Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setSamplingRate(Server *self, PyObject *arg) { if (self->server_booted) { Server_warning(self, "Can't change sampling rate for booted server.\n"); Py_INCREF(Py_None); return Py_None; } if (arg != NULL && PyNumber_Check(arg)) { self->samplingRate = PyFloat_AsDouble(arg); } else { Server_error(self, "Sampling rate must be a number.\n"); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setNchnls(Server *self, PyObject *arg) { if (self->server_booted) { Server_warning(self, "Can't change number of channels for booted server.\n"); Py_INCREF(Py_None); return Py_None; } if (arg != NULL && PyInt_Check(arg)) { self->nchnls = PyInt_AsLong(arg); } else { Server_error(self, "Number of channels must be an integer.\n"); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setIchnls(Server *self, PyObject *arg) { if (self->server_booted) { Server_warning(self, "Can't change number of input channels for booted server.\n"); Py_INCREF(Py_None); return Py_None; } if (arg != NULL && PyInt_Check(arg)) { self->ichnls = PyInt_AsLong(arg); } else { Server_error(self, "Number of input channels must be an integer.\n"); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setBufferSize(Server *self, PyObject *arg) { if (self->server_booted) { Server_warning(self, "Can't change buffer size for booted server.\n"); Py_INCREF(Py_None); return Py_None; } if (arg != NULL && PyInt_Check(arg)) { self->bufferSize = PyInt_AsLong(arg); } else { Server_error(self, "Buffer size must be an integer.\n"); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setDuplex(Server *self, PyObject *arg) { if (self->server_booted) { Server_warning(self,"Can't change duplex mode for booted server.\n"); Py_INCREF(Py_None); return Py_None; } if (arg != NULL) { if (PyInt_Check(arg)) self->duplex = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setJackAuto(Server *self, PyObject *args) { int in=1, out=1; if (! PyArg_ParseTuple(args, "ii", &in, &out)) { Py_INCREF(Py_None); return Py_None; } self->jackautoin = in; self->jackautoout = out; Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setJackAutoConnectInputPorts(Server *self, PyObject *arg) { PyObject *tmp; if (arg != NULL) { if (PyList_Check(arg)) { tmp = arg; Py_XDECREF(self->jackAutoConnectInputPorts); Py_INCREF(tmp); self->jackAutoConnectInputPorts = tmp; } } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setJackAutoConnectOutputPorts(Server *self, PyObject *arg) { PyObject *tmp; if (arg != NULL) { if (PyList_Check(arg)) { tmp = arg; Py_XDECREF(self->jackAutoConnectOutputPorts); Py_INCREF(tmp); self->jackAutoConnectOutputPorts = tmp; } } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setGlobalSeed(Server *self, PyObject *arg) { unsigned int tmp; if (arg != NULL) { if (PyInt_Check(arg)) { tmp = PyInt_AsLong(arg); if (tmp < 0) self->globalSeed = 0; else self->globalSeed = tmp; } else self->globalSeed = 0; } else self->globalSeed = 0; Py_INCREF(Py_None); return Py_None; } int Server_generateSeed(Server *self, int oid) { int curseed, seed, count, mult; long ltime; count = ++rnd_objs_count[oid]; mult = rnd_objs_mult[oid]; if (self->globalSeed > 0) { curseed = self->globalSeed + ((count * mult) % 32768); } else { ltime = time(NULL); seed = (unsigned) (ltime / 2) % 32768; curseed = seed + ((count * mult) % 32768); } srand(curseed); return 0; } static PyObject * Server_setAmp(Server *self, PyObject *arg) { if (arg != NULL) { int check = PyNumber_Check(arg); if (check) { self->amp = PyFloat_AsDouble(arg); if (self->amp != 0.0) self->resetAmp = self->amp; } } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setAmpCallable(Server *self, PyObject *arg) { int i; PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_XDECREF(self->GUI); Py_INCREF(tmp); self->GUI = tmp; self->lastRms = (float *)realloc(self->lastRms, self->nchnls * sizeof(float)); for (i=0; inchnls; i++) { self->lastRms[i] = 0.0; } for (i=1; i<100; i++) { if ((self->bufferSize * i / self->samplingRate) > 0.045) { self->numPass = i; break; } } self->gcount = 0; self->withGUI = 1; Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setTimeCallable(Server *self, PyObject *arg) { int i; PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_XDECREF(self->TIME); Py_INCREF(tmp); self->TIME = tmp; for (i=1; i<100; i++) { if ((self->bufferSize * i / self->samplingRate) > 0.06) { self->timePass = i; break; } } self->tcount = 0; self->withTIME = 1; Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setVerbosity(Server *self, PyObject *arg) { if (arg != NULL) { int check = PyInt_Check(arg); if (check) { self->verbosity = PyInt_AsLong(arg); } } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_setStartOffset(Server *self, PyObject *arg) { if (arg != NULL) { int check = PyNumber_Check(arg); if (check) { self->startoffset = PyFloat_AsDouble(arg); } } Py_INCREF(Py_None); return Py_None; } int Server_pm_init(Server *self) { int i = 0; PmError pmerr; if (self->midiActive == 0) { self->withPortMidi = 0; self->withPortMidiOut = 0; return 0; } pmerr = Pm_Initialize(); if (pmerr) { Server_warning(self, "Portmidi warning: could not initialize Portmidi: %s\n", Pm_GetErrorText(pmerr)); self->withPortMidi = 0; self->withPortMidiOut = 0; return -1; } else { Server_debug(self, "Portmidi initialized.\n"); self->withPortMidi = 1; self->withPortMidiOut = 1; } if (self->withPortMidi == 1) { self->midiin_count = self->midiout_count = 0; int num_devices = Pm_CountDevices(); Server_debug(self, "Portmidi number of devices: %d.\n", num_devices); if (num_devices > 0) { if (self->midi_input < num_devices) { if (self->midi_input == -1) self->midi_input = Pm_GetDefaultInputDeviceID(); Server_debug(self, "Midi input device : %d.\n", self->midi_input); const PmDeviceInfo *info = Pm_GetDeviceInfo(self->midi_input); if (info != NULL) { if (info->input) { pmerr = Pm_OpenInput(&self->midiin[0], self->midi_input, NULL, 100, NULL, NULL); if (pmerr) { Server_warning(self, "Portmidi warning: could not open midi input %d (%s): %s\n", self->midi_input, info->name, Pm_GetErrorText(pmerr)); self->withPortMidi = 0; } else { Server_debug(self, "Midi input (%s) opened.\n", info->name); self->midiin_count = 1; } } else { Server_warning(self, "Portmidi warning: Midi Device (%s), not an input device!\n", info->name); self->withPortMidi = 0; } } } else if (self->midi_input >= num_devices) { Server_debug(self, "Midi input device : all!\n"); self->midiin_count = 0; for (i=0; iinput) { pmerr = Pm_OpenInput(&self->midiin[self->midiin_count], i, NULL, 100, NULL, NULL); if (pmerr) { Server_warning(self, "Portmidi warning: could not open midi input %d (%s): %s\n", 0, info->name, Pm_GetErrorText(pmerr)); } else { Server_debug(self, "Midi input (%s) opened.\n", info->name); self->midiin_count++; } } } } if (self->midiin_count == 0) self->withPortMidi = 0; } else { Server_warning(self, "Portmidi warning: no input device!\n"); self->withPortMidi = 0; } if (self->midi_output < num_devices) { if (self->midi_output == -1) self->midi_output = Pm_GetDefaultOutputDeviceID(); Server_debug(self, "Midi output device : %d.\n", self->midi_output); const PmDeviceInfo *outinfo = Pm_GetDeviceInfo(self->midi_output); if (outinfo != NULL) { if (outinfo->output) { Pt_Start(1, 0, 0); /* start a timer with millisecond accuracy */ pmerr = Pm_OpenOutput(&self->midiout[0], self->midi_output, NULL, 0, NULL, NULL, 1); if (pmerr) { Server_warning(self, "Portmidi warning: could not open midi output %d (%s): %s\n", self->midi_output, outinfo->name, Pm_GetErrorText(pmerr)); self->withPortMidiOut = 0; if (Pt_Started()) Pt_Stop(); } else { Server_debug(self, "Midi output (%s) opened.\n", outinfo->name); self->midiout_count = 1; } } else { Server_warning(self, "Portmidi warning: Midi Device (%s), not an output device!\n", outinfo->name); self->withPortMidiOut = 0; } } } else if (self->midi_output >= num_devices) { Server_debug(self, "Midi output device : all!\n"); self->midiout_count = 0; Pt_Start(1, 0, 0); /* start a timer with millisecond accuracy */ for (i=0; ioutput) { pmerr = Pm_OpenOutput(&self->midiout[self->midiout_count], i, NULL, 100, NULL, NULL, 1); if (pmerr) { Server_warning(self, "Portmidi warning: could not open midi output %d (%s): %s\n", 0, outinfo->name, Pm_GetErrorText(pmerr)); } else { Server_debug(self, "Midi output (%s) opened.\n", outinfo->name); self->midiout_count++; } } } } if (self->midiout_count == 0) { if (Pt_Started()) Pt_Stop(); self->withPortMidiOut = 0; } } else { Server_warning(self, "Portmidi warning: no output device!\n"); self->withPortMidiOut = 0; } if (self->withPortMidi == 0 && self->withPortMidiOut == 0) { Pm_Terminate(); Server_warning(self, "Portmidi closed.\n"); } } else { Server_warning(self, "Portmidi warning: no midi device found!\nPortmidi closed.\n"); self->withPortMidi = 0; self->withPortMidiOut = 0; Pm_Terminate(); } } if (self->withPortMidi == 1) { self->midi_count = 0; for (i=0; imidiin_count; i++) { Pm_SetFilter(self->midiin[i], PM_FILT_ACTIVE | PM_FILT_CLOCK); } } return 0; } static PyObject * Server_boot(Server *self, PyObject *arg) { int audioerr = 0; int i; if (self->server_booted == 1) { Server_error(self, "Server already booted!\n"); Py_INCREF(Py_None); return Py_None; } self->server_started = 0; self->stream_count = 0; self->elapsedSamples = 0; int needNewBuffer = 0; if (arg != NULL && PyBool_Check(arg)) { needNewBuffer = PyObject_IsTrue(arg); } else { Server_error(self, "The argument to set for a new buffer must be a boolean.\n"); } self->streams = PyList_New(0); switch (self->audio_be_type) { case PyoPortaudio: audioerr = Server_pa_init(self); break; case PyoJack: #ifdef USE_JACK audioerr = Server_jack_init(self); if (audioerr < 0) { Server_jack_deinit(self); } #else audioerr = -1; Server_error(self, "Pyo built without Jack support\n"); #endif break; case PyoCoreaudio: #ifdef USE_COREAUDIO audioerr = Server_coreaudio_init(self); if (audioerr < 0) { Server_coreaudio_deinit(self); } #else audioerr = -1; Server_error(self, "Pyo built without Coreaudio support\n"); #endif break; case PyoOffline: audioerr = Server_offline_init(self); if (audioerr < 0) { Server_offline_deinit(self); } break; case PyoOfflineNB: audioerr = Server_offline_init(self); if (audioerr < 0) { Server_offline_deinit(self); } break; case PyoEmbedded: audioerr = Server_embedded_init(self); if (audioerr < 0) { Server_embedded_deinit(self); } break; } if (needNewBuffer == 1){ /* Must allocate buffer after initializing the audio backend in case parameters change there */ if (self->input_buffer) { free(self->input_buffer); } self->input_buffer = (MYFLT *)calloc(self->bufferSize * self->ichnls, sizeof(MYFLT)); if (self->output_buffer) { free(self->output_buffer); } self->output_buffer = (float *)calloc(self->bufferSize * self->nchnls, sizeof(float)); } for (i=0; ibufferSize*self->ichnls; i++) { self->input_buffer[i] = 0.0; } for (i=0; ibufferSize*self->nchnls; i++) { self->output_buffer[i] = 0.0; } if (audioerr == 0) { self->server_booted = 1; } else { self->server_booted = 0; Server_error(self, "\nServer not booted.\n"); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_start(Server *self) { int err = -1, midierr = 0; if (self->server_started == 1) { Server_warning(self, "Server already started!\n"); Py_INCREF(Py_None); return Py_None; } if (self->server_booted == 0) { Server_warning(self, "The Server must be booted!\n"); Py_INCREF(Py_None); return Py_None; } Server_debug(self, "Server_start: number of streams %d\n", self->stream_count); /* Ensure Python is set up for threading */ PyEval_InitThreads(); self->server_stopped = 0; self->server_started = 1; self->timeStep = (int)(0.01 * self->samplingRate); if (self->audio_be_type != PyoOffline && self->audio_be_type != PyoOfflineNB && self->audio_be_type != PyoEmbedded) { midierr = Server_pm_init(self); Server_debug(self, "PortMidi initialization return code : %d.\n", midierr); } if (self->startoffset > 0.0) { Server_message(self,"Rendering %.2f seconds offline...\n", self->startoffset); int numBlocks = ceil(self->startoffset * self->samplingRate/self->bufferSize); self->lastAmp = 1.0; self->amp = 0.0; while (numBlocks-- > 0) { offline_process_block((Server *) self); } Server_message(self,"Offline rendering completed. Start realtime processing.\n"); self->startoffset = 0.0; } self->amp = self->resetAmp; switch (self->audio_be_type) { case PyoPortaudio: err = Server_pa_start(self); break; case PyoCoreaudio: #ifdef USE_COREAUDIO err = Server_coreaudio_start(self); #endif break; case PyoJack: #ifdef USE_JACK err = Server_jack_start(self); #endif break; case PyoOffline: err = Server_offline_start(self); break; case PyoOfflineNB: err = Server_offline_nb_start(self); break; case PyoEmbedded: err = Server_embedded_nb_start(self); break; } if (err) { Server_error(self, "Error starting server.\n"); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_stop(Server *self) { int i; int err = -1; if (self->server_started == 0) { Server_warning(self, "The Server must be started!\n"); Py_INCREF(Py_None); return Py_None; } switch (self->audio_be_type) { case PyoPortaudio: err = Server_pa_stop(self); break; case PyoCoreaudio: #ifdef USE_COREAUDIO err = Server_coreaudio_stop(self); #endif break; case PyoJack: #ifdef USE_JACK err = Server_jack_stop(self); #endif break; case PyoOffline: err = Server_offline_stop(self); break; case PyoOfflineNB: err = Server_offline_stop(self); break; case PyoEmbedded: err = Server_embedded_stop(self); break; } if (err < 0) { Server_error(self, "Error stopping server.\n"); } else { self->server_stopped = 1; if (self->withPortMidi == 1) { for (i=0; imidiin_count; i++) { Pm_Close(self->midiin[i]); } } if (self->withPortMidiOut == 1) { for (i=0; imidiout_count; i++) { Pm_Close(self->midiout[i]); } } if (self->withPortMidi == 1 || self->withPortMidiOut == 1) { if (Pt_Started()) Pt_Stop(); Pm_Terminate(); } self->withPortMidi = 0; self->withPortMidiOut = 0; } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_recordOptions(Server *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"dur", "filename", "fileformat", "sampletype", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "d|sii", kwlist, &self->recdur, &self->recpath, &self->recformat, &self->rectype)) { return PyInt_FromLong(-1); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_start_rec(Server *self, PyObject *args, PyObject *kwds) { char *filename=NULL; static char *kwlist[] = {"filename", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &filename)) { return PyInt_FromLong(-1); } Server_start_rec_internal(self, filename); Py_INCREF(Py_None); return Py_None; } static int Server_start_rec_internal(Server *self, char *filename) { /* Prepare sfinfo */ self->recinfo.samplerate = (int)self->samplingRate; self->recinfo.channels = self->nchnls; Server_debug(self, "recinfo.samplerate : %i\n", self->recinfo.samplerate); Server_debug(self, "recinfo.channels : %i\n", self->recinfo.channels); switch (self->recformat) { case 0: self->recinfo.format = SF_FORMAT_WAV; break; case 1: self->recinfo.format = SF_FORMAT_AIFF; break; case 2: self->recinfo.format = SF_FORMAT_AU; break; case 3: self->recinfo.format = SF_FORMAT_RAW; break; case 4: self->recinfo.format = SF_FORMAT_SD2; break; case 5: self->recinfo.format = SF_FORMAT_FLAC; break; case 6: self->recinfo.format = SF_FORMAT_CAF; break; case 7: self->recinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS; break; } if (self->recformat != 7) { switch (self->rectype) { case 0: self->recinfo.format = self->recinfo.format | SF_FORMAT_PCM_16; break; case 1: self->recinfo.format = self->recinfo.format | SF_FORMAT_PCM_24; break; case 2: self->recinfo.format = self->recinfo.format | SF_FORMAT_PCM_32; break; case 3: self->recinfo.format = self->recinfo.format | SF_FORMAT_FLOAT; break; case 4: self->recinfo.format = self->recinfo.format | SF_FORMAT_DOUBLE; break; case 5: self->recinfo.format = self->recinfo.format | SF_FORMAT_ULAW; break; case 6: self->recinfo.format = self->recinfo.format | SF_FORMAT_ALAW; break; } } Server_debug(self, "recinfo.format : %i\n", self->recinfo.format); /* Open the output file. */ if (filename == NULL) { Server_debug(self, "recpath : %s\n", self->recpath); if (! (self->recfile = sf_open(self->recpath, SFM_WRITE, &self->recinfo))) { Server_error(self, "Not able to open output file %s.\n", self->recpath); Server_debug(self, "%s\n", sf_strerror(self->recfile)); return -1; } } else { Server_debug(self, "filename : %s\n", filename); if (! (self->recfile = sf_open(filename, SFM_WRITE, &self->recinfo))) { Server_error(self, "Not able to open output file %s.\n", filename); Server_debug(self, "%s\n", sf_strerror(self->recfile)); return -1; } } self->record = 1; return 0; } static PyObject * Server_stop_rec(Server *self, PyObject *args) { self->record = 0; sf_close(self->recfile); Py_INCREF(Py_None); return Py_None; } static PyObject * Server_addStream(Server *self, PyObject *args) { PyObject *tmp; if (! PyArg_ParseTuple(args, "O", &tmp)) return PyInt_FromLong(-1); if (tmp == NULL) { Server_error(self, "Server_addStream needs a pyo object as argument.\n"); return PyInt_FromLong(-1); } PyList_Append(self->streams, tmp); self->stream_count++; Py_INCREF(Py_None); return Py_None; } PyObject * Server_removeStream(Server *self, int id) { int i, sid; Stream *stream_tmp; PyGILState_STATE s = PyGILState_Ensure(); //if (PyObject_HasAttrString((PyObject *)self, "streams")) { if (PySequence_Size(self->streams) != -1) { for (i=0; istream_count; i++) { stream_tmp = (Stream *)PyList_GetItem(self->streams, i); if (stream_tmp != NULL) { sid = Stream_getStreamId(stream_tmp); if (sid == id) { Server_debug(self, "Removed stream id %d\n", id); PySequence_DelItem(self->streams, i); self->stream_count--; break; } } } } PyGILState_Release(s); Py_INCREF(Py_None); return Py_None; } PyObject * Server_changeStreamPosition(Server *self, PyObject *args) { int i, rsid, csid, sid; Stream *ref_stream_tmp, *cur_stream_tmp, *stream_tmp; if (! PyArg_ParseTuple(args, "OO", &ref_stream_tmp, &cur_stream_tmp)) return PyInt_FromLong(-1); rsid = Stream_getStreamId(ref_stream_tmp); csid = Stream_getStreamId(cur_stream_tmp); for (i=0; istream_count; i++) { stream_tmp = (Stream *)PyList_GET_ITEM(self->streams, i); sid = Stream_getStreamId(stream_tmp); if (sid == csid) { PySequence_DelItem(self->streams, i); self->stream_count--; break; } } for (i=0; istream_count; i++) { stream_tmp = (Stream *)PyList_GET_ITEM(self->streams, i); sid = Stream_getStreamId(stream_tmp); if (sid == rsid) { break; } } Py_INCREF(cur_stream_tmp); PyList_Insert(self->streams, i, (PyObject *)cur_stream_tmp); self->stream_count++; Py_INCREF(Py_None); return Py_None; } PyObject * Server_noteout(Server *self, PyObject *args) { int i, pit, vel, chan, curtime; PmEvent buffer[1]; PmTimestamp timestamp; if (! PyArg_ParseTuple(args, "iiii", &pit, &vel, &chan, ×tamp)) return PyInt_FromLong(-1); if (self->withPortMidiOut) { curtime = Pt_Time(); buffer[0].timestamp = curtime + timestamp; if (chan == 0) buffer[0].message = Pm_Message(0x90, pit, vel); else buffer[0].message = Pm_Message(0x90 | (chan - 1), pit, vel); for (i=0; imidiout_count; i++) { Pm_Write(self->midiout[i], buffer, 1); } } Py_INCREF(Py_None); return Py_None; } PyObject * Server_afterout(Server *self, PyObject *args) { int i, pit, vel, chan, curtime; PmEvent buffer[1]; PmTimestamp timestamp; if (! PyArg_ParseTuple(args, "iiii", &pit, &vel, &chan, ×tamp)) return PyInt_FromLong(-1); if (self->withPortMidiOut) { curtime = Pt_Time(); buffer[0].timestamp = curtime + timestamp; if (chan == 0) buffer[0].message = Pm_Message(0xA0, pit, vel); else buffer[0].message = Pm_Message(0xA0 | (chan - 1), pit, vel); for (i=0; imidiout_count; i++) { Pm_Write(self->midiout[i], buffer, 1); } } Py_INCREF(Py_None); return Py_None; } PyObject * Server_ctlout(Server *self, PyObject *args) { int i, ctlnum, value, chan, curtime; PmEvent buffer[1]; PmTimestamp timestamp; if (! PyArg_ParseTuple(args, "iiii", &ctlnum, &value, &chan, ×tamp)) return PyInt_FromLong(-1); if (self->withPortMidiOut) { curtime = Pt_Time(); buffer[0].timestamp = curtime + timestamp; if (chan == 0) buffer[0].message = Pm_Message(0xB0, ctlnum, value); else buffer[0].message = Pm_Message(0xB0 | (chan - 1), ctlnum, value); for (i=0; imidiout_count; i++) { Pm_Write(self->midiout[i], buffer, 1); } } Py_INCREF(Py_None); return Py_None; } PyObject * Server_programout(Server *self, PyObject *args) { int i, value, chan, curtime; PmEvent buffer[1]; PmTimestamp timestamp; if (! PyArg_ParseTuple(args, "iii", &value, &chan, ×tamp)) return PyInt_FromLong(-1); if (self->withPortMidiOut) { curtime = Pt_Time(); buffer[0].timestamp = curtime + timestamp; if (chan == 0) buffer[0].message = Pm_Message(0xC0, value, 0); else buffer[0].message = Pm_Message(0xC0 | (chan - 1), value, 0); for (i=0; imidiout_count; i++) { Pm_Write(self->midiout[i], buffer, 1); } } Py_INCREF(Py_None); return Py_None; } PyObject * Server_pressout(Server *self, PyObject *args) { int i, value, chan, curtime; PmEvent buffer[1]; PmTimestamp timestamp; if (! PyArg_ParseTuple(args, "iii", &value, &chan, ×tamp)) return PyInt_FromLong(-1); if (self->withPortMidiOut) { curtime = Pt_Time(); buffer[0].timestamp = curtime + timestamp; if (chan == 0) buffer[0].message = Pm_Message(0xD0, value, 0); else buffer[0].message = Pm_Message(0xD0 | (chan - 1), value, 0); for (i=0; imidiout_count; i++) { Pm_Write(self->midiout[i], buffer, 1); } } Py_INCREF(Py_None); return Py_None; } PyObject * Server_bendout(Server *self, PyObject *args) { int i, lsb, msb, value, chan, curtime; PmEvent buffer[1]; PmTimestamp timestamp; if (! PyArg_ParseTuple(args, "iii", &value, &chan, ×tamp)) return PyInt_FromLong(-1); if (self->withPortMidiOut) { curtime = Pt_Time(); buffer[0].timestamp = curtime + timestamp; lsb = value & 0x007F; msb = (value & (0x007F << 7)) >> 7; if (chan == 0) buffer[0].message = Pm_Message(0xE0, lsb, msb); else buffer[0].message = Pm_Message(0xE0 | (chan - 1), lsb, msb); for (i=0; imidiout_count; i++) { Pm_Write(self->midiout[i], buffer, 1); } } Py_INCREF(Py_None); return Py_None; } MYFLT * Server_getInputBuffer(Server *self) { return (MYFLT *)self->input_buffer; } PmEvent * Server_getMidiEventBuffer(Server *self) { return (PmEvent *)self->midiEvents; } int Server_getMidiEventCount(Server *self) { return self->midi_count; } static PyObject * Server_addMidiEvent(Server *self, PyObject *args) { int status, data1, data2; PmEvent buffer; if (! PyArg_ParseTuple(args, "iii", &status, &data1, &data2)) return PyInt_FromLong(-1); buffer.timestamp = 0; buffer.message = Pm_Message(status, data1, data2); self->midiEvents[self->midi_count++] = buffer; Py_INCREF(Py_None); return Py_None; } int Server_getCurrentResamplingFactor(Server *self) { return self->currentResampling; } int Server_getLastResamplingFactor(Server *self) { return self->lastResampling; } static PyObject * Server_getSamplingRate(Server *self) { if (self->currentResampling < 0) return PyFloat_FromDouble(self->samplingRate / -self->currentResampling); else return PyFloat_FromDouble(self->samplingRate * self->currentResampling); } static PyObject * Server_getNchnls(Server *self) { return PyInt_FromLong(self->nchnls); } static PyObject * Server_getIchnls(Server *self) { return PyInt_FromLong(self->ichnls); } static PyObject * Server_getGlobalSeed(Server *self) { return PyInt_FromLong(self->globalSeed); } static PyObject * Server_getBufferSize(Server *self) { if (self->currentResampling < 0) return PyInt_FromLong(self->bufferSize / -self->currentResampling); else return PyInt_FromLong(self->bufferSize * self->currentResampling); } static PyObject * Server_beginResamplingBlock(Server *self, PyObject *arg) { if (PyInt_Check(arg)) { self->lastResampling = self->currentResampling; self->currentResampling = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Server_endResamplingBlock(Server *self) { self->lastResampling = self->currentResampling; self->currentResampling = 1; Py_INCREF(Py_None); return Py_None; } static PyObject * Server_getIsStarted(Server *self) { return PyInt_FromLong(self->server_started); } static PyObject * Server_getIsBooted(Server *self) { return PyInt_FromLong(self->server_booted); } static PyObject * Server_getMidiActive(Server *self) { return PyInt_FromLong(self->withPortMidi); } static PyObject * Server_getStreams(Server *self) { Py_INCREF(self->streams); return self->streams; } static PyObject * Server_setServer(Server *self) { serverID = self->thisServerID; /* TODO: Should return a more conventional signal, like True or False */ return PyString_FromString("Server set"); } static PyObject * Server_getInputAddr(Server *self) { char address[32]; sprintf(address, "%p", &self->input_buffer[0]); return PyString_FromString(address); } static PyObject * Server_getOutputAddr(Server *self) { char address[32]; sprintf(address, "%p", &self->output_buffer[0]); return PyString_FromString(address); } static PyObject * Server_getServerID(Server *self) { return PyInt_FromLong(self->thisServerID); } static PyObject * Server_getServerAddr(Server *self) { char address[32]; sprintf(address, "%p", &my_server[self->thisServerID]); return PyString_FromString(address); } void Server_getThisServer(int id, Server *server) { server = my_server[id]; } /* static PyObject * Server_getThisServerFunc(Server *self) { char address[32]; sprintf(address, "%p", &Server_getThisServer); return PyString_FromString(address); } */ static PyObject * Server_getEmbedICallbackAddr(Server *self) { char address[32]; sprintf(address, "%p", &Server_embedded_i_startIdx); return PyString_FromString(address); } static PyMethodDef Server_methods[] = { {"setInputDevice", (PyCFunction)Server_setInputDevice, METH_O, "Sets audio input device."}, {"setOutputDevice", (PyCFunction)Server_setOutputDevice, METH_O, "Sets audio output device."}, {"setInputOffset", (PyCFunction)Server_setInputOffset, METH_O, "Sets audio input channel offset."}, {"setOutputOffset", (PyCFunction)Server_setOutputOffset, METH_O, "Sets audio output channel offset."}, {"setInOutDevice", (PyCFunction)Server_setInOutDevice, METH_O, "Sets both audio input and output device."}, {"setMidiInputDevice", (PyCFunction)Server_setMidiInputDevice, METH_O, "Sets MIDI input device."}, {"setMidiOutputDevice", (PyCFunction)Server_setMidiOutputDevice, METH_O, "Sets MIDI output device."}, {"deactivateMidi", (PyCFunction)Server_deactivateMidi, METH_NOARGS, "Deactivates midi callback."}, {"setSamplingRate", (PyCFunction)Server_setSamplingRate, METH_O, "Sets the server's sampling rate."}, {"setBufferSize", (PyCFunction)Server_setBufferSize, METH_O, "Sets the server's buffer size."}, {"beginResamplingBlock", (PyCFunction)Server_beginResamplingBlock, METH_O, "Starts a resampling code block."}, {"endResamplingBlock", (PyCFunction)Server_endResamplingBlock, METH_NOARGS, "Stops a resampling code block."}, {"setNchnls", (PyCFunction)Server_setNchnls, METH_O, "Sets the server's number of output/input channels."}, {"setIchnls", (PyCFunction)Server_setIchnls, METH_O, "Sets the server's number of input channels."}, {"setDuplex", (PyCFunction)Server_setDuplex, METH_O, "Sets the server's duplex mode (0 = only out, 1 = in/out)."}, {"setJackAuto", (PyCFunction)Server_setJackAuto, METH_VARARGS, "Tells the server to auto-connect Jack ports (0 = disable, 1 = enable)."}, {"setJackAutoConnectInputPorts", (PyCFunction)Server_setJackAutoConnectInputPorts, METH_O, "Sets a list of ports to auto-connect inputs when using Jack."}, {"setJackAutoConnectOutputPorts", (PyCFunction)Server_setJackAutoConnectOutputPorts, METH_O, "Sets a list of ports to auto-connect outputs when using Jack."}, {"setGlobalSeed", (PyCFunction)Server_setGlobalSeed, METH_O, "Sets the server's global seed for random objects."}, {"setAmp", (PyCFunction)Server_setAmp, METH_O, "Sets the overall amplitude."}, {"setAmpCallable", (PyCFunction)Server_setAmpCallable, METH_O, "Sets the Server's GUI callable object."}, {"setTimeCallable", (PyCFunction)Server_setTimeCallable, METH_O, "Sets the Server's TIME callable object."}, {"setVerbosity", (PyCFunction)Server_setVerbosity, METH_O, "Sets the verbosity."}, {"setStartOffset", (PyCFunction)Server_setStartOffset, METH_O, "Sets starting time offset."}, {"boot", (PyCFunction)Server_boot, METH_O, "Setup and boot the server."}, {"shutdown", (PyCFunction)Server_shut_down, METH_NOARGS, "Shut down the server."}, {"start", (PyCFunction)Server_start, METH_NOARGS, "Starts the server's callback loop."}, {"stop", (PyCFunction)Server_stop, METH_NOARGS, "Stops the server's callback loop."}, {"recordOptions", (PyCFunction)Server_recordOptions, METH_VARARGS|METH_KEYWORDS, "Sets format settings for offline rendering and global recording."}, {"recstart", (PyCFunction)Server_start_rec, METH_VARARGS|METH_KEYWORDS, "Start automatic output recording."}, {"recstop", (PyCFunction)Server_stop_rec, METH_NOARGS, "Stop automatic output recording."}, {"addStream", (PyCFunction)Server_addStream, METH_VARARGS, "Adds an audio stream to the server. \ This is for internal use and must never be called by the user."}, {"removeStream", (PyCFunction)Server_removeStream, METH_VARARGS, "Adds an audio stream to the server. \ This is for internal use and must never be called by the user."}, {"changeStreamPosition", (PyCFunction)Server_changeStreamPosition, METH_VARARGS, "Puts an audio stream before another in the stack. \ This is for internal use and must never be called by the user."}, {"noteout", (PyCFunction)Server_noteout, METH_VARARGS, "Send a Midi note event to Portmidi output stream."}, {"afterout", (PyCFunction)Server_afterout, METH_VARARGS, "Send an aftertouch event to Portmidi output stream."}, {"ctlout", (PyCFunction)Server_ctlout, METH_VARARGS, "Send a control change event to Portmidi output stream."}, {"programout", (PyCFunction)Server_programout, METH_VARARGS, "Send a program change event to Portmidi output stream."}, {"pressout", (PyCFunction)Server_pressout, METH_VARARGS, "Send a channel pressure event to Portmidi output stream."}, {"bendout", (PyCFunction)Server_bendout, METH_VARARGS, "Send a pitch bend event to Portmidi output stream."}, {"addMidiEvent", (PyCFunction)Server_addMidiEvent, METH_VARARGS, "Add a midi event manually (without using portmidi callback)."}, {"getStreams", (PyCFunction)Server_getStreams, METH_NOARGS, "Returns the list of streams added to the server."}, {"getSamplingRate", (PyCFunction)Server_getSamplingRate, METH_NOARGS, "Returns the server's sampling rate."}, {"getNchnls", (PyCFunction)Server_getNchnls, METH_NOARGS, "Returns the server's current number of output channels."}, {"getIchnls", (PyCFunction)Server_getIchnls, METH_NOARGS, "Returns the server's current number of input channels."}, {"getGlobalSeed", (PyCFunction)Server_getGlobalSeed, METH_NOARGS, "Returns the server's global seed."}, {"getBufferSize", (PyCFunction)Server_getBufferSize, METH_NOARGS, "Returns the server's buffer size."}, {"getIsBooted", (PyCFunction)Server_getIsBooted, METH_NOARGS, "Returns 1 if the server is booted, otherwise returns 0."}, {"getIsStarted", (PyCFunction)Server_getIsStarted, METH_NOARGS, "Returns 1 if the server is started, otherwise returns 0."}, {"getMidiActive", (PyCFunction)Server_getMidiActive, METH_NOARGS, "Returns 1 if midi callback is active, otherwise returns 0."}, {"_setDefaultRecPath", (PyCFunction)Server_setDefaultRecPath, METH_VARARGS|METH_KEYWORDS, "Sets the default recording path."}, {"setServer", (PyCFunction)Server_setServer, METH_NOARGS, "Sets this server as the one to use for new objects when using the embedded device"}, {"getInputAddr", (PyCFunction)Server_getInputAddr, METH_NOARGS, "Get the embedded device input buffer memory address"}, {"getOutputAddr", (PyCFunction)Server_getOutputAddr, METH_NOARGS, "Get the embedded device output buffer memory address"}, {"getServerID", (PyCFunction)Server_getServerID, METH_NOARGS, "Get the embedded device server memory address"}, {"getServerAddr", (PyCFunction)Server_getServerAddr, METH_NOARGS, "Get the embedded device server memory address"}, {"getEmbedICallbackAddr", (PyCFunction)Server_getEmbedICallbackAddr, METH_NOARGS, "Get the embedded device interleaved callback method memory address"}, {NULL} /* Sentinel */ }; static PyMemberDef Server_members[] = { {"streams", T_OBJECT_EX, offsetof(Server, streams), 0, "Server's streams list."}, {NULL} /* Sentinel */ }; PyTypeObject ServerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Server", /*tp_name*/ sizeof(Server), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Server_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/ "Pyo Server object. Handles communication with Portaudio and processing callback loop.", /* tp_doc */ (traverseproc)Server_traverse, /* tp_traverse */ (inquiry)Server_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Server_methods, /* tp_methods */ Server_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)Server_init, /* tp_init */ 0, /* tp_alloc */ Server_new, /* tp_new */ };pyo/src/engine/inputfadermodule.c0000644000175000017500000002406012652732202016427 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD PyObject *input1; PyObject *input2; Stream *input1_stream; Stream *input2_stream; MYFLT fadetime; int switcher; double currentTime; double sampleToSec; } InputFader; static void InputFader_setProcMode(InputFader *self) {}; static void InputFader_process_only_first(InputFader *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input1_stream); for (i=0; ibufsize; i++) { self->data[i] = in[i]; } } static void InputFader_process_only_second(InputFader *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input2_stream); for (i=0; ibufsize; i++) { self->data[i] = in[i]; } } static void InputFader_process_one(InputFader *self) { int i; MYFLT sclfade, val; MYFLT *in1 = Stream_getData((Stream *)self->input1_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); val = 0.0; sclfade = 1. / self->fadetime; for (i=0; ibufsize; i++) { if (self->currentTime < self->fadetime) { val = MYSQRT(self->currentTime * sclfade); self->currentTime += self->sampleToSec; } else val = 1.; self->data[i] = in1[i] * val + in2[i] * (1 - val); } if (val == 1.) self->proc_func_ptr = InputFader_process_only_first; } static void InputFader_process_two(InputFader *self) { int i; MYFLT sclfade, val; MYFLT *in1 = Stream_getData((Stream *)self->input1_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); val = 0.0; sclfade = 1. / self->fadetime; for (i=0; ibufsize; i++) { if (self->currentTime < self->fadetime) { val = MYSQRT(self->currentTime * sclfade); self->currentTime += self->sampleToSec; } else val = 1.; self->data[i] = in2[i] * val + in1[i] * (1 - val); } if (val == 1.) self->proc_func_ptr = InputFader_process_only_second; } static void InputFader_compute_next_data_frame(InputFader *self) { (*self->proc_func_ptr)(self); } static int InputFader_traverse(InputFader *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input1); Py_VISIT(self->input1_stream); Py_VISIT(self->input2); Py_VISIT(self->input2_stream); return 0; } static int InputFader_clear(InputFader *self) { pyo_CLEAR Py_CLEAR(self->input1); Py_CLEAR(self->input1_stream); Py_CLEAR(self->input2); Py_CLEAR(self->input2_stream); return 0; } static void InputFader_dealloc(InputFader* self) { pyo_DEALLOC InputFader_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * InputFader_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp=NULL, *streamtmp; InputFader *self; self = (InputFader *)type->tp_alloc(type, 0); self->switcher = 0; self->fadetime = 0.05; self->currentTime = 0.0; INIT_OBJECT_COMMON self->sampleToSec = 1. / self->sr; Stream_setFunctionPtr(self->stream, InputFader_compute_next_data_frame); self->mode_func_ptr = InputFader_setProcMode; self->proc_func_ptr = InputFader_process_only_first; static char *kwlist[] = {"input", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &inputtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "server") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument must be a PyoObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input1); self->input1 = inputtmp; streamtmp = PyObject_CallMethod((PyObject *)self->input1, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->input1_stream); self->input1_stream = (Stream *)streamtmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); return (PyObject *)self; } static PyObject * InputFader_setInput(InputFader *self, PyObject *args, PyObject *kwds) { PyObject *tmp, *streamtmp; static char *kwlist[] = {"input", "fadetime", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_F, kwlist, &tmp, &self->fadetime)) Py_RETURN_NONE; self->switcher = (self->switcher + 1) % 2; self->currentTime = 0.0; if (self->fadetime == 0) self->fadetime = 0.0001; Py_INCREF(tmp); if (self->switcher == 0) { Py_DECREF(self->input1); self->input1 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->input1, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->input1_stream); self->input1_stream = (Stream *)streamtmp; self->proc_func_ptr = InputFader_process_one; } else { Py_XDECREF(self->input2); self->input2 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (Stream *)streamtmp; self->proc_func_ptr = InputFader_process_two; } Py_INCREF(Py_None); return Py_None; } static PyObject * InputFader_getServer(InputFader* self) { GET_SERVER }; static PyObject * InputFader_getStream(InputFader* self) { GET_STREAM }; static PyObject * InputFader_play(InputFader *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * InputFader_out(InputFader *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * InputFader_stop(InputFader *self) { STOP }; static PyMemberDef InputFader_members[] = { {"server", T_OBJECT_EX, offsetof(InputFader, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(InputFader, stream), 0, "Stream object."}, {"input1", T_OBJECT_EX, offsetof(InputFader, input1), 0, "First input."}, {"input2", T_OBJECT_EX, offsetof(InputFader, input2), 0, "Second input."}, {NULL} /* Sentinel */ }; static PyMethodDef InputFader_methods[] = { {"getServer", (PyCFunction)InputFader_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)InputFader_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)InputFader_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)InputFader_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setInput", (PyCFunction)InputFader_setInput, METH_VARARGS|METH_KEYWORDS, "Crossfade between current stream and given stream."}, {"stop", (PyCFunction)InputFader_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject InputFaderType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.InputFader_base", /*tp_name*/ sizeof(InputFader), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)InputFader_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "InputFader objects. Generates a crossfade between current input sound stream and new input sound stream.", /* tp_doc */ (traverseproc)InputFader_traverse, /* tp_traverse */ (inquiry)InputFader_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ InputFader_methods, /* tp_methods */ InputFader_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ InputFader_new, /* tp_new */ }; pyo/src/engine/interpolation.c0000644000175000017500000000511612652732202015750 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include "interpolation.h" #include "pyomodule.h" #include MYFLT nointerp(MYFLT *buf, int index, MYFLT frac, int size) { return buf[index]; } MYFLT linear(MYFLT *buf, int index, MYFLT frac, int size) { MYFLT x1 = buf[index]; MYFLT x2 = buf[index+1]; return (x1 + (x2 - x1) * frac); } MYFLT cosine(MYFLT *buf, int index, MYFLT frac, int size) { MYFLT frac2; MYFLT x1 = buf[index]; MYFLT x2 = buf[index+1]; frac2 = (1.0 - MYCOS(frac * M_PI)) * 0.5; return (x1 + (x2 - x1) * frac2); } MYFLT cubic(MYFLT *buf, int index, MYFLT frac, int size) { MYFLT x0, x3, a0, a1, a2, a3; MYFLT x1 = buf[index]; MYFLT x2 = buf[index+1]; if (index == 0) { x0 = x1 + (x1 - x2); x3 = buf[index + 2]; } else if (index >= (size-2)) { x0 = buf[index - 1]; x3 = x2 + (x2 - x1); } else { x0 = buf[index - 1]; x3 = buf[index + 2]; } a3 = frac * frac; a3 -= 1.0; a3 *= (1.0 / 6.0); a2 = (frac + 1.0) * 0.5; a0 = a2 - 1.0; a1 = a3 * 3.0; a2 -= a1; a0 -= a3; a1 -= frac; a0 *= frac; a1 *= frac; a2 *= frac; a3 *= frac; a1 += 1.0; return (a0*x0+a1*x1+a2*x2+a3*x3); }pyo/src/engine/pvstreammodule.c0000644000175000017500000000714212652732202016131 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #define __PV_STREAM_MODULE #include "pvstreammodule.h" #undef __PV_STREAM_MODULE /************************/ /* PVStream object */ /************************/ static void PVStream_dealloc(PVStream* self) { self->magn = NULL; self->freq = NULL; self->ob_type->tp_free((PyObject*)self); } int PVStream_getFFTsize(PVStream *self) { return self->fftsize; } int PVStream_getOlaps(PVStream *self) { return self->olaps; } MYFLT ** PVStream_getMagn(PVStream *self) { return (MYFLT **)self->magn; } MYFLT ** PVStream_getFreq(PVStream *self) { return (MYFLT **)self->freq; } int * PVStream_getCount(PVStream *self) { return (int *)self->count; } void PVStream_setFFTsize(PVStream *self, int fftsize) { self->fftsize = fftsize; } void PVStream_setOlaps(PVStream *self, int olaps) { self->olaps = olaps; } void PVStream_setMagn(PVStream *self, MYFLT **data) { self->magn = data; } void PVStream_setFreq(PVStream *self, MYFLT **data) { self->freq = data; } void PVStream_setCount(PVStream *self, int *data) { self->count = data; } PyTypeObject PVStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "pyo.PVStream", /*tp_name*/ sizeof(PVStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "\n\ Phase Vocoder stream object. For internal use only. \n\n\ ", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ };pyo/src/engine/fft.c0000644000175000017500000003770512652732202013651 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ /****************************************************** ** FFT library ** ** (one-dimensional complex and real FFTs for array ** lengths of 2^n) ** ** Author: Toth Laszlo (tothl@inf.u-szeged.hu) ** ** Research Group on Artificial Intelligence ** H-6720 Szeged, Aradi vertanuk tere 1, Hungary ** ** Last modified: 97.05.29 ** ** Modified by belangeo 2011.05.25 ** - Added twiddle factors lookup table (radix-2) ** - Added twiddle factors 2d lookup table (split-radix) ** ** Original file can be found on musicdsp.org : ** http://www.musicdsp.org/archive.php?classid=2#79 ****************************************************** */ #include "fft.h" #include "pyomodule.h" #include void fft_compute_split_twiddle(MYFLT **twiddle, int size) { /* pre-compute split-radix twiddle factors in 2d array of length [4][size>>3] */ int j; int n8 = size >> 3; MYFLT e = 2.0 * PI / size; MYFLT a = e; MYFLT a3; for(j=2; j<=n8; j++) { a3 = 3 * a; twiddle[0][j-1] = MYCOS(a); twiddle[1][j-1] = MYSIN(a); twiddle[2][j-1] = MYCOS(a3); twiddle[3][j-1] = MYSIN(a3); a = j * e; } return; } void fft_compute_radix2_twiddle(MYFLT *twiddle, int size) { /* pre-compute radix-2 twiddle factors in one array of length n */ /* re[0], re[1], ..., re[n/2-1], im[0], im[1], ..., im[n/2-1] */ int i; int hsize = size / 2; for (i=0; i>= 1; } j += k; } /* length two butterflies */ i0 = 0; id = 4; do { for (; i02; k>>=1) { n2 <<= 1; /* power of two from 4 to n */ n4 = n2 >> 2; n8 = n2 >> 3; pas = n / n2; i1 = 0; id = n2 << 1; do { for (; i12; k>>=1) { id = n2; n2 >>= 1; n4 = n2 >> 2; n8 = n2 >> 3; pas = n / n2; i1 = 0; do { for (; i1>= 1; } j += k; } for (i=0; i1; dl>>=1, astep+=astep) { l1 = data; l2 = data + dl; for(;l2> 1; end = data + size + size; for(dl=2; astep>0; dl+=dl, astep>>=1) { l1 = data; l2 = data + dl; for(; l2> 1; for (i=0, j=0; i>= 1; } j += k; } } /* ***************************************************** ** used by realfft ** parameters as above ** ** Source: Brigham: The Fast Fourier Transform ** Prentice Hall, ? ***************************************************** */ void realize(MYFLT *data, int size) { MYFLT xr,yr,xi,yi,wr,wi,dr,di,ang,astep; MYFLT *l1, *l2; l1 = data; l2 = data + size + size - 2; xr = *l1; xi = *(l1+1); *l1 = xr + xi; *(l1+1) = xr - xi; l1 += 2; astep = PI / size; for(ang=astep; l1<=l2; l1+=2, l2-=2, ang+=astep) { xr = (*l1 + *l2) / 2; yi = (-(*l1) + (*l2)) / 2; yr = (*(l1+1) + *(l2+1)) / 2; xi = (*(l1+1) - *(l2+1)) / 2; wr = cos(ang); wi = -sin(ang); dr = yr * wr - yi * wi; di = yr * wi + yi * wr; *l1 = xr + dr; *(l1+1) = xi + di; *l2 = xr - dr; *(l2+1) = -xi + di; } } /* ***************************************************** ** used by inverse realfft ** parameters as above ** ** Source: Brigham: The Fast Fourier Transform ** Prentice Hall, ? ****************************************************** */ void unrealize(MYFLT *data, int size) { MYFLT xr,yr,xi,yi,wr,wi,dr,di,ang,astep; MYFLT *l1, *l2; l1 = data; l2 = data + size + size - 2; xr = (*l1) / 2; xi = (*(l1+1)) / 2; *l1 = xr + xi; *(l1+1) = xr - xi; l1 += 2; astep = PI / size; for(ang=astep; l1<=l2; l1+=2, l2-=2, ang+=astep){ xr = (*l1+*l2) / 2; yi = -(-(*l1) + (*l2)) / 2; yr = (*(l1+1) + *(l2+1)) / 2; xi = (*(l1+1) - *(l2+1)) / 2; wr = cos(ang); wi = -sin(ang); dr = yr * wr - yi * wi; di = yr * wi + yi * wr; *l2 = xr + dr; *(l1+1) = xi + di; *l1 = xr - dr; *(l2+1) = -xi + di; } } /* ***************************************************** ** in-place Radix-2 FFT for real values ** (by the so-called "packing method") ** data: array of doubles: ** re(0),re(1),re(2),...,re(size-1) ** ** output: ** re(0),re(size/2),re(1),im(1),re(2),im(2),...,re(size/2-1),im(size/2-1) ** normalized by array length ** ** Source: see the routines it calls ... ******************************************************* */ void realfft_packed(MYFLT *data, MYFLT *outdata, int size, MYFLT *twiddle) { int i; size >>= 1; dif_butterfly(data, size, twiddle); unshuffle(data, size); realize(data, size); size <<= 1; for (i=0; i>= 1; unrealize(data, size); unshuffle(data, size); inverse_dit_butterfly(data, size, twiddle); size <<= 1; for (i=0; i. * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD PyObject *input; int modebuffer[2]; } Mix; static void Mix_postprocessing_ii(Mix *self) { POST_PROCESSING_II }; static void Mix_postprocessing_ai(Mix *self) { POST_PROCESSING_AI }; static void Mix_postprocessing_ia(Mix *self) { POST_PROCESSING_IA }; static void Mix_postprocessing_aa(Mix *self) { POST_PROCESSING_AA }; static void Mix_postprocessing_ireva(Mix *self) { POST_PROCESSING_IREVA }; static void Mix_postprocessing_areva(Mix *self) { POST_PROCESSING_AREVA }; static void Mix_postprocessing_revai(Mix *self) { POST_PROCESSING_REVAI }; static void Mix_postprocessing_revaa(Mix *self) { POST_PROCESSING_REVAA }; static void Mix_postprocessing_revareva(Mix *self) { POST_PROCESSING_REVAREVA }; static void Mix_setProcMode(Mix *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Mix_postprocessing_ii; break; case 1: self->muladd_func_ptr = Mix_postprocessing_ai; break; case 2: self->muladd_func_ptr = Mix_postprocessing_revai; break; case 10: self->muladd_func_ptr = Mix_postprocessing_ia; break; case 11: self->muladd_func_ptr = Mix_postprocessing_aa; break; case 12: self->muladd_func_ptr = Mix_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Mix_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Mix_postprocessing_areva; break; case 22: self->muladd_func_ptr = Mix_postprocessing_revareva; break; } } static void Mix_compute_next_data_frame(Mix *self) { int i, j; MYFLT old; PyObject *stream; Py_ssize_t lsize = PyList_Size(self->input); MYFLT buffer[self->bufsize]; memset(&buffer, 0, sizeof(buffer)); for (i=0; iinput, i), "_getStream", NULL); MYFLT *in = Stream_getData((Stream *)stream); for (j=0; jbufsize; j++) { old = buffer[j]; buffer[j] = in[j] + old; } } for (i=0; ibufsize; i++) { self->data[i] = buffer[i]; } (*self->muladd_func_ptr)(self); } static int Mix_traverse(Mix *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); return 0; } static int Mix_clear(Mix *self) { pyo_CLEAR Py_CLEAR(self->input); return 0; } static void Mix_dealloc(Mix* self) { pyo_DEALLOC Mix_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Mix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp=NULL, *multmp=NULL, *addtmp=NULL; Mix *self; self = (Mix *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Mix_compute_next_data_frame); self->mode_func_ptr = Mix_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Mix_getServer(Mix* self) { GET_SERVER }; static PyObject * Mix_getStream(Mix* self) { GET_STREAM }; static PyObject * Mix_setMul(Mix *self, PyObject *arg) { SET_MUL }; static PyObject * Mix_setAdd(Mix *self, PyObject *arg) { SET_ADD }; static PyObject * Mix_setSub(Mix *self, PyObject *arg) { SET_SUB }; static PyObject * Mix_setDiv(Mix *self, PyObject *arg) { SET_DIV }; static PyObject * Mix_play(Mix *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Mix_out(Mix *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Mix_stop(Mix *self) { STOP }; static PyObject * Mix_multiply(Mix *self, PyObject *arg) { MULTIPLY }; static PyObject * Mix_inplace_multiply(Mix *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Mix_add(Mix *self, PyObject *arg) { ADD }; static PyObject * Mix_inplace_add(Mix *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Mix_sub(Mix *self, PyObject *arg) { SUB }; static PyObject * Mix_inplace_sub(Mix *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Mix_div(Mix *self, PyObject *arg) { DIV }; static PyObject * Mix_inplace_div(Mix *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Mix_members[] = { {"server", T_OBJECT_EX, offsetof(Mix, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Mix, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Mix, input), 0, "List of input signals to mix."}, {"mul", T_OBJECT_EX, offsetof(Mix, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Mix, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Mix_methods[] = { {"getServer", (PyCFunction)Mix_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Mix_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Mix_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Mix_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Mix_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Mix_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Mix_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Mix_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Mix_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Mix_as_number = { (binaryfunc)Mix_add, /*nb_add*/ (binaryfunc)Mix_sub, /*nb_subtract*/ (binaryfunc)Mix_multiply, /*nb_multiply*/ (binaryfunc)Mix_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Mix_inplace_add, /*inplace_add*/ (binaryfunc)Mix_inplace_sub, /*inplace_subtract*/ (binaryfunc)Mix_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Mix_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject MixType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Mix_base", /*tp_name*/ sizeof(Mix), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Mix_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Mix_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Mix objects. Retreive audio from an input channel.", /* tp_doc */ (traverseproc)Mix_traverse, /* tp_traverse */ (inquiry)Mix_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Mix_methods, /* tp_methods */ Mix_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Mix_new, /* tp_new */ }; pyo/src/engine/streammodule.c0000644000175000017500000002013312652732202015556 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #define __STREAM_MODULE #include "streammodule.h" #undef __STREAM_MODULE int stream_id = 1; int Stream_getNewStreamId() { return stream_id++; } static int Stream_traverse(Stream *self, visitproc visit, void *arg) { Py_VISIT(self->streamobject); return 0; } static int Stream_clear(Stream *self) { Py_CLEAR(self->streamobject); return 0; } static void Stream_dealloc(Stream* self) { self->data = NULL; Stream_clear(self); self->ob_type->tp_free((PyObject*)self); } int Stream_getStreamId(Stream *self) { return self->sid; } int Stream_getStreamActive(Stream *self) { return self->active; } int Stream_getStreamChnl(Stream *self) { return self->chnl; } int Stream_getStreamToDac(Stream *self) { return self->todac; } int Stream_getBufferCountWait(Stream *self) { return self->bufferCountWait; } int Stream_getDuration(Stream *self) { return self->duration; } MYFLT * Stream_getData(Stream *self) { return (MYFLT *)self->data; } void Stream_setData(Stream *self, MYFLT *data) { self->data = data; } void Stream_setFunctionPtr(Stream *self, void *ptr) { self->funcptr = ptr; } void Stream_callFunction(Stream *self) { (*self->funcptr)(self->streamobject); } void Stream_IncrementBufferCount(Stream *self) { self->bufferCount++; if (self->bufferCount >= self->bufferCountWait) { self->active = 1; self->bufferCountWait = self->bufferCount = 0; } } void Stream_IncrementDurationCount(Stream *self) { self->bufferCount++; if (self->bufferCount >= self->duration) { PyObject_CallMethod((PyObject *)Stream_getStreamObject(self), "stop", NULL); self->duration = self->bufferCount = 0; } } static PyObject * Stream_getValue(Stream *self) { return Py_BuildValue(TYPE_F, self->data[self->bufsize-1]); } static PyObject * Stream_getId(Stream *self) { return Py_BuildValue("i", self->sid); } PyObject * Stream_getStreamObject(Stream *self) { Py_INCREF(self->streamobject); return self->streamobject; } PyObject * Stream_isPlaying(Stream *self) { if (self->active || self->todac) { Py_INCREF(Py_True); return Py_True; } else { Py_INCREF(Py_False); return Py_False; } } PyObject * Stream_isOutputting(Stream *self) { if (self->todac) { Py_INCREF(Py_True); return Py_True; } else { Py_INCREF(Py_False); return Py_False; } } static PyMethodDef Stream_methods[] = { {"getValue", (PyCFunction)Stream_getValue, METH_NOARGS, "Returns the first sample of the current buffer."}, {"getId", (PyCFunction)Stream_getId, METH_NOARGS, "Returns the ID of assigned to this stream."}, {"getStreamObject", (PyCFunction)Stream_getStreamObject, METH_NOARGS, "Returns the object associated with this stream."}, {"isPlaying", (PyCFunction)Stream_isPlaying, METH_NOARGS, "Returns True if the stream is playing, otherwise, returns False."}, {"isOutputting", (PyCFunction)Stream_isOutputting, METH_NOARGS, "Returns True if the stream outputs to dac, otherwise, returns False."}, {NULL} /* Sentinel */ }; PyTypeObject StreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "pyo.Stream", /*tp_name*/ sizeof(Stream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Stream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "\n\ Audio stream objects. For internal use only. \n\n\ A Stream object must never be instantiated by the user. \n\n\ A Stream is a mono buffer of audio samples. It is used to pass \n\ audio between objects and the server. A PyoObject can manage many \n\ streams if, for example, a list is given to a parameter. \n\n\ A Sine object with only one stream:\n\n\ a = Sine(freq=1000)\n\n\ len(a)\n\n\ 1\n\n\n\ A Sine object with four streams:\n\n\ a = Sine(freq=[250,500,750,100])\n\n\ len(a)\n\n\ 4\n\n\n\ The first stream of this object contains the samples from the 250Hz waveform.\n\ The second stream contains the samples from the 500Hz waveform, and so on.\n\n\ User can call a specific stream of an object by giving the position of the stream\n\ between brackets, beginning at 0. To retrieve only the third stream of our object:\n\n\ a[2].out()\n\n\ The method getStreamObject() can be called on a Stream object to retrieve the \n\ XXX_base object associated with this Stream. This method can be used by developers who\n\ are debugging their programs!\n\n\ ", /* tp_doc */ (traverseproc)Stream_traverse, /* tp_traverse */ (inquiry)Stream_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Stream_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; /************************/ /* TriggerStream object */ /************************/ static void TriggerStream_dealloc(TriggerStream* self) { self->data = NULL; self->ob_type->tp_free((PyObject*)self); } MYFLT * TriggerStream_getData(TriggerStream *self) { return (MYFLT *)self->data; } void TriggerStream_setData(TriggerStream *self, MYFLT *data) { self->data = data; } PyTypeObject TriggerStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "pyo.TriggerStream", /*tp_name*/ sizeof(TriggerStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TriggerStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "\n\ Trigger stream object. For internal use only. \n\n\ ", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ };pyo/src/engine/listenermodule.c0000644000175000017500000003742012652732202016117 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "portmidi.h" #include "porttime.h" #include "lo/lo.h" static void error(int num, const char *msg, const char *path) { printf("liblo server error %d in path %s: %s\n", num, path, msg); } typedef struct { PyObject_HEAD PyObject *osccallable; lo_server osc_server; int oscport; } OscListener; static PyObject * OscListener_get(OscListener *self) { while (lo_server_recv_noblock(self->osc_server, 0) != 0) {}; Py_INCREF(Py_None); return Py_None; } int process_osc(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { OscListener *server = (OscListener *)user_data; PyObject *tup; lo_blob *blob = NULL; char *blobdata = NULL; uint32_t blobsize = 0; PyObject *charlist = NULL; tup = PyTuple_New(argc+1); int i, j = 0; PyGILState_STATE s = PyGILState_Ensure(); PyTuple_SET_ITEM(tup, 0, PyString_FromString(path)); for (i=0; ii)); break; case LO_INT64: PyTuple_SET_ITEM(tup, i+1, PyLong_FromLong(argv[i]->h)); break; case LO_FLOAT: PyTuple_SET_ITEM(tup, i+1, PyFloat_FromDouble(argv[i]->f)); break; case LO_DOUBLE: PyTuple_SET_ITEM(tup, i+1, PyFloat_FromDouble(argv[i]->d)); break; case LO_STRING: PyTuple_SET_ITEM(tup, i+1, PyString_FromString(&argv[i]->s)); break; case LO_CHAR: PyTuple_SET_ITEM(tup, i+1, PyString_FromFormat("%c", argv[i]->c)); break; case LO_BLOB: blob = (lo_blob)argv[i]; blobsize = lo_blob_datasize(blob); blobdata = lo_blob_dataptr(blob); charlist = PyList_New(blobsize); for (j=0; jm[j])); } PyTuple_SET_ITEM(tup, i+1, charlist); break; case LO_NIL: Py_INCREF(Py_None); PyTuple_SET_ITEM(tup, i+1, Py_None); break; case LO_TRUE: Py_INCREF(Py_True); PyTuple_SET_ITEM(tup, i+1, Py_True); break; case LO_FALSE: Py_INCREF(Py_False); PyTuple_SET_ITEM(tup, i+1, Py_False); break; default: break; } } PyObject_Call((PyObject *)server->osccallable, tup, NULL); PyGILState_Release(s); Py_XDECREF(tup); return 0; } static int OscListener_traverse(OscListener *self, visitproc visit, void *arg) { Py_VISIT(self->osccallable); return 0; } static int OscListener_clear(OscListener *self) { Py_CLEAR(self->osccallable); return 0; } static void OscListener_dealloc(OscListener* self) { lo_server_free(self->osc_server); OscListener_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * OscListener_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { char buf[20]; PyObject *osccalltmp=NULL; OscListener *self; self = (OscListener *)type->tp_alloc(type, 0); static char *kwlist[] = {"osccallable", "port", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi", kwlist, &osccalltmp, &self->oscport)) Py_RETURN_NONE; if (osccalltmp) { PyObject_CallMethod((PyObject *)self, "setOscFunction", "O", osccalltmp); } sprintf(buf, "%i", self->oscport); self->osc_server = lo_server_new(buf, error); lo_server_add_method(self->osc_server, NULL, NULL, process_osc, (void *)self); return (PyObject *)self; } static PyObject * OscListener_setOscFunction(OscListener *self, PyObject *arg) { PyObject *tmp; if (arg == Py_None) { Py_INCREF(Py_None); return Py_None; } if (! PyCallable_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function."); Py_INCREF(Py_None); return Py_None; } tmp = arg; Py_XDECREF(self->osccallable); Py_INCREF(tmp); self->osccallable = tmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef OscListener_members[] = { {NULL} /* Sentinel */ }; static PyMethodDef OscListener_methods[] = { {"get", (PyCFunction)OscListener_get, METH_NOARGS, "Check for new osc messages."}, {"setOscFunction", (PyCFunction)OscListener_setOscFunction, METH_O, "Sets the function to be called."}, {NULL} /* Sentinel */ }; PyTypeObject OscListenerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.OscListener_base", /*tp_name*/ sizeof(OscListener), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)OscListener_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "OscListener objects. Calls a function with OSC data as arguments.", /* tp_doc */ (traverseproc)OscListener_traverse, /* tp_traverse */ (inquiry)OscListener_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ OscListener_methods, /* tp_methods */ OscListener_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ OscListener_new, /* tp_new */ }; typedef struct { PyObject_HEAD PyObject *midicallable; PmStream *midiin[64]; int mididev; int midicount; int active; } MidiListener; void process_midi(PtTimestamp timestamp, void *userData) { PmError result; PmEvent buffer; /* just one message at a time */ int i, status, data1, data2; PyObject *tup = NULL; MidiListener *server = (MidiListener *)userData; if (server->active == 0) return; PyGILState_STATE s = PyGILState_Ensure(); do { for (i=0; imidicount; i++) { result = Pm_Poll(server->midiin[i]); if (result) { if (Pm_Read(server->midiin[i], &buffer, 1) == pmBufferOverflow) continue; status = Pm_MessageStatus(buffer.message); data1 = Pm_MessageData1(buffer.message); data2 = Pm_MessageData2(buffer.message); tup = PyTuple_New(3); PyTuple_SetItem(tup, 0, PyInt_FromLong(status)); PyTuple_SetItem(tup, 1, PyInt_FromLong(data1)); PyTuple_SetItem(tup, 2, PyInt_FromLong(data2)); PyObject_Call((PyObject *)server->midicallable, tup, NULL); } } } while (result); PyGILState_Release(s); Py_XDECREF(tup); } static int MidiListener_traverse(MidiListener *self, visitproc visit, void *arg) { Py_VISIT(self->midicallable); return 0; } static int MidiListener_clear(MidiListener *self) { Py_CLEAR(self->midicallable); return 0; } static void MidiListener_dealloc(MidiListener* self) { if (self->active == 1) PyObject_CallMethod((PyObject *)self, "stop", NULL); MidiListener_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * MidiListener_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *midicalltmp=NULL; MidiListener *self; self = (MidiListener *)type->tp_alloc(type, 0); self->active = self->midicount = 0; self->mididev = -1; static char *kwlist[] = {"midicallable", "mididevice", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi", kwlist, &midicalltmp, &self->mididev)) Py_RETURN_NONE; if (midicalltmp) { PyObject_CallMethod((PyObject *)self, "setMidiFunction", "O", midicalltmp); } return (PyObject *)self; } static PyObject * MidiListener_play(MidiListener *self) { int i, num_devices; PmError pmerr; /* always start the timer before you start midi */ Pt_Start(1, &process_midi, (void *)self); pmerr = Pm_Initialize(); if (pmerr) { printf("Portmidi warning: could not initialize Portmidi: %s\n", Pm_GetErrorText(pmerr)); } num_devices = Pm_CountDevices(); if (num_devices > 0) { if (self->mididev < num_devices) { if (self->mididev == -1) self->mididev = Pm_GetDefaultInputDeviceID(); const PmDeviceInfo *info = Pm_GetDeviceInfo(self->mididev); if (info != NULL) { if (info->input) { pmerr = Pm_OpenInput(&self->midiin[0], self->mididev, NULL, 100, NULL, NULL); if (pmerr) { printf("Portmidi warning: could not open midi input %d (%s): %s\n", self->mididev, info->name, Pm_GetErrorText(pmerr)); } else { self->midicount = 1; } } } } else if (self->mididev >= num_devices) { self->midicount = 0; for (i=0; iinput) { pmerr = Pm_OpenInput(&self->midiin[self->midicount], i, NULL, 100, NULL, NULL); if (pmerr) { printf("Portmidi warning: could not open midi input %d (%s): %s\n", i, info->name, Pm_GetErrorText(pmerr)); } else { self->midicount++; } } } } } } for (i=0; imidicount; i++) { Pm_SetFilter(self->midiin[i], PM_FILT_ACTIVE | PM_FILT_CLOCK); } if (self->midicount > 0) self->active = 1; Py_INCREF(Py_None); return Py_None; }; static PyObject * MidiListener_stop(MidiListener *self) { int i; Pt_Stop(); for (i=0; imidicount; i++) { Pm_Close(self->midiin[i]); } Pm_Terminate(); self->active = 0; Py_INCREF(Py_None); return Py_None; }; static PyObject * MidiListener_setMidiFunction(MidiListener *self, PyObject *arg) { PyObject *tmp; if (! PyCallable_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function."); Py_INCREF(Py_None); return Py_None; } tmp = arg; Py_XDECREF(self->midicallable); Py_INCREF(tmp); self->midicallable = tmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef MidiListener_members[] = { {NULL} /* Sentinel */ }; static PyMethodDef MidiListener_methods[] = { {"play", (PyCFunction)MidiListener_play, METH_NOARGS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)MidiListener_stop, METH_NOARGS, "Stops computing."}, {"setMidiFunction", (PyCFunction)MidiListener_setMidiFunction, METH_O, "Sets the function to be called."}, {NULL} /* Sentinel */ }; PyTypeObject MidiListenerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.MidiListener_base", /*tp_name*/ sizeof(MidiListener), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)MidiListener_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "MidiListener objects. Calls a function with midi data as arguments.", /* tp_doc */ (traverseproc)MidiListener_traverse, /* tp_traverse */ (inquiry)MidiListener_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ MidiListener_methods, /* tp_methods */ MidiListener_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MidiListener_new, /* tp_new */ }; pyo/src/engine/wind.c0000644000175000017500000001221312652732202014016 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * * * * Envelope window generator : * * 0 : Rectangular (no window) * * 1 : Hamming * * 2 : Hanning * * 3 : Bartlett (triangular) * * 4 : Blackman 3-term * * 5 : Blackman-Harris 4-term * * 6 : Blackman-Harris 7-term * * 7 : Tuckey (alpha = 0.66) * * 8 : Sine (half-sine window) * *************************************************************************/ #include "wind.h" #include "pyomodule.h" #include void gen_window(MYFLT *window, int size, int wintype) { int i; MYFLT arg; switch (wintype) { case 0: /* Rectangular */ for (i=0; i. * *************************************************************************/ #include #include #include "portaudio.h" #include "sndfile.h" #include "pyomodule.h" #include "servermodule.h" #include "streammodule.h" #include "pvstreammodule.h" #include "dummymodule.h" #include "tablemodule.h" #include "matrixmodule.h" /** Note : ** Add an argument to pa_get_* and pm_get_* functions to allow printing to the console **/ /****** Portaudio utilities ******/ static void portaudio_assert(PaError ecode, const char* cmdName) { if (ecode != paNoError) { const char* eText = Pa_GetErrorText(ecode); if (!eText) { eText = "???"; } fprintf(stderr, "portaudio error in %s: %s\n", cmdName, eText); Pa_Terminate(); } } #define portaudio_count_host_apis_info \ "\nReturns the number of host apis found by Portaudio.\n\n\ >>> c = pa_count_host_apis()\n\ >>> print c\n\ 1\n\n" #define portaudio_get_version_info \ "\nReturns the version number, as an integer, of the current portaudio installation.\n\n\ >>> v = pa_get_version()\n\ >>> print v\n\ 1899\n\n" static PyObject * portaudio_get_version() { return PyInt_FromLong(Pa_GetVersion()); } #define portaudio_get_version_text_info \ "\nReturns the textual description of the current portaudio installation.\n\n\ >>> desc = pa_get_version_text()\n\ >>> print desc\n\ PortAudio V19-devel (built Oct 8 2012 16:25:16)\n\n" static PyObject * portaudio_get_version_text() { return PyString_FromString(Pa_GetVersionText()); } static PyObject * portaudio_count_host_apis(){ PaError err; PaHostApiIndex numApis; err = Pa_Initialize(); if (err != paNoError) { portaudio_assert(err, "Pa_Initialize"); Py_RETURN_NONE; } else { numApis = Pa_GetHostApiCount(); if( numApis < 0 ) portaudio_assert(numApis, "Pa_GetHostApiCount"); return PyInt_FromLong(numApis); } } #define portaudio_list_host_apis_info \ "\nPrints a list of all host apis found by Portaudio.\n\n\ >>> pa_list_host_apis()\n\ index: 0, id: 5, name: Core Audio, num devices: 6, default in: 0, default out: 2\n\n" static PyObject* portaudio_list_host_apis(){ PaError err; PaHostApiIndex n, i; err = Pa_Initialize(); if (err != paNoError) { portaudio_assert(err, "Pa_Initialize"); } else { n = Pa_GetHostApiCount(); if (n < 0){ portaudio_assert(n, "Pa_GetHostApiCount"); } else { for (i=0; i < n; ++i){ const PaHostApiInfo *info = Pa_GetHostApiInfo(i); assert(info); fprintf(stdout, "index: %i, id: %i, name: %s, num devices: %i, default in: %i, default out: %i\n", i, (int)info->type, info->name, (int)info->deviceCount, (int)info->defaultInputDevice, (int)info->defaultOutputDevice); } } } Py_RETURN_NONE; } #define portaudio_get_default_host_api_info \ "\nReturns the index number of Portaudio's default host api.\n\n\ >>> h = pa_get_default_host_api()\n\ >>> print h\n\ 0\n\n" static PyObject* portaudio_get_default_host_api(){ PaError err; PaHostApiIndex i; err = Pa_Initialize(); if (err != paNoError) { portaudio_assert(err, "Pa_Initialize"); Py_RETURN_NONE; } else { i = Pa_GetDefaultHostApi(); return PyInt_FromLong(i); } } #define portaudio_count_devices_info \ "\nReturns the number of devices found by Portaudio.\n\n\ >>> c = pa_count_devices()\n\ >>> print c\n\ 6\n\n" static PyObject* portaudio_count_devices(){ PaError err; PaDeviceIndex numDevices; err = Pa_Initialize(); if (err != paNoError) { portaudio_assert(err, "Pa_Initialize"); Py_RETURN_NONE; } else { numDevices = Pa_GetDeviceCount(); if( numDevices < 0 ) portaudio_assert(numDevices, "Pa_GetDeviceCount"); return PyInt_FromLong(numDevices); } } #define portaudio_list_devices_info \ "\nPrints a list of all devices found by Portaudio.\n\n\ >>> pa_list_devices()\n\ AUDIO devices:\n\ 0: IN, name: Built-in Microphone, host api index: 0, default sr: 44100 Hz, latency: 0.001088 s\n\ 1: IN, name: Built-in Input, host api index: 0, default sr: 44100 Hz, latency: 0.001088 s\n\ 2: OUT, name: Built-in Output, host api index: 0, default sr: 44100 Hz, latency: 0.001088 s\n\ 3: IN, name: UA-4FX, host api index: 0, default sr: 44100 Hz, latency: 0.010000 s\n\ 3: OUT, name: UA-4FX, host api index: 0, default sr: 44100 Hz, latency: 0.003061 s\n\ 4: IN, name: Soundflower (2ch), host api index: 0, default sr: 44100 Hz, latency: 0.010000 s\n\ 4: OUT, name: Soundflower (2ch), host api index: 0, default sr: 44100 Hz, latency: 0.000000 s\n\ 5: IN, name: Soundflower (16ch), host api index: 0, default sr: 44100 Hz, latency: 0.010000 s\n\ 5: OUT, name: Soundflower (16ch), host api index: 0, default sr: 44100 Hz, latency: 0.000000 s\n\n" static PyObject* portaudio_list_devices(){ PaError err; PaDeviceIndex n, i; err = Pa_Initialize(); if (err != paNoError) { portaudio_assert(err, "Pa_Initialize"); Py_RETURN_NONE; } else { n = Pa_GetDeviceCount(); if (n < 0){ portaudio_assert(n, "Pa_GetDeviceCount"); } else { printf("AUDIO devices:\n"); for (i=0; i < n; ++i){ const PaDeviceInfo *info = Pa_GetDeviceInfo(i); assert(info); if (info->maxInputChannels > 0) fprintf(stdout, "%i: IN, name: %s, host api index: %i, default sr: %i Hz, latency: %f s\n", i, info->name, (int)info->hostApi, (int)info->defaultSampleRate, (float)info->defaultLowInputLatency); if (info->maxOutputChannels > 0) fprintf(stdout, "%i: OUT, name: %s, host api index: %i, default sr: %i Hz, latency: %f s\n", i, info->name, (int)info->hostApi, (int)info->defaultSampleRate, (float)info->defaultLowOutputLatency); } printf("\n"); } } Py_RETURN_NONE; } #define portaudio_get_devices_infos_info \ "\nReturns informations about all devices found by Portaudio.\n\n\ This function returns two dictionaries, one containing a dictionary for each input device and one containing a dictionary for each output device.\ Keys of outer dictionaries are the device index as returned by Portaudio. Keys of inner dictionaries are: 'name', 'host api index', 'default sr' and 'latency'.\n\n\ >>> inputs, outputs = pa_get_devices_infos()\n\ >>> print '- Inputs:'\n\ >>> for index in sorted(inputs.keys()):\n\ ... print ' Device index:', index\n\ ... for key in ['name', 'host api index', 'default sr', 'latency']:\n\ ... print ' %s:' % key, inputs[index][key]\n\ >>> print '- Outputs:'\n\ >>> for index in sorted(outputs.keys()):\n\ ... print ' Device index:', index\n\ ... for key in ['name', 'host api index', 'default sr', 'latency']:\n\ ... print ' %s:' % key, outputs[index][key]\n\n" static PyObject* portaudio_get_devices_infos(){ PaError err; PaDeviceIndex n, i; PyObject *inDict, *outDict, *tmpDict; inDict = PyDict_New(); outDict = PyDict_New(); err = Pa_Initialize(); if (err != paNoError) { portaudio_assert(err, "Pa_Initialize"); Py_RETURN_NONE; } else { n = Pa_GetDeviceCount(); if (n < 0){ portaudio_assert(n, "Pa_GetDeviceCount"); Py_RETURN_NONE; } else { for (i=0; i < n; ++i){ const PaDeviceInfo *info = Pa_GetDeviceInfo(i); assert(info); tmpDict = PyDict_New(); if (info->maxInputChannels > 0) { PyDict_SetItemString(tmpDict, "name", PyString_FromString(info->name)); PyDict_SetItemString(tmpDict, "host api index", PyInt_FromLong((int)info->hostApi)); PyDict_SetItemString(tmpDict, "default sr", PyInt_FromLong((int)info->defaultSampleRate)); PyDict_SetItemString(tmpDict, "latency", PyFloat_FromDouble((float)info->defaultLowInputLatency)); PyDict_SetItem(inDict, PyInt_FromLong(i), PyDict_Copy(tmpDict)); } if (info->maxOutputChannels > 0) { PyDict_SetItemString(tmpDict, "name", PyString_FromString(info->name)); PyDict_SetItemString(tmpDict, "host api index", PyInt_FromLong((int)info->hostApi)); PyDict_SetItemString(tmpDict, "default sr", PyInt_FromLong((int)info->defaultSampleRate)); PyDict_SetItemString(tmpDict, "latency", PyFloat_FromDouble((float)info->defaultLowOutputLatency)); PyDict_SetItem(outDict, PyInt_FromLong(i), PyDict_Copy(tmpDict)); } } return Py_BuildValue("(OO)", inDict, outDict); } } } #define portaudio_get_output_devices_info \ "\nReturns output devices (device names, device indexes) found by Portaudio.\n\n`device names` is a list of strings and `device indexes` is a list of the actual\nPortaudio index of each device.\n\n\ >>> outs = pa_get_output_devices()\n\ >>> print outs\n\ (['Built-in Output', 'UA-4FX', 'Soundflower (2ch)', 'Soundflower (16ch)'], [2, 3, 4, 5])\n\n" static PyObject* portaudio_get_output_devices(){ PaError err; PaDeviceIndex n, i; PyObject *list, *list_index; list = PyList_New(0); list_index = PyList_New(0); err = Pa_Initialize(); if (err != paNoError) { portaudio_assert(err, "Pa_Initialize"); Py_RETURN_NONE; } else { n = Pa_GetDeviceCount(); if (n < 0){ portaudio_assert(n, "Pa_GetDeviceCount"); Py_RETURN_NONE; } else { for (i=0; i < n; ++i){ const PaDeviceInfo *info=Pa_GetDeviceInfo(i); assert(info); if (info->maxOutputChannels > 0){ PyList_Append(list, PyString_FromString(info->name)); PyList_Append(list_index, PyInt_FromLong(i)); } } return Py_BuildValue("OO", list, list_index); } } } #define portaudio_get_output_max_channels_info \ "\nRetrieve the maximum number of output channels for the specified device.\n\n:Args:\n\n \ x: int\n Device index as listed by Portaudio (see pa_get_output_devices).\n\n\ >>> device = 'HDA Intel PCH: STAC92xx Analog (hw:0,0)'\n\ >>> dev_list, dev_index = pa_get_output_devices()\n\ >>> dev = dev_index[dev_list.index(device)]\n\ >>> print 'Device index:', dev\n\ >>> maxouts = pa_get_output_max_channels(dev)\n\ >>> maxins = pa_get_input_max_channels(dev)\n\ >>> print 'Max outputs:', maxouts\n\ >>> print 'Max inputs:', maxins\n\ >>> if maxouts >= 2 and maxins >= 2:\n\ ... nchnls = 2\n\ >>> else:\n\ ... nchnls = 1\n\n" static PyObject* portaudio_get_output_max_channels(PyObject *self, PyObject *arg){ PaError err; PaDeviceIndex n, i = PyInt_AsLong(arg); err = Pa_Initialize(); if (err != paNoError) { portaudio_assert(err, "Pa_Initialize"); Py_RETURN_NONE; } else { n = Pa_GetDeviceCount(); if (n < 0){ portaudio_assert(n, "Pa_GetDeviceCount"); Py_RETURN_NONE; } else { const PaDeviceInfo *info=Pa_GetDeviceInfo(i); assert(info); return PyInt_FromLong(info->maxOutputChannels); } } } #define portaudio_get_input_max_channels_info \ "\nRetrieve the maximum number of input channels for the specified device.\n\n:Args:\n\n \ x: int\n Device index as listed by Portaudio (see pa_get_input_devices).\n\n\ >>> device = 'HDA Intel PCH: STAC92xx Analog (hw:0,0)'\n\ >>> dev_list, dev_index = pa_get_output_devices()\n\ >>> dev = dev_index[dev_list.index(device)]\n\ >>> print 'Device index:', dev\n\ >>> maxouts = pa_get_output_max_channels(dev)\n\ >>> maxins = pa_get_input_max_channels(dev)\n\ >>> print 'Max outputs', maxouts\n\ >>> print 'Max inputs:', maxins\n\ >>> if maxouts >= 2 and maxins >= 2:\n\ ... nchnls = 2\n\ >>> else:\n\ ... nchnls = 1\n\n" static PyObject* portaudio_get_input_max_channels(PyObject *self, PyObject *arg){ PaError err; PaDeviceIndex n, i = PyInt_AsLong(arg); err = Pa_Initialize(); if (err != paNoError) { portaudio_assert(err, "Pa_Initialize"); Py_RETURN_NONE; } else { n = Pa_GetDeviceCount(); if (n < 0){ portaudio_assert(n, "Pa_GetDeviceCount"); Py_RETURN_NONE; } else { const PaDeviceInfo *info=Pa_GetDeviceInfo(i); assert(info); return PyInt_FromLong(info->maxInputChannels); } } } #define portaudio_get_input_devices_info \ "\nReturns input devices (device names, device indexes) found by Portaudio.\n\n`device names` is a list of strings and `device indexes` is a list of the actual\nPortaudio index of each device.\n\n\ >>> ins = pa_get_input_devices()\n\ >>> print ins\n\ (['Built-in Microphone', 'Built-in Input', 'UA-4FX', 'Soundflower (2ch)', 'Soundflower (16ch)'], [0, 1, 3, 4, 5])\n\n" static PyObject* portaudio_get_input_devices(){ PaError err; PaDeviceIndex n, i; PyObject *list, *list_index; list = PyList_New(0); list_index = PyList_New(0); err = Pa_Initialize(); if (err != paNoError) { portaudio_assert(err, "Pa_Initialize"); Py_RETURN_NONE; } else { n = Pa_GetDeviceCount(); if (n < 0){ portaudio_assert(n, "Pa_GetDeviceCount"); Py_RETURN_NONE; } else { for (i=0; i < n; ++i){ const PaDeviceInfo *info=Pa_GetDeviceInfo(i); assert(info); if (info->maxInputChannels > 0){ PyList_Append(list, PyString_FromString(info->name)); PyList_Append(list_index, PyInt_FromLong(i)); } } return Py_BuildValue("OO", list, list_index); } } } #define portaudio_get_default_input_info \ "\nReturns the index number of Portaudio's default input device.\n\n\ >>> names, indexes = pa_get_input_devices()\n\ >>> name = names[indexes.index(pa_get_default_input())]\n\ >>> print name\n\ 'Built-in Microphone'\n\n" static PyObject* portaudio_get_default_input(){ PaError err; PaDeviceIndex i; err = Pa_Initialize(); if (err != paNoError) { portaudio_assert(err, "Pa_Initialize"); Py_RETURN_NONE; } else { i = Pa_GetDefaultInputDevice(); return PyInt_FromLong(i); } } #define portaudio_get_default_output_info \ "\nReturns the index number of Portaudio's default output device.\n\n\ >>> names, indexes = pa_get_output_devices()\n\ >>> name = names[indexes.index(pa_get_default_output())]\n\ >>> print name\n\ 'UA-4FX'\n\n" static PyObject* portaudio_get_default_output(){ PaError err; PaDeviceIndex i; err = Pa_Initialize(); if (err != paNoError) { portaudio_assert(err, "Pa_Initialize"); Py_RETURN_NONE; } else { i = Pa_GetDefaultOutputDevice(); return PyInt_FromLong(i); } } /****** Portmidi utilities ******/ #define portmidi_count_devices_info \ "\nReturns the number of devices found by Portmidi.\n\n\ >>> c = pm_count_devices()\n\ >>> print c\n\ 6\n\n" static PyObject * portmidi_count_devices(){ int numDevices; numDevices = Pm_CountDevices(); return PyInt_FromLong(numDevices); } #define portmidi_list_devices_info \ "\nPrints a list of all devices found by Portmidi.\n\n\ >>> pm_list_devices()\n\ MIDI devices:\n\ 0: IN, name: IAC Driver Bus 1, interface: CoreMIDI\n\ 1: IN, name: from MaxMSP 1, interface: CoreMIDI\n\ 2: IN, name: from MaxMSP 2, interface: CoreMIDI\n\ 3: OUT, name: IAC Driver Bus 1, interface: CoreMIDI\n\ 4: OUT, name: to MaxMSP 1, interface: CoreMIDI\n\ 5: OUT, name: to MaxMSP 2, interface: CoreMIDI\n\n" static PyObject * portmidi_list_devices(){ int i; printf("MIDI devices:\n"); for (i = 0; i < Pm_CountDevices(); i++) { const PmDeviceInfo *info = Pm_GetDeviceInfo(i); if (info->input && info->output) printf("%d: IN/OUT, name: %s, interface: %s\n", i, info->name, info->interf); else if (info->input) printf("%d: IN, name: %s, interface: %s\n", i, info->name, info->interf); else if (info->output) printf("%d: OUT, name: %s, interface: %s\n", i, info->name, info->interf); } printf("\n"); Py_RETURN_NONE; } #define portmidi_get_input_devices_info \ "\nReturns midi input devices (device names, device indexes) found by Portmidi.\n\n`device names` is a list of strings and `device indexes` is a list of the actual\nPortmidi index of each device.\n\n\ >>> ins = pm_get_input_devices()\n\ >>> print ins\n\ (['IAC Driver Bus 1', 'from MaxMSP 1', 'from MaxMSP 2'], [0, 1, 2])\n\n" static PyObject* portmidi_get_input_devices(){ int n, i; PyObject *list, *list_index; list = PyList_New(0); list_index = PyList_New(0); n = Pm_CountDevices(); if (n < 0){ printf("Portmidi warning: No Midi interface found\n\n"); } else { for (i=0; i < n; i++){ const PmDeviceInfo *info = Pm_GetDeviceInfo(i); if (info->input){ PyList_Append(list, PyString_FromString(info->name)); PyList_Append(list_index, PyInt_FromLong(i)); } } printf("\n"); } return Py_BuildValue("OO", list, list_index); } #define portmidi_get_output_devices_info \ "\nReturns midi output devices (device names, device indexes) found by Portmidi.\n\n`device names` is a list of strings and `device indexes` is a list of the actual\nPortmidi index of each device.\n\n\ >>> outs = pm_get_output_devices()\n\ >>> print outs\n\ (['IAC Driver Bus 1', 'to MaxMSP 1', 'to MaxMSP 2'], [3, 4, 5])\n\n" static PyObject* portmidi_get_output_devices(){ int n, i; PyObject *list, *list_index; list = PyList_New(0); list_index = PyList_New(0); n = Pm_CountDevices(); if (n < 0){ printf("Portmidi warning: No Midi interface found\n\n"); } else { for (i=0; i < n; i++){ const PmDeviceInfo *info = Pm_GetDeviceInfo(i); if (info->output){ PyList_Append(list, PyString_FromString(info->name)); PyList_Append(list_index, PyInt_FromLong(i)); } } printf("\n"); } return Py_BuildValue("OO", list, list_index); } #define portmidi_get_default_input_info \ "\nReturns the index number of Portmidi's default input device.\n\n\ >>> names, indexes = pm_get_input_devices()\n\ >>> name = names[indexes.index(pm_get_default_input())]\n\ >>> print name\n\ 'IAC Driver Bus 1'\n\n" static PyObject * portmidi_get_default_input(){ PmDeviceID i; i = Pm_GetDefaultInputDeviceID(); if (i < 0) printf("pm_get_default_input: no midi input device found.\n"); return PyInt_FromLong(i); } #define portmidi_get_default_output_info \ "\nReturns the index number of Portmidi's default output device.\n\n\ >>> names, indexes = pm_get_output_devices()\n\ >>> name = names[indexes.index(pm_get_default_output())]\n\ >>> print name\n\ 'IAC Driver Bus 1'\n\n" static PyObject * portmidi_get_default_output(){ PmDeviceID i; i = Pm_GetDefaultOutputDeviceID(); if (i < 0) printf("pm_get_default_output: no midi output device found.\n"); return PyInt_FromLong(i); } /****** Libsndfile utilities ******/ static int libsndfile_get_format(int fileformat, int sampletype) { int format = 0; switch (fileformat) { case 0: format = SF_FORMAT_WAV; break; case 1: format = SF_FORMAT_AIFF; break; case 2: format = SF_FORMAT_AU; break; case 3: format = SF_FORMAT_RAW; break; case 4: format = SF_FORMAT_SD2; break; case 5: format = SF_FORMAT_FLAC; break; case 6: format = SF_FORMAT_CAF; break; case 7: format = SF_FORMAT_OGG | SF_FORMAT_VORBIS; break; } if (fileformat != 7) { switch (sampletype) { case 0: format = format | SF_FORMAT_PCM_16; break; case 1: format = format | SF_FORMAT_PCM_24; break; case 2: format = format | SF_FORMAT_PCM_32; break; case 3: format = format | SF_FORMAT_FLOAT; break; case 4: format = format | SF_FORMAT_DOUBLE; break; case 5: format = format | SF_FORMAT_ULAW; break; case 6: format = format | SF_FORMAT_ALAW; break; } } return format; } #define sndinfo_info \ "\nRetrieve informations about a soundfile.\n\n\ Prints the infos of the given soundfile to the console and returns a tuple containing:\n\n(number of frames, duration in seconds, sampling rate,\nnumber of channels, file format, sample type).\n\n:Args:\n\n \ path : string\n Path of a valid soundfile.\n \ print : boolean, optional\n If True, sndinfo will print sound infos to the console. Defaults to False.\n\n\ >>> path = SNDS_PATH + '/transparent.aif'\n\ >>> print path\n\ /usr/lib/python2.7/dist-packages/pyolib/snds/transparent.aif\n\ >>> info = sndinfo(path)\n\ >>> print info\n\ (29877, 0.6774829931972789, 44100.0, 1, 'AIFF', '16 bit int')\n\n" static PyObject * sndinfo(PyObject *self, PyObject *args, PyObject *kwds) { SNDFILE *sf; SF_INFO info; char *pathtmp; char *path; char fileformat[5]; char *sampletype; int format; int subformat; int print = 0; static char *kwlist[] = {"path", "print", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &pathtmp, &print)) { PySys_WriteStderr("sndinfo: failed to open the file.\n"); Py_RETURN_NONE; } path = malloc(strlen(pathtmp)+1); strcpy(path, pathtmp); /* Open the sound file. */ info.format = 0; sf = sf_open(path, SFM_READ, &info); if (sf == NULL) { PySys_WriteStderr("sndinfo: failed to open the file.\n"); Py_RETURN_NONE; } else { /* Retrieve file format */ format = (int)info.format; if (format > SF_FORMAT_WAV && format < SF_FORMAT_AIFF) { strcpy(fileformat, "WAVE"); subformat = format - SF_FORMAT_WAV; } else if (format > SF_FORMAT_AIFF && format < SF_FORMAT_AU) { strcpy(fileformat, "AIFF"); subformat = format - SF_FORMAT_AIFF; } else if (format > SF_FORMAT_AU && format < SF_FORMAT_RAW) { strcpy(fileformat, "AU"); subformat = format - SF_FORMAT_AU; } else if (format > SF_FORMAT_RAW && format < SF_FORMAT_PAF) { strcpy(fileformat, "RAW"); subformat = format - SF_FORMAT_RAW; } else if (format > SF_FORMAT_SD2 && format < SF_FORMAT_FLAC) { strcpy(fileformat, "SD2"); subformat = format - SF_FORMAT_SD2; } else if (format > SF_FORMAT_FLAC && format < SF_FORMAT_CAF) { strcpy(fileformat, "FLAC"); subformat = format - SF_FORMAT_FLAC; } else if (format > SF_FORMAT_CAF && format < SF_FORMAT_WVE) { strcpy(fileformat, "CAF"); subformat = format - SF_FORMAT_CAF; } else if (format > SF_FORMAT_OGG && format < SF_FORMAT_MPC2K) { strcpy(fileformat, "OGG"); subformat = format - SF_FORMAT_OGG; } else if (format > SF_FORMAT_RF64 && format < 0x230000) { strcpy(fileformat, "RF64"); subformat = format - SF_FORMAT_RF64; } else { strcpy(fileformat, "????"); subformat = -1; } /* Retrieve sample type */ if (subformat != -1) { switch (subformat) { case SF_FORMAT_PCM_S8: sampletype = malloc(strlen("s8 bit int") + 1); strcpy(sampletype, "s8 bit int"); break; case SF_FORMAT_PCM_U8: sampletype = malloc(strlen("u8 bit int") + 1); strcpy(sampletype, "u8 bit int"); break; case SF_FORMAT_PCM_16: sampletype = malloc(strlen("16 bit int") + 1); strcpy(sampletype, "16 bit int"); break; case SF_FORMAT_PCM_24: sampletype = malloc(strlen("24 bit int") + 1); strcpy(sampletype, "24 bit int"); break; case SF_FORMAT_PCM_32: sampletype = malloc(strlen("32 bit int") + 1); strcpy(sampletype, "32 bit int"); break; case SF_FORMAT_FLOAT: sampletype = malloc(strlen("32 bit float") + 1); strcpy(sampletype, "32 bit float"); break; case SF_FORMAT_DOUBLE: sampletype = malloc(strlen("64 bit float") + 1); strcpy(sampletype, "64 bit float"); break; case SF_FORMAT_ULAW: sampletype = malloc(strlen("U-Law encoded") + 1); strcpy(sampletype, "U-Law encoded"); break; case SF_FORMAT_ALAW: sampletype = malloc(strlen("A-Law encoded") + 1); strcpy(sampletype, "A-Law encoded"); break; case SF_FORMAT_VORBIS: sampletype = malloc(strlen("vorbis encoding") + 1); strcpy(sampletype, "vorbis encoding"); break; default: /* printf("%d\n", subformat); */ sampletype = malloc(strlen("Unknown...") + 1); strcpy(sampletype, "Unknown..."); break; } } else { sampletype = malloc(strlen("Unknown...") + 1); strcpy(sampletype, "Unknown..."); } if (print) fprintf(stdout, "name: %s\nnumber of frames: %i\nduration: %.4f sec\nsr: %.2f\nchannels: %i\nformat: %s\nsample type: %s\n", path, (int)info.frames, ((float)info.frames / info.samplerate), (float)info.samplerate, (int)info.channels, fileformat, sampletype); PyObject *sndinfo = PyTuple_Pack(6, PyInt_FromLong(info.frames), PyFloat_FromDouble((float)info.frames / info.samplerate), PyFloat_FromDouble(info.samplerate), PyInt_FromLong(info.channels), PyString_FromString(fileformat), PyString_FromString(sampletype)); sf_close(sf); free(path); free(sampletype); return sndinfo; } } #define savefile_info \ "\nCreates an audio file from a list of floats.\n\n:Args:\n\n \ samples : list of floats\n list of samples data, or list of list of samples data if more than 1 channels.\n \ path : string\n Full path (including extension) of the new file.\n \ sr : int, optional\n Sampling rate of the new file. Defaults to 44100.\n \ channels : int, optional\n number of channels of the new file. Defaults to 1.\n \ fileformat : int, optional\n Format type of the new file. Defaults to 0. Supported formats are:\n \ 0. WAVE - Microsoft WAV format (little endian) {.wav, .wave}\n \ 1. AIFF - Apple/SGI AIFF format (big endian) {.aif, .aiff}\n \ 2. AU - Sun/NeXT AU format (big endian) {.au}\n \ 3. RAW - RAW PCM data {no extension}\n \ 4. SD2 - Sound Designer 2 {.sd2}\n \ 5. FLAC - FLAC lossless file format {.flac}\n \ 6. CAF - Core Audio File format {.caf}\n \ 7. OGG - Xiph OGG container {.ogg}\n \ sampletype ; int, optional\n Bit depth encoding of the audio file. Defaults to 0.\n \ SD2 and FLAC only support 16 or 24 bit int. Supported types are:\n \ 0. 16 bit int\n \ 1. 24 bit int\n \ 2. 32 bit int\n \ 3. 32 bit float\n \ 4. 64 bit float\n \ 5. U-Law encoded\n \ 6. A-Law encoded\n\n\ >>> from random import uniform\n\ >>> import os\n\ >>> home = os.path.expanduser('~')\n\ >>> sr, dur, chnls, path = 44100, 5, 2, os.path.join(home, 'noise.aif')\n\ >>> samples = [[uniform(-0.5,0.5) for i in range(sr*dur)] for i in range(chnls)]\n\ >>> savefile(samples=samples, path=path, sr=sr, channels=chnls, fileformat=1, sampletype=1)\n\n" static PyObject * savefile(PyObject *self, PyObject *args, PyObject *kwds) { int i, j, size; char *recpath; PyObject *samples; MYFLT *sampsarray; int sr = 44100; int channels = 1; int fileformat = 0; int sampletype = 0; SNDFILE *recfile; SF_INFO recinfo; static char *kwlist[] = {"samples", "path", "sr", "channels", "fileformat", "sampletype", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Os|iiii", kwlist, &samples, &recpath, &sr, &channels, &fileformat, &sampletype)) return PyInt_FromLong(-1); recinfo.samplerate = sr; recinfo.channels = channels; recinfo.format = libsndfile_get_format(fileformat, sampletype); if (channels == 1) { size = PyList_Size(samples); sampsarray = (MYFLT *)malloc(size * sizeof(MYFLT)); for (i=0; i>> import os\n\ >>> home = os.path.expanduser('~')\n\ >>> path1 = SNDS_PATH + '/transparent.aif'\n\ >>> path2 = os.path.join(home, '/transparent2.aif')\n\ >>> t = SndTable(path1)\n\ >>> savefileFromTable(table=t, path=path, fileformat=1, sampletype=1)\n\n" static PyObject * savefileFromTable(PyObject *self, PyObject *args, PyObject *kwds) { int i, j, size; char *recpath; PyObject *table; PyObject *base_objs; PyObject *tablestreamlist; MYFLT *sampsarray; int sr = 44100; int channels = 1; int fileformat = 0; int sampletype = 0; int count = 0; int num_items = 0; SNDFILE *recfile; SF_INFO recinfo; static char *kwlist[] = {"table", "path", "fileformat", "sampletype", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Os|ii", kwlist, &table, &recpath, &fileformat, &sampletype)) return PyInt_FromLong(-1); base_objs = PyObject_GetAttrString(table, "_base_objs"); channels = PyList_Size(base_objs); tablestreamlist = PyList_New(channels); for (i=0; i>> import os\n\ >>> home = os.path.expanduser('~')\n\ >>> f = SNDS_PATH+'/transparent.aif'\n\ >>> # upsample a signal 3 times\n\ >>> upfile = os.path.join(home, 'trans_upsamp_2.aif')\n\ >>> upsamp(f, upfile, 2, 256)\n\ >>> # downsample the upsampled signal 3 times\n\ >>> downfile = os.path.join(home, 'trans_downsamp_3.aif')\n\ >>> downsamp(upfile, downfile, 3, 256)\n\n" #define downsamp_info \ "\nDecreases the sampling rate of an audio file.\n\n:Args:\n\n \ path : string\n Full path (including extension) of the audio file to convert.\n \ outfile : string\n Full path (including extension) of the new file.\n \ down : int, optional\n Downsampling factor. Defaults to 4.\n \ order : int, optional\n Length, in samples, of the anti-aliasing lowpass filter. Defaults to 128.\n\n\ >>> import os\n\ >>> home = os.path.expanduser('~')\n\ >>> f = SNDS_PATH+'/transparent.aif'\n\ >>> # upsample a signal 3 times\n\ >>> upfile = os.path.join(home, 'trans_upsamp_2.aif')\n\ >>> upsamp(f, upfile, 2, 256)\n\ >>> # downsample the upsampled signal 3 times\n\ >>> downfile = os.path.join(home, 'trans_downsamp_3.aif')\n\ >>> downsamp(upfile, downfile, 3, 256)\n\n" MYFLT HALF_BLACKMAN[513] = {5.999999848427251e-05, 6.0518785176100209e-05, 6.2141079979483038e-05, 6.4805892179720104e-05, 6.8557070335373282e-05, 7.335994450841099e-05, 7.9284000094048679e-05, 8.6251806351356208e-05, 9.4344803073909134e-05, 0.00010353395919082686, 0.0001138320003519766, 0.0001252776273759082, 0.00013784394832327962, 0.00015158756286837161, 0.00016646583389956504, 0.00018252100562676787, 0.00019978794443886727, 0.00021828405442647636, 0.00023800843337085098, 0.00025901006301864982, 0.0002812814200296998, 0.00030484798480756581, 0.00032972017652355134, 0.00035596732050180435, 0.00038358545862138271, 0.0004126313142478466, 0.00044307118514552712, 0.00047501336666755378, 0.00050844199722632766, 0.00054337596520781517, 0.00057988864136859775, 0.00061800965340808034, 0.00065775914117693901, 0.000699152413289994, 0.00074227934237569571, 0.00078715570271015167, 0.00083377416012808681, 0.00088227324886247516, 0.0009326221770606935, 0.00098489224910736084, 0.0010391034884378314, 0.0010953464079648256, 0.001153626712039113, 0.0012140328763052821, 0.0012765693245455623, 0.001341317780315876, 0.0014083425048738718, 0.0014776336029171944, 0.001549328095279634, 0.0016234172508120537, 0.0017000052612274885, 0.0017791179707273841, 0.0018608199898153543, 0.0019451823318377137, 0.0020322385244071484, 0.0021220885682851076, 0.0022147782146930695, 0.0023103870917111635, 0.0024089745711535215, 0.0025105655658990145, 0.0026152802165597677, 0.0027231767307966948, 0.0028343265876173973, 0.0029487889260053635, 0.0030666270758956671, 0.0031879479065537453, 0.0033128033392131329, 0.0034412886016070843, 0.0035734693519771099, 0.0037094042636454105, 0.0038491983432322741, 0.0039929361082613468, 0.0041406778618693352, 0.004292510449886322, 0.0044485158286988735, 0.004608803428709507, 0.0047734435647726059, 0.0049425391480326653, 0.005116121843457222, 0.0052943285554647446, 0.0054772454313933849, 0.0056649716570973396, 0.0058575910516083241, 0.0060551739297807217, 0.0062578483484685421, 0.0064656869508326054, 0.0066788033582270145, 0.0068972636945545673, 0.0071212123148143291, 0.0073507223278284073, 0.007585874292999506, 0.0078268209472298622, 0.0080736298114061356, 0.0083263935521245003, 0.0085852388292551041, 0.0088502718135714531, 0.0091215828433632851, 0.0093993041664361954, 0.0096835149452090263, 0.0099743194878101349, 0.010271874256432056, 0.010576239787042141, 0.010887577198445797, 0.01120593398809433, 0.01153149176388979, 0.011864298023283482, 0.012204526923596859, 0.012552268803119659, 0.012907638214528561, 0.013270745985209942, 0.013641729019582272, 0.014020670205354691, 0.014407743699848652, 0.014803030528128147, 0.015206646174192429, 0.015618747100234032, 0.016039434820413589, 0.0164688341319561, 0.01690707728266716, 0.017354268580675125, 0.017810540273785591, 0.018276045098900795, 0.018750874325633049, 0.019235162064433098, 0.01972905732691288, 0.020232660695910454, 0.020746102556586266, 0.021269544959068298, 0.021803082898259163, 0.022346852347254753, 0.022900991141796112, 0.023465657606720924, 0.024040926247835159, 0.024626968428492546, 0.025223886594176292, 0.025831848382949829, 0.026450937613844872, 0.02708134613931179, 0.027723187580704689, 0.02837657742202282, 0.029041649773716927, 0.029718579724431038, 0.030407454818487167, 0.03110840916633606, 0.03182162344455719, 0.032547183334827423, 0.033285260200500488, 0.034035947173833847, 0.034799445420503616, 0.035575807094573975, 0.036365248262882233, 0.037167854607105255, 0.037983741611242294, 0.038813117891550064, 0.039656046777963638, 0.040512733161449432, 0.041383236646652222, 0.042267743498086929, 0.043166369199752808, 0.044079229235649109, 0.045006513595581055, 0.045948274433612823, 0.046904727816581726, 0.047875978052616119, 0.048862140625715256, 0.049863360822200775, 0.050879742950201035, 0.051911454647779465, 0.052958611398935318, 0.054021358489990234, 0.055099856108427048, 0.056194130331277847, 0.057304393500089645, 0.0584307461977005, 0.059573329985141754, 0.060732249170541763, 0.061907690018415451, 0.063099689781665802, 0.064308419823646545, 0.065534010529518127, 0.066776573657989502, 0.068036213517189026, 0.069313108921051025, 0.070607319474220276, 0.071918979287147522, 0.073248207569122314, 0.074595145881175995, 0.075959883630275726, 0.07734256237745285, 0.078743241727352142, 0.080162093043327332, 0.08159918338060379, 0.083054669201374054, 0.084528610110282898, 0.086021184921264648, 0.087532415986061096, 0.089062459766864777, 0.090611375868320465, 0.092179328203201294, 0.093766368925571442, 0.095372647047042847, 0.096998192369937897, 0.098643146455287933, 0.10030759125947952, 0.10199161618947983, 0.10369531810283661, 0.10541882365942001, 0.10716214776039124, 0.10892540961503983, 0.11070869863033295, 0.11251209676265717, 0.11433566361665726, 0.11617954820394516, 0.11804373562335968, 0.11992833018302917, 0.12183342128992081, 0.12375906854867935, 0.12570534646511078, 0.12767235934734344, 0.12966008484363556, 0.13166864216327667, 0.13369807600975037, 0.13574843108654022, 0.13781978189945221, 0.13991223275661469, 0.14202572405338287, 0.14416038990020752, 0.14631621539592743, 0.14849328994750977, 0.15069162845611572, 0.15291133522987366, 0.15515235066413879, 0.15741473436355591, 0.15969853103160858, 0.1620037853717804, 0.16433051228523254, 0.16667875647544861, 0.16904847323894501, 0.17143970727920532, 0.17385250329971313, 0.17628686130046844, 0.17874275147914886, 0.18122029304504395, 0.18371935188770294, 0.18623997271060944, 0.18878217041492462, 0.1913459450006485, 0.19393126666545868, 0.19653819501399994, 0.19916661083698273, 0.20181652903556824, 0.20448794960975647, 0.20718084275722504, 0.20989517867565155, 0.2126309871673584, 0.21538813412189484, 0.21816661953926086, 0.2209663987159729, 0.22378745675086975, 0.22662979364395142, 0.22949324548244476, 0.23237781226634979, 0.23528343439102173, 0.23821006715297699, 0.24115763604640961, 0.24412614107131958, 0.24711540341377258, 0.25012537837028503, 0.25315603613853455, 0.25620725750923157, 0.25927898287773132, 0.26237118244171143, 0.26548364758491516, 0.26861634850502014, 0.27176916599273682, 0.27494201064109802, 0.2781347930431366, 0.28134745359420776, 0.28457978367805481, 0.28783169388771057, 0.29110309481620789, 0.29439383745193481, 0.29770383238792419, 0.30103299021720886, 0.30438104271888733, 0.30774796009063721, 0.31113356351852417, 0.31453773379325867, 0.31796032190322876, 0.3214012086391449, 0.32486018538475037, 0.32833707332611084, 0.33183175325393677, 0.33534407615661621, 0.33887386322021484, 0.34242099523544312, 0.34598517417907715, 0.34956631064414978, 0.35316416621208191, 0.35677862167358398, 0.3604094386100769, 0.36405652761459351, 0.36771953105926514, 0.37139829993247986, 0.37509268522262573, 0.37880244851112366, 0.38252738118171692, 0.38626736402511597, 0.39002197980880737, 0.39379113912582397, 0.39757457375526428, 0.40137210488319397, 0.40518343448638916, 0.40900847315788269, 0.41284680366516113, 0.41669824719429016, 0.42056256532669067, 0.42443951964378357, 0.42832884192466736, 0.4322303831577301, 0.43614372611045837, 0.44006863236427307, 0.44400492310523987, 0.4479522705078125, 0.45191043615341187, 0.45587921142578125, 0.45985805988311768, 0.46384698152542114, 0.46784573793411255, 0.47185373306274414, 0.47587084770202637, 0.47989678382873535, 0.48393124341964722, 0.48797392845153809, 0.49202454090118408, 0.49608278274536133, 0.50014835596084595, 0.50422090291976929, 0.50830012559890747, 0.5123857855796814, 0.51647758483886719, 0.52057504653930664, 0.52467787265777588, 0.5287858247756958, 0.53289848566055298, 0.53701561689376831, 0.54113680124282837, 0.54526180028915405, 0.54939013719558716, 0.55352163314819336, 0.55765581130981445, 0.56179243326187134, 0.56593120098114014, 0.57007157802581787, 0.57421320676803589, 0.57835590839385986, 0.58249920606613159, 0.58664274215698242, 0.59078621864318848, 0.59492921829223633, 0.5990714430809021, 0.60321247577667236, 0.60735195875167847, 0.61148953437805176, 0.61562496423721313, 0.61975759267807007, 0.62388718128204346, 0.62801331281661987, 0.63213574886322021, 0.6362539529800415, 0.64036762714385986, 0.64447635412216187, 0.64857983589172363, 0.65267753601074219, 0.65676921606063843, 0.66085445880889893, 0.6649329662322998, 0.66900408267974854, 0.67306756973266602, 0.67712306976318359, 0.68117010593414307, 0.68520838022232056, 0.68923747539520264, 0.69325697422027588, 0.69726645946502686, 0.70126563310623169, 0.70525401830673218, 0.70923143625259399, 0.71319711208343506, 0.71715086698532104, 0.72109222412109375, 0.7250208854675293, 0.72893643379211426, 0.73283845186233521, 0.73672652244567871, 0.74060028791427612, 0.74445939064025879, 0.74830329418182373, 0.75213176012039185, 0.75594443082809448, 0.75974071025848389, 0.76352030038833618, 0.76728278398513794, 0.77102780342102051, 0.77475500106811523, 0.77846395969390869, 0.78215426206588745, 0.78582549095153809, 0.78947734832763672, 0.79310941696166992, 0.79672133922576904, 0.80031275749206543, 0.80388307571411133, 0.80743205547332764, 0.8109593391418457, 0.81446456909179688, 0.81794726848602295, 0.82140713930130005, 0.82484376430511475, 0.82825678586959839, 0.83164584636688232, 0.8350105881690979, 0.83835059404373169, 0.84166562557220459, 0.84495508670806885, 0.84821879863739014, 0.85145628452301025, 0.8546673059463501, 0.85785144567489624, 0.86100828647613525, 0.86413758993148804, 0.86723899841308594, 0.87031209468841553, 0.87335652112960815, 0.87637203931808472, 0.87935841083526611, 0.88231492042541504, 0.88524156808853149, 0.88813787698745728, 0.89100354909896851, 0.89383822679519653, 0.89664167165756226, 0.89941352605819702, 0.90215343236923218, 0.90486115217208862, 0.90753632783889771, 0.91017866134643555, 0.91278791427612305, 0.91536372900009155, 0.91790568828582764, 0.92041373252868652, 0.92288732528686523, 0.92532640695571899, 0.92773056030273438, 0.93009954690933228, 0.93243312835693359, 0.93473094701766968, 0.93699288368225098, 0.93921846151351929, 0.94140768051147461, 0.94356006383895874, 0.94567543268203735, 0.94775348901748657, 0.94979411363601685, 0.95179694890975952, 0.95376187562942505, 0.95568859577178955, 0.95757681131362915, 0.95942646265029907, 0.96123719215393066, 0.9630088210105896, 0.96474123001098633, 0.96643412113189697, 0.96808725595474243, 0.96970051527023315, 0.97127372026443481, 0.97280663251876831, 0.97429907321929932, 0.97575092315673828, 0.9771619439125061, 0.97853195667266846, 0.97986090183258057, 0.98114854097366333, 0.98239481449127197, 0.98359936475753784, 0.98476219177246094, 0.98588317632675171, 0.98696213960647583, 0.98799896240234375, 0.98899352550506592, 0.98994570970535278, 0.99085539579391479, 0.9917224645614624, 0.99254685640335083, 0.99332839250564575, 0.99406707286834717, 0.99476277828216553, 0.99541538953781128, 0.99602478742599487, 0.99659103155136108, 0.99711394309997559, 0.99759352207183838, 0.99802964925765991, 0.99842232465744019, 0.9987715482711792, 0.99907714128494263, 0.99933922290802002, 0.99955761432647705, 0.9997323751449585, 0.99986344575881958, 0.9999508261680603, 0.99999451637268066, 0.99999451637268066}; /* gen_lp_impulse generates a sinc function to be used as a lowpass impulse response. array is the container where to save the impulse response function. size is the convolution impulse response length in samples. freq is the cutoff frequency in radians. */ void gen_lp_impulse(MYFLT *array, int size, float freq) { int i, ppi; MYFLT pp, ppf, env, scl, invSum, val; int half = size / 2; MYFLT vsum = 0.0; MYFLT envPointerScaling = 1.0 / (size + 1) * 1024.0; MYFLT sincScaling = (MYFLT)half; for (i=0; i convolution lowpass filter. samples is the samples array to filter. impulse is the impulse response array. num_samps is the number of samples to filter. size is the filter order. Minimum suggested = 16, ideal = 128 or higher. gain is the gain of the filter. */ void lp_conv(MYFLT *samples, MYFLT *impulse, int num_samps, int size, int gain) { int i, j, count, tmp_count; MYFLT val; MYFLT intmp[size]; for (i=0; i 2) { /* apply lowpass filter */ sincfunc = (MYFLT *)malloc(order * sizeof(MYFLT)); gen_lp_impulse(sincfunc, order, PI/up); for (i=0; i 2) { /* apply lowpass filter */ sincfunc = (MYFLT *)malloc(order * sizeof(MYFLT)); gen_lp_impulse(sincfunc, order, PI/down); for (i=0; inAnchorIndex = nAnchorIndex; m_pStack->nFloaterIndex = nFloaterIndex; m_pStack->precPrev = precPrev; } int StackPop( int *pnAnchorIndex, int *pnFloaterIndex ) { STACK_RECORD *precStack = m_pStack; if ( precStack == NULL ) return 0; *pnAnchorIndex = precStack->nAnchorIndex; *pnFloaterIndex = precStack->nFloaterIndex; m_pStack = precStack->precPrev; free( precStack ); return 1; } static PyObject * reducePoints(PyObject *self, PyObject *args, PyObject *kwds) { int i, nPointsCount, nVertexIndex, nAnchorIndex, nFloaterIndex; MYFLT dSegmentVecLength; MYFLT dAnchorVecX, dAnchorVecY; MYFLT dAnchorUnitVecX, dAnchorUnitVecY; MYFLT dVertexVecLength; MYFLT dVertexVecX, dVertexVecY; MYFLT dProjScalar; MYFLT dVertexDistanceToSegment; MYFLT dMaxDistThisSegment; int nVertexIndexMaxDistance; PyObject *pointlist, *pPointsOut, *tup; MYFLT *pPointsX, *pPointsY; int *pnUseFlag; MYFLT dTolerance = .02; MYFLT xMax, yMin, yMax; static char *kwlist[] = {"pointlist", "tolerance", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_F, kwlist, &pointlist, &dTolerance)) return PyInt_FromLong(-1); nPointsCount = PyList_Size(pointlist); pPointsX = (MYFLT *)malloc(nPointsCount * sizeof(MYFLT)); pPointsY = (MYFLT *)malloc(nPointsCount * sizeof(MYFLT)); pnUseFlag = (int *)malloc(nPointsCount * sizeof(int)); tup = PyList_GET_ITEM(pointlist, 0); if (PyTuple_Check(tup) == 1) { for (i=0; i yMax) yMax = pPointsY[i]; } for (i=0; i 1.0) { closest[0] = xp2[0]; closest[1] = xp2[1]; } else { closest[0] = xp1[0] + u * xDelta; closest[1] = xp1[1] + u * yDelta; } return PyFloat_FromDouble(MYSQRT(MYPOW(xp[0] - closest[0], 2.0) + MYPOW(xp[1] - closest[1], 2.0))); } #define linToCosCurve_info \ "\nCreates a cosinus interpolated curve from a list of points.\n\n\ A point is a tuple (or a list) of two floats, time and value.\n\n:Args:\n\n \ data : list of points\n Set of points between which will be inserted interpolated segments.\n \ yrange : list of 2 floats, optional\n Minimum and maximum values on the Y axis. Defaults to [0., 1.].\n \ totaldur : float, optional\n X axis duration. Defaults to 1.\n \ points : int, optional\n Number of points in the output list. Defaults to 1024.\n \ log : boolean, optional\n Set this value to True if the Y axis has a logarithmic scale. Defaults to False\n\n\ >>> s = Server().boot()\n\ >>> a = [(0,0), (0.25, 1), (0.33, 1), (1,0)]\n\ >>> b = linToCosCurve(a, yrange=[0, 1], totaldur=1, points=8192)\n\ >>> t = DataTable(size=len(b), init=[x[1] for x in b])\n\ >>> t.view()\n\n" static PyObject * linToCosCurve(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *data, *fdata, *out, *inout, *ftup, *yrange=NULL, *fyrange=NULL; int i, j, datasize, steps; double tmp, x1, x2, y1, y2, mu, ydiff, log10ymin, log10ymax; double *xdata, *ydata, *cxdata, *cydata; double totaldur = 1.0; double ymin = 0.0; double ymax = 1.0; int num = 1024; double inc = 1.0 / num; int log = 0; int count = 0; static char *kwlist[] = {"data", "yrange", "totaldur", "points", "log", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|Odii", kwlist, &data, &yrange, &totaldur, &num, &log)) Py_RETURN_NONE; if (yrange) { fyrange = PySequence_Fast(yrange, NULL); ymin = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(fyrange, 0)); ymax = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(fyrange, 1)); } ydiff = ymax - ymin; log10ymin = log10(ymin); log10ymax = log10(ymax); fdata = PySequence_Fast(data, NULL); datasize = PySequence_Size(fdata); xdata = (double *)malloc(datasize * sizeof(double)); ydata = (double *)malloc(datasize * sizeof(double)); /* acquire data + normalization */ if (log == 0) { for (i=0; i>> a = 0.5\n\ >>> b = rescale(a, 0, 1, 20, 20000, False, True)\n\ >>> print b\n\ 632.453369141\n\ >>> a = [0, .4, .8]\n\ >>> b = rescale(a, 0, 1, 20, 20000, False, True)\n\ >>> print b\n\ [20.000001907348633, 316.97738647460938, 5023.7705078125]\n\n" static PyObject * rescale(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *data, *out; MYFLT datascl, curscl, val; MYFLT xmin = 0.0; MYFLT xmax = 1.0; MYFLT ymin = 0.0; MYFLT ymax = 1.0; int xlog = 0; int ylog = 0; int i, cnt; int type; // 0 = float, 1 = list of floats static char *kwlist[] = {"data", "xmin", "xmax", "ymin", "ymax", "xlog", "ylog", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FFFFII, kwlist, &data, &xmin, &xmax, &ymin, &ymax, &xlog, &ylog)) return PyInt_FromLong(-1); if (PyNumber_Check(data)) type = 0; else if (PyList_Check(data)) type = 1; else { Py_INCREF(Py_None); return Py_None; } if (xlog == 0 && ylog == 0) { datascl = xmax - xmin; curscl = ymax - ymin; curscl /= datascl; if (type == 0) { val = PyFloat_AsDouble(data); return Py_BuildValue("d", (val - xmin) * curscl + ymin); } else if (type == 1) { cnt = PyList_Size(data); out = PyList_New(cnt); for (i=0; i>> a = 0.5\n\ >>> b = floatmap(a, 0, 1, 4)\n\ >>> print b\n\ 0.0625\n\n" static PyObject * floatmap(PyObject *self, PyObject *args, PyObject *kwds) { MYFLT x = 0.0; MYFLT min = 0.0; MYFLT max = 1.0; MYFLT exp = 1.0; static char *kwlist[] = {"x", "min", "max", "exp", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F_FFF, kwlist, &x, &min, &max, &exp)) return PyInt_FromLong(-1); if (x < 0.0) x = 0.0; else if (x > 1.0) x = 1.0; if (exp != 1.0) x = MYPOW(x, exp); return Py_BuildValue("d", x * (max - min) + min); } /****** Conversion utilities ******/ #define midiToHz_info \ "\nConverts a midi note value to frequency in Hertz.\n\n:Args:\n\n \ x : int or float\n Midi note. `x` can be a number, a list or a tuple, otherwise the function returns None.\n\n\ >>> a = (48, 60, 62, 67)\n\ >>> b = midiToHz(a)\n\ >>> print b\n\ (130.8127826503271, 261.62556530066814, 293.66476791748823, 391.9954359818656)\n\ >>> a = [48, 60, 62, 67]\n\ >>> b = midiToHz(a)\n\ >>> print b\n\ [130.8127826503271, 261.62556530066814, 293.66476791748823, 391.9954359818656]\n\ >>> b = midiToHz(60.0)\n\ >>> print b\n\ 261.625565301\n\n" static PyObject * midiToHz(PyObject *self, PyObject *arg) { int count = 0; int i = 0; double x = 0.0; PyObject *newseq = NULL; if (PyNumber_Check(arg)) return Py_BuildValue("d", 440.0 * MYPOW(2.0, (PyFloat_AsDouble(arg) - 69) / 12.0)); else if (PyList_Check(arg)) { count = PyList_Size(arg); newseq = PyList_New(count); for (i=0; i>> a = (110.0, 220.0, 440.0, 880.0)\n\ >>> b = hzToMidi(a)\n\ >>> print b\n\ (45.0, 57.0, 69.0, 81.0)\n\ >>> a = [110.0, 220.0, 440.0, 880.0]\n\ >>> b = hzToMidi(a)\n\ >>> print b\n\ [45.0, 57.0, 69.0, 81.0]\n\ >>> b = hzToMidi(440.0)\n\ >>> print b\n\ 69.0\n\n" static PyObject * hzToMidi(PyObject *self, PyObject *arg) { int count = 0; int i = 0; double x = 0.0; PyObject *newseq = NULL; if (PyNumber_Check(arg)) return Py_BuildValue("d", 12.0 * MYLOG2(PyFloat_AsDouble(arg) / 440.0) + 69); else if (PyList_Check(arg)) { count = PyList_Size(arg); newseq = PyList_New(count); for (i=0; i>> a = (48, 60, 62, 67)\n\ >>> b = midiToTranspo(a)\n\ >>> print b\n \ (0.49999999999997335, 1.0, 1.122462048309383, 1.4983070768767281)\n\ >>> a = [48, 60, 62, 67]\n\ >>> b = midiToTranspo(a)\n\ >>> print b\n\ [0.49999999999997335, 1.0, 1.122462048309383, 1.4983070768767281]\n\ >>> b = midiToTranspo(60.0)\n\ >>> print b\n\ 1.0\n\n" static PyObject * midiToTranspo(PyObject *self, PyObject *arg) { int count = 0; int i = 0; double x = 0.0; PyObject *newseq = NULL; if (PyNumber_Check(arg)) return Py_BuildValue("d", pow(1.0594630943593, PyFloat_AsDouble(arg)-60.0)); else if (PyList_Check(arg)) { count = PyList_Size(arg); newseq = PyList_New(count); for (i=0; i>> s = Server().boot()\n\ >>> a = (64, 128, 256)\n\ >>> b = sampsToSec(a)\n\ >>> print b\n\ (0.0014512471655328798, 0.0029024943310657597, 0.0058049886621315194)\n\ >>> a = [64, 128, 256]\n\ >>> b = sampsToSec(a)\n\ >>> print b\n\ [0.0014512471655328798, 0.0029024943310657597, 0.0058049886621315194]\n\ >>> b = sampsToSec(8192)\n\ >>> print b\n\ 0.185759637188\n\n" static PyObject * sampsToSec(PyObject *self, PyObject *arg) { PyObject *server = PyServer_get_server(); if (server == NULL) { printf("Warning: A Server must be booted before calling `sampsToSec` function.\n"); Py_RETURN_NONE; } double sr = PyFloat_AsDouble(PyObject_CallMethod(server, "getSamplingRate", NULL)); int count = 0; int i = 0; double x = 0.0; PyObject *newseq = NULL; if (PyNumber_Check(arg)) return Py_BuildValue("d", PyFloat_AsDouble(arg) / sr); else if (PyList_Check(arg)) { count = PyList_Size(arg); newseq = PyList_New(count); for (i=0; i>> s = Server().boot()\n\ >>> a = (0.1, 0.25, 0.5, 1)\n\ >>> b = secToSamps(a)\n\ >>> print b\n\ (4410, 11025, 22050, 44100)\n\ >>> a = [0.1, 0.25, 0.5, 1]\n\ >>> b = secToSamps(a)\n\ >>> print b\n\ [4410, 11025, 22050, 44100]\n\ >>> b = secToSamps(2.5)\n\ >>> print b\n\ 110250\n\n" static PyObject * secToSamps(PyObject *self, PyObject *arg) { PyObject *server = PyServer_get_server(); if (server == NULL) { printf("Warning: A Server must be booted before calling `secToSamps` function.\n"); Py_RETURN_NONE; } double sr = PyFloat_AsDouble(PyObject_CallMethod(server, "getSamplingRate", NULL)); int count = 0; int i = 0; double x = 0.0; PyObject *newseq = NULL; if (PyNumber_Check(arg)) return Py_BuildValue("l", (long)(PyFloat_AsDouble(arg) * sr)); else if (PyList_Check(arg)) { count = PyList_Size(arg); newseq = PyList_New(count); for (i=0; i>> print serverCreated()\n\ False\n\ >>> s = Server()\n\ >>> print serverCreated()\n\ True\n\n" static PyObject * serverCreated(PyObject *self) { if (PyServer_get_server() != NULL) { Py_INCREF(Py_True); return Py_True; } else { Py_INCREF(Py_False); return Py_False; } } #define serverBooted_info \ "\nReturns True if an already created Server is booted, otherwise, returns False.\n\n\ >>> s = Server()\n\ >>> print serverBooted()\n\ False\n\ >>> s.boot()\n\ >>> print serverBooted()\n\ True\n\n" static PyObject * serverBooted(PyObject *self) { int boot; PyObject *server; if (PyServer_get_server() != NULL) { server = PyServer_get_server(); boot = PyInt_AsLong(PyObject_CallMethod(server, "getIsBooted", NULL)); if (boot == 0) { Py_INCREF(Py_False); return Py_False; } else { Py_INCREF(Py_True); return Py_True; } } else { printf("Warning: A Server must be created before calling `serverBooted` function.\n"); Py_INCREF(Py_False); return Py_False; } } static PyMethodDef pyo_functions[] = { {"pa_get_version", (PyCFunction)portaudio_get_version, METH_NOARGS, portaudio_get_version_info}, {"pa_get_version_text", (PyCFunction)portaudio_get_version_text, METH_NOARGS, portaudio_get_version_text_info}, {"pa_count_devices", (PyCFunction)portaudio_count_devices, METH_NOARGS, portaudio_count_devices_info}, {"pa_count_host_apis", (PyCFunction)portaudio_count_host_apis, METH_NOARGS, portaudio_count_host_apis_info}, {"pa_list_devices", (PyCFunction)portaudio_list_devices, METH_NOARGS, portaudio_list_devices_info}, {"pa_get_devices_infos", (PyCFunction)portaudio_get_devices_infos, METH_NOARGS, portaudio_get_devices_infos_info}, {"pa_get_input_max_channels", (PyCFunction)portaudio_get_input_max_channels, METH_O, portaudio_get_input_max_channels_info}, {"pa_get_output_max_channels", (PyCFunction)portaudio_get_output_max_channels, METH_O, portaudio_get_output_max_channels_info}, {"pa_get_output_devices", (PyCFunction)portaudio_get_output_devices, METH_NOARGS, portaudio_get_output_devices_info}, {"pa_get_input_devices", (PyCFunction)portaudio_get_input_devices, METH_NOARGS, portaudio_get_input_devices_info}, {"pa_list_host_apis", (PyCFunction)portaudio_list_host_apis, METH_NOARGS, portaudio_list_host_apis_info}, {"pa_get_default_input", (PyCFunction)portaudio_get_default_input, METH_NOARGS, portaudio_get_default_input_info}, {"pa_get_default_host_api", (PyCFunction)portaudio_get_default_host_api, METH_NOARGS, portaudio_get_default_host_api_info}, {"pa_get_default_output", (PyCFunction)portaudio_get_default_output, METH_NOARGS, portaudio_get_default_output_info}, {"pm_count_devices", (PyCFunction)portmidi_count_devices, METH_NOARGS, portmidi_count_devices_info}, {"pm_list_devices", (PyCFunction)portmidi_list_devices, METH_NOARGS, portmidi_list_devices_info}, {"pm_get_input_devices", (PyCFunction)portmidi_get_input_devices, METH_NOARGS, portmidi_get_input_devices_info}, {"pm_get_default_input", (PyCFunction)portmidi_get_default_input, METH_NOARGS, portmidi_get_default_input_info}, {"pm_get_output_devices", (PyCFunction)portmidi_get_output_devices, METH_NOARGS, portmidi_get_output_devices_info}, {"pm_get_default_output", (PyCFunction)portmidi_get_default_output, METH_NOARGS, portmidi_get_default_output_info}, {"sndinfo", (PyCFunction)sndinfo, METH_VARARGS|METH_KEYWORDS, sndinfo_info}, {"savefile", (PyCFunction)savefile, METH_VARARGS|METH_KEYWORDS, savefile_info}, {"savefileFromTable", (PyCFunction)savefileFromTable, METH_VARARGS|METH_KEYWORDS, savefileFromTable_info}, {"upsamp", (PyCFunction)upsamp, METH_VARARGS|METH_KEYWORDS, upsamp_info}, {"downsamp", (PyCFunction)downsamp, METH_VARARGS|METH_KEYWORDS, downsamp_info}, {"reducePoints", (PyCFunction)reducePoints, METH_VARARGS|METH_KEYWORDS, reducePoints_info}, {"distanceToSegment", (PyCFunction)distanceToSegment, METH_VARARGS|METH_KEYWORDS, distanceToSegment_info}, {"rescale", (PyCFunction)rescale, METH_VARARGS|METH_KEYWORDS, rescale_info}, {"floatmap", (PyCFunction)floatmap, METH_VARARGS|METH_KEYWORDS, floatmap_info}, {"linToCosCurve", (PyCFunction)linToCosCurve, METH_VARARGS|METH_KEYWORDS, linToCosCurve_info}, {"midiToHz", (PyCFunction)midiToHz, METH_O, midiToHz_info}, {"hzToMidi", (PyCFunction)hzToMidi, METH_O, hzToMidi_info}, {"midiToTranspo", (PyCFunction)midiToTranspo, METH_O, midiToTranspo_info}, {"sampsToSec", (PyCFunction)sampsToSec, METH_O, sampsToSec_info}, {"secToSamps", (PyCFunction)secToSamps, METH_O, secToSamps_info}, {"serverCreated", (PyCFunction)serverCreated, METH_NOARGS, serverCreated_info}, {"serverBooted", (PyCFunction)serverBooted, METH_NOARGS, serverBooted_info}, {NULL, NULL, 0, NULL}, }; static PyObject * module_add_object(PyObject *module, const char *name, PyTypeObject *type) { if (PyType_Ready(type) < 0) Py_RETURN_NONE; Py_INCREF(type); PyModule_AddObject(module, name, (PyObject *)type); Py_RETURN_NONE; } PyMODINIT_FUNC #ifndef USE_DOUBLE init_pyo(void) #else init_pyo64(void) #endif { PyObject *m; m = Py_InitModule3(LIB_BASE_NAME, pyo_functions, "Python digital signal processing module."); #ifndef NO_MESSAGES #ifndef USE_DOUBLE printf("pyo version %s (uses single precision)\n", PYO_VERSION); #else printf("pyo version %s (uses double precision)\n", PYO_VERSION); #endif #endif module_add_object(m, "Server_base", &ServerType); module_add_object(m, "MidiListener_base", &MidiListenerType); module_add_object(m, "OscListener_base", &OscListenerType); module_add_object(m, "Stream", &StreamType); module_add_object(m, "TriggerStream", &TriggerStreamType); module_add_object(m, "PVStream", &PVStreamType); module_add_object(m, "Dummy_base", &DummyType); module_add_object(m, "TriggerDummy_base", &TriggerDummyType); module_add_object(m, "TableStream", &TableStreamType); module_add_object(m, "MatrixStream", &MatrixStreamType); module_add_object(m, "Record_base", &RecordType); module_add_object(m, "ControlRec_base", &ControlRecType); module_add_object(m, "ControlRead_base", &ControlReadType); module_add_object(m, "NoteinRec_base", &NoteinRecType); module_add_object(m, "NoteinRead_base", &NoteinReadType); module_add_object(m, "Compare_base", &CompareType); module_add_object(m, "Mix_base", &MixType); module_add_object(m, "Sig_base", &SigType); module_add_object(m, "SigTo_base", &SigToType); module_add_object(m, "VarPort_base", &VarPortType); module_add_object(m, "InputFader_base", &InputFaderType); module_add_object(m, "Adsr_base", &AdsrType); module_add_object(m, "Linseg_base", &LinsegType); module_add_object(m, "Expseg_base", &ExpsegType); module_add_object(m, "HarmTable_base", &HarmTableType); module_add_object(m, "ChebyTable_base", &ChebyTableType); module_add_object(m, "HannTable_base", &HannTableType); module_add_object(m, "SincTable_base", &SincTableType); module_add_object(m, "WinTable_base", &WinTableType); module_add_object(m, "ParaTable_base", &ParaTableType); module_add_object(m, "LinTable_base", &LinTableType); module_add_object(m, "LogTable_base", &LogTableType); module_add_object(m, "CosLogTable_base", &CosLogTableType); module_add_object(m, "CosTable_base", &CosTableType); module_add_object(m, "CurveTable_base", &CurveTableType); module_add_object(m, "ExpTable_base", &ExpTableType); module_add_object(m, "SndTable_base", &SndTableType); module_add_object(m, "DataTable_base", &DataTableType); module_add_object(m, "NewTable_base", &NewTableType); module_add_object(m, "TableRec_base", &TableRecType); module_add_object(m, "TableRecTimeStream_base", &TableRecTimeStreamType); module_add_object(m, "TableMorph_base", &TableMorphType); module_add_object(m, "TrigTableRec_base", &TrigTableRecType); module_add_object(m, "TrigTableRecTimeStream_base", &TrigTableRecTimeStreamType); module_add_object(m, "TableWrite_base", &TableWriteType); module_add_object(m, "TablePut_base", &TablePutType); module_add_object(m, "NewMatrix_base", &NewMatrixType); module_add_object(m, "MatrixPointer_base", &MatrixPointerType); module_add_object(m, "MatrixRec_base", &MatrixRecType); module_add_object(m, "MatrixRecLoop_base", &MatrixRecLoopType); module_add_object(m, "MatrixMorph_base", &MatrixMorphType); module_add_object(m, "Input_base", &InputType); module_add_object(m, "Trig_base", &TrigType); module_add_object(m, "NextTrig_base", &NextTrigType); module_add_object(m, "Metro_base", &MetroType); module_add_object(m, "Seqer_base", &SeqerType); module_add_object(m, "Seq_base", &SeqType); module_add_object(m, "Clouder_base", &ClouderType); module_add_object(m, "Cloud_base", &CloudType); module_add_object(m, "Beater_base", &BeaterType); module_add_object(m, "Beat_base", &BeatType); module_add_object(m, "BeatTapStream_base", &BeatTapStreamType); module_add_object(m, "BeatAmpStream_base", &BeatAmpStreamType); module_add_object(m, "BeatDurStream_base", &BeatDurStreamType); module_add_object(m, "BeatEndStream_base", &BeatEndStreamType); module_add_object(m, "Fader_base", &FaderType); module_add_object(m, "Randi_base", &RandiType); module_add_object(m, "Randh_base", &RandhType); module_add_object(m, "Choice_base", &ChoiceType); module_add_object(m, "RandDur_base", &RandDurType); module_add_object(m, "Xnoise_base", &XnoiseType); module_add_object(m, "XnoiseMidi_base", &XnoiseMidiType); module_add_object(m, "XnoiseDur_base", &XnoiseDurType); module_add_object(m, "RandInt_base", &RandIntType); module_add_object(m, "Urn_base", &UrnType); module_add_object(m, "SfPlayer_base", &SfPlayerType); module_add_object(m, "SfPlay_base", &SfPlayType); module_add_object(m, "SfMarkerShuffler_base", &SfMarkerShufflerType); module_add_object(m, "SfMarkerShuffle_base", &SfMarkerShuffleType); module_add_object(m, "SfMarkerLooper_base", &SfMarkerLooperType); module_add_object(m, "SfMarkerLoop_base", &SfMarkerLoopType); module_add_object(m, "Osc_base", &OscType); module_add_object(m, "OscLoop_base", &OscLoopType); module_add_object(m, "OscTrig_base", &OscTrigType); module_add_object(m, "OscBank_base", &OscBankType); module_add_object(m, "SumOsc_base", &SumOscType); module_add_object(m, "TableRead_base", &TableReadType); module_add_object(m, "Pulsar_base", &PulsarType); module_add_object(m, "Sine_base", &SineType); module_add_object(m, "SineLoop_base", &SineLoopType); module_add_object(m, "Fm_base", &FmType); module_add_object(m, "CrossFm_base", &CrossFmType); module_add_object(m, "LFO_base", &LFOType); module_add_object(m, "Blit_base", &BlitType); module_add_object(m, "Rossler_base", &RosslerType); module_add_object(m, "RosslerAlt_base", &RosslerAltType); module_add_object(m, "Lorenz_base", &LorenzType); module_add_object(m, "LorenzAlt_base", &LorenzAltType); module_add_object(m, "Phasor_base", &PhasorType); module_add_object(m, "SuperSaw_base", &SuperSawType); module_add_object(m, "Pointer_base", &PointerType); module_add_object(m, "TableIndex_base", &TableIndexType); module_add_object(m, "Lookup_base", &LookupType); module_add_object(m, "Noise_base", &NoiseType); module_add_object(m, "PinkNoise_base", &PinkNoiseType); module_add_object(m, "BrownNoise_base", &BrownNoiseType); module_add_object(m, "Biquad_base", &BiquadType); module_add_object(m, "Biquadx_base", &BiquadxType); module_add_object(m, "Biquada_base", &BiquadaType); module_add_object(m, "EQ_base", &EQType); module_add_object(m, "Tone_base", &ToneType); module_add_object(m, "Atone_base", &AtoneType); module_add_object(m, "DCBlock_base", &DCBlockType); module_add_object(m, "Allpass_base", &AllpassType); module_add_object(m, "Allpass2_base", &Allpass2Type); module_add_object(m, "Phaser_base", &PhaserType); module_add_object(m, "Vocoder_base", &VocoderType); module_add_object(m, "Port_base", &PortType); module_add_object(m, "Denorm_base", &DenormType); module_add_object(m, "Disto_base", &DistoType); module_add_object(m, "Clip_base", &ClipType); module_add_object(m, "Mirror_base", &MirrorType); module_add_object(m, "Wrap_base", &WrapType); module_add_object(m, "Between_base", &BetweenType); module_add_object(m, "Degrade_base", &DegradeType); module_add_object(m, "Compress_base", &CompressType); module_add_object(m, "Gate_base", &GateType); module_add_object(m, "Balance_base", &BalanceType); module_add_object(m, "Delay_base", &DelayType); module_add_object(m, "SDelay_base", &SDelayType); module_add_object(m, "Waveguide_base", &WaveguideType); module_add_object(m, "AllpassWG_base", &AllpassWGType); module_add_object(m, "Midictl_base", &MidictlType); module_add_object(m, "CtlScan_base", &CtlScanType); module_add_object(m, "CtlScan2_base", &CtlScan2Type); module_add_object(m, "MidiNote_base", &MidiNoteType); module_add_object(m, "Notein_base", &NoteinType); module_add_object(m, "NoteinTrig_base", &NoteinTrigType); module_add_object(m, "Bendin_base", &BendinType); module_add_object(m, "Touchin_base", &TouchinType); module_add_object(m, "Programin_base", &PrograminType); module_add_object(m, "MidiAdsr_base", &MidiAdsrType); module_add_object(m, "MidiDelAdsr_base", &MidiDelAdsrType); module_add_object(m, "OscSend_base", &OscSendType); module_add_object(m, "OscDataSend_base", &OscDataSendType); module_add_object(m, "OscReceive_base", &OscReceiveType); module_add_object(m, "OscReceiver_base", &OscReceiverType); module_add_object(m, "OscListReceive_base", &OscListReceiveType); module_add_object(m, "OscListReceiver_base", &OscListReceiverType); module_add_object(m, "OscDataReceive_base", &OscDataReceiveType); module_add_object(m, "TrigRand_base", &TrigRandType); module_add_object(m, "TrigRandInt_base", &TrigRandIntType); module_add_object(m, "TrigVal_base", &TrigValType); module_add_object(m, "TrigChoice_base", &TrigChoiceType); module_add_object(m, "Iter_base", &IterType); module_add_object(m, "TrigEnv_base", &TrigEnvType); module_add_object(m, "TrigLinseg_base", &TrigLinsegType); module_add_object(m, "TrigExpseg_base", &TrigExpsegType); module_add_object(m, "TrigFunc_base", &TrigFuncType); module_add_object(m, "TrigXnoise_base", &TrigXnoiseType); module_add_object(m, "TrigXnoiseMidi_base", &TrigXnoiseMidiType); module_add_object(m, "Pattern_base", &PatternType); module_add_object(m, "CallAfter_base", &CallAfterType); module_add_object(m, "BandSplitter_base", &BandSplitterType); module_add_object(m, "BandSplit_base", &BandSplitType); module_add_object(m, "FourBandMain_base", &FourBandMainType); module_add_object(m, "FourBand_base", &FourBandType); module_add_object(m, "HilbertMain_base", &HilbertMainType); module_add_object(m, "Hilbert_base", &HilbertType); module_add_object(m, "Follower_base", &FollowerType); module_add_object(m, "Follower2_base", &Follower2Type); module_add_object(m, "ZCross_base", &ZCrossType); module_add_object(m, "SPanner_base", &SPannerType); module_add_object(m, "Panner_base", &PannerType); module_add_object(m, "Pan_base", &PanType); module_add_object(m, "SPan_base", &SPanType); module_add_object(m, "Switcher_base", &SwitcherType); module_add_object(m, "Switch_base", &SwitchType); module_add_object(m, "Selector_base", &SelectorType); module_add_object(m, "VoiceManager_base", &VoiceManagerType); module_add_object(m, "Mixer_base", &MixerType); module_add_object(m, "MixerVoice_base", &MixerVoiceType); module_add_object(m, "Counter_base", &CounterType); module_add_object(m, "Count_base", &CountType); module_add_object(m, "Thresh_base", &ThreshType); module_add_object(m, "Percent_base", &PercentType); module_add_object(m, "Timer_base", &TimerType); module_add_object(m, "Select_base", &SelectType); module_add_object(m, "Change_base", &ChangeType); module_add_object(m, "Score_base", &ScoreType); module_add_object(m, "Freeverb_base", &FreeverbType); module_add_object(m, "WGVerb_base", &WGVerbType); module_add_object(m, "Chorus_base", &ChorusType); module_add_object(m, "Convolve_base", &ConvolveType); module_add_object(m, "IRWinSinc_base", &IRWinSincType); module_add_object(m, "IRPulse_base", &IRPulseType); module_add_object(m, "IRAverage_base", &IRAverageType); module_add_object(m, "IRFM_base", &IRFMType); module_add_object(m, "Granulator_base", &GranulatorType); module_add_object(m, "Looper_base", &LooperType); module_add_object(m, "Harmonizer_base", &HarmonizerType); module_add_object(m, "Print_base", &PrintType); module_add_object(m, "M_Sin_base", &M_SinType); module_add_object(m, "M_Cos_base", &M_CosType); module_add_object(m, "M_Tan_base", &M_TanType); module_add_object(m, "M_Abs_base", &M_AbsType); module_add_object(m, "M_Sqrt_base", &M_SqrtType); module_add_object(m, "M_Log_base", &M_LogType); module_add_object(m, "M_Log2_base", &M_Log2Type); module_add_object(m, "M_Log10_base", &M_Log10Type); module_add_object(m, "M_Pow_base", &M_PowType); module_add_object(m, "M_Atan2_base", &M_Atan2Type); module_add_object(m, "M_Floor_base", &M_FloorType); module_add_object(m, "M_Ceil_base", &M_CeilType); module_add_object(m, "M_Round_base", &M_RoundType); module_add_object(m, "M_Tanh_base", &M_TanhType); module_add_object(m, "Snap_base", &SnapType); module_add_object(m, "Interp_base", &InterpType); module_add_object(m, "SampHold_base", &SampHoldType); module_add_object(m, "DBToA_base", &DBToAType); module_add_object(m, "AToDB_base", &AToDBType); module_add_object(m, "Scale_base", &ScaleType); module_add_object(m, "CentsToTranspo_base", &CentsToTranspoType); module_add_object(m, "TranspoToCents_base", &TranspoToCentsType); module_add_object(m, "MToF_base", &MToFType); module_add_object(m, "FToM_base", &FToMType); module_add_object(m, "MToT_base", &MToTType); module_add_object(m, "FFTMain_base", &FFTMainType); module_add_object(m, "FFT_base", &FFTType); module_add_object(m, "IFFT_base", &IFFTType); module_add_object(m, "CarToPol_base", &CarToPolType); module_add_object(m, "PolToCar_base", &PolToCarType); module_add_object(m, "FrameDeltaMain_base", &FrameDeltaMainType); module_add_object(m, "FrameDelta_base", &FrameDeltaType); module_add_object(m, "FrameAccum_base", &FrameAccumType); module_add_object(m, "FrameAccumMain_base", &FrameAccumMainType); module_add_object(m, "VectralMain_base", &VectralMainType); module_add_object(m, "Vectral_base", &VectralType); module_add_object(m, "Min_base", &MinType); module_add_object(m, "Max_base", &MaxType); module_add_object(m, "Delay1_base", &Delay1Type); module_add_object(m, "RCOsc_base", &RCOscType); module_add_object(m, "Yin_base", &YinType); module_add_object(m, "SVF_base", &SVFType); module_add_object(m, "Average_base", &AverageType); module_add_object(m, "CvlVerb_base", &CvlVerbType); module_add_object(m, "Spectrum_base", &SpectrumType); module_add_object(m, "Reson_base", &ResonType); module_add_object(m, "Resonx_base", &ResonxType); module_add_object(m, "ButLP_base", &ButLPType); module_add_object(m, "ButHP_base", &ButHPType); module_add_object(m, "ButBP_base", &ButBPType); module_add_object(m, "ButBR_base", &ButBRType); module_add_object(m, "PVAnal_base", &PVAnalType); module_add_object(m, "PVSynth_base", &PVSynthType); module_add_object(m, "PVTranspose_base", &PVTransposeType); module_add_object(m, "PVVerb_base", &PVVerbType); module_add_object(m, "PVGate_base", &PVGateType); module_add_object(m, "PVAddSynth_base", &PVAddSynthType); module_add_object(m, "PVCross_base", &PVCrossType); module_add_object(m, "PVMult_base", &PVMultType); module_add_object(m, "PVMorph_base", &PVMorphType); module_add_object(m, "PVFilter_base", &PVFilterType); module_add_object(m, "PVDelay_base", &PVDelayType); module_add_object(m, "PVBuffer_base", &PVBufferType); module_add_object(m, "PVShift_base", &PVShiftType); module_add_object(m, "PVAmpMod_base", &PVAmpModType); module_add_object(m, "PVFreqMod_base", &PVFreqModType); module_add_object(m, "PVBufLoops_base", &PVBufLoopsType); module_add_object(m, "PVBufTabLoops_base", &PVBufTabLoopsType); module_add_object(m, "PVMix_base", &PVMixType); module_add_object(m, "Granule_base", &GranuleType); module_add_object(m, "TableScale_base", &TableScaleType); module_add_object(m, "TrackHold_base", &TrackHoldType); module_add_object(m, "ComplexRes_base", &ComplexResType); module_add_object(m, "STReverb_base", &STReverbType); module_add_object(m, "STRev_base", &STRevType); module_add_object(m, "Pointer2_base", &Pointer2Type); module_add_object(m, "Centroid_base", &CentroidType); module_add_object(m, "AttackDetector_base", &AttackDetectorType); module_add_object(m, "SmoothDelay_base", &SmoothDelayType); module_add_object(m, "TrigBurster_base", &TrigBursterType); module_add_object(m, "TrigBurst_base", &TrigBurstType); module_add_object(m, "TrigBurstTapStream_base", &TrigBurstTapStreamType); module_add_object(m, "TrigBurstAmpStream_base", &TrigBurstAmpStreamType); module_add_object(m, "TrigBurstDurStream_base", &TrigBurstDurStreamType); module_add_object(m, "TrigBurstEndStream_base", &TrigBurstEndStreamType); module_add_object(m, "Scope_base", &ScopeType); module_add_object(m, "PeakAmp_base", &PeakAmpType); module_add_object(m, "MainParticle_base", &MainParticleType); module_add_object(m, "Particle_base", &ParticleType); module_add_object(m, "AtanTable_base", &AtanTableType); module_add_object(m, "RawMidi_base", &RawMidiType); module_add_object(m, "Resample_base", &ResampleType); module_add_object(m, "Expr_base", &ExprType); PyModule_AddStringConstant(m, "PYO_VERSION", PYO_VERSION); #ifdef COMPILE_EXTERNALS EXTERNAL_OBJECTS PyModule_AddIntConstant(m, "WITH_EXTERNALS", 1); #else PyModule_AddIntConstant(m, "WITH_EXTERNALS", 0); #endif #ifndef USE_DOUBLE PyModule_AddIntConstant(m, "USE_DOUBLE", 0); #else PyModule_AddIntConstant(m, "USE_DOUBLE", 1); #endif }pyo/src/engine/dummymodule.c0000644000175000017500000005675112652732202015435 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" static void Dummy_postprocessing_ii(Dummy *self) { POST_PROCESSING_II }; static void Dummy_postprocessing_ai(Dummy *self) { POST_PROCESSING_AI }; static void Dummy_postprocessing_ia(Dummy *self) { POST_PROCESSING_IA }; static void Dummy_postprocessing_aa(Dummy *self) { POST_PROCESSING_AA }; static void Dummy_postprocessing_ireva(Dummy *self) { POST_PROCESSING_IREVA }; static void Dummy_postprocessing_areva(Dummy *self) { POST_PROCESSING_AREVA }; static void Dummy_postprocessing_revai(Dummy *self) { POST_PROCESSING_REVAI }; static void Dummy_postprocessing_revaa(Dummy *self) { POST_PROCESSING_REVAA }; static void Dummy_postprocessing_revareva(Dummy *self) { POST_PROCESSING_REVAREVA }; static void Dummy_setProcMode(Dummy *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Dummy_postprocessing_ii; break; case 1: self->muladd_func_ptr = Dummy_postprocessing_ai; break; case 2: self->muladd_func_ptr = Dummy_postprocessing_revai; break; case 10: self->muladd_func_ptr = Dummy_postprocessing_ia; break; case 11: self->muladd_func_ptr = Dummy_postprocessing_aa; break; case 12: self->muladd_func_ptr = Dummy_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Dummy_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Dummy_postprocessing_areva; break; case 22: self->muladd_func_ptr = Dummy_postprocessing_revareva; break; } } static void Dummy_compute_next_data_frame(Dummy *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = in[i]; } (*self->muladd_func_ptr)(self); } static int Dummy_traverse(Dummy *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Dummy_clear(Dummy *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Dummy_dealloc(Dummy* self) { pyo_DEALLOC Dummy_clear(self); self->ob_type->tp_free((PyObject*)self); } PyObject * Dummy_initialize(Dummy *self) { int i; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Dummy_compute_next_data_frame); self->mode_func_ptr = Dummy_setProcMode; PyObject_CallMethod(self->server, "addStream", "O", self->stream); Stream_setStreamActive(self->stream, 1); Py_INCREF(Py_None); return Py_None; } static PyObject * Dummy_setInput(Dummy *self, PyObject *arg) { PyObject *tmp, *streamtmp; tmp = arg; Py_INCREF(tmp); Py_XDECREF(self->input); self->input = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (Stream *)streamtmp; (*self->mode_func_ptr)(self); Dummy_compute_next_data_frame(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Dummy_getServer(Dummy* self) { GET_SERVER }; static PyObject * Dummy_getStream(Dummy* self) { GET_STREAM }; static PyObject * Dummy_setMul(Dummy *self, PyObject *arg) { SET_MUL }; static PyObject * Dummy_setAdd(Dummy *self, PyObject *arg) { SET_ADD }; static PyObject * Dummy_setSub(Dummy *self, PyObject *arg) { SET_SUB }; static PyObject * Dummy_setDiv(Dummy *self, PyObject *arg) { SET_DIV }; static PyObject * Dummy_play(Dummy *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Dummy_out(Dummy *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Dummy_stop(Dummy *self) { STOP }; static PyObject * Dummy_multiply(Dummy *self, PyObject *arg) { MULTIPLY }; static PyObject * Dummy_inplace_multiply(Dummy *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Dummy_add(Dummy *self, PyObject *arg) { ADD }; static PyObject * Dummy_inplace_add(Dummy *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Dummy_sub(Dummy *self, PyObject *arg) { SUB }; static PyObject * Dummy_inplace_sub(Dummy *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Dummy_div(Dummy *self, PyObject *arg) { DIV }; static PyObject * Dummy_inplace_div(Dummy *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Dummy_members[] = { {"server", T_OBJECT_EX, offsetof(Dummy, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Dummy, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Dummy, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(Dummy, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Dummy, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Dummy_methods[] = { {"getServer", (PyCFunction)Dummy_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Dummy_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Dummy_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Dummy_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Dummy_stop, METH_NOARGS, "Stops computing."}, {"setInput", (PyCFunction)Dummy_setInput, METH_O, "Sets the input sound object."}, {"setMul", (PyCFunction)Dummy_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)Dummy_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)Dummy_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Dummy_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Dummy_as_number = { (binaryfunc)Dummy_add, /*nb_add*/ (binaryfunc)Dummy_sub, /*nb_subtract*/ (binaryfunc)Dummy_multiply, /*nb_multiply*/ (binaryfunc)Dummy_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Dummy_inplace_add, /*inplace_add*/ (binaryfunc)Dummy_inplace_sub, /*inplace_subtract*/ (binaryfunc)Dummy_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Dummy_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject DummyType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Dummy_base", /*tp_name*/ sizeof(Dummy), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Dummy_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Dummy_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Dummy objects.", /* tp_doc */ (traverseproc)Dummy_traverse, /* tp_traverse */ (inquiry)Dummy_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Dummy_methods, /* tp_methods */ Dummy_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; /************************************************************************************************/ /* TriggerDummy streamer */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD PyObject *input; TriggerStream *input_stream; int modebuffer[2]; } TriggerDummy; static void TriggerDummy_postprocessing_ii(TriggerDummy *self) { POST_PROCESSING_II }; static void TriggerDummy_postprocessing_ai(TriggerDummy *self) { POST_PROCESSING_AI }; static void TriggerDummy_postprocessing_ia(TriggerDummy *self) { POST_PROCESSING_IA }; static void TriggerDummy_postprocessing_aa(TriggerDummy *self) { POST_PROCESSING_AA }; static void TriggerDummy_postprocessing_ireva(TriggerDummy *self) { POST_PROCESSING_IREVA }; static void TriggerDummy_postprocessing_areva(TriggerDummy *self) { POST_PROCESSING_AREVA }; static void TriggerDummy_postprocessing_revai(TriggerDummy *self) { POST_PROCESSING_REVAI }; static void TriggerDummy_postprocessing_revaa(TriggerDummy *self) { POST_PROCESSING_REVAA }; static void TriggerDummy_postprocessing_revareva(TriggerDummy *self) { POST_PROCESSING_REVAREVA }; static void TriggerDummy_setProcMode(TriggerDummy *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = TriggerDummy_postprocessing_ii; break; case 1: self->muladd_func_ptr = TriggerDummy_postprocessing_ai; break; case 2: self->muladd_func_ptr = TriggerDummy_postprocessing_revai; break; case 10: self->muladd_func_ptr = TriggerDummy_postprocessing_ia; break; case 11: self->muladd_func_ptr = TriggerDummy_postprocessing_aa; break; case 12: self->muladd_func_ptr = TriggerDummy_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TriggerDummy_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TriggerDummy_postprocessing_areva; break; case 22: self->muladd_func_ptr = TriggerDummy_postprocessing_revareva; break; } } static void TriggerDummy_compute_next_data_frame(TriggerDummy *self) { int i; MYFLT *tmp = TriggerStream_getData((TriggerStream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = tmp[i]; } (*self->muladd_func_ptr)(self); } static int TriggerDummy_traverse(TriggerDummy *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int TriggerDummy_clear(TriggerDummy *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void TriggerDummy_dealloc(TriggerDummy* self) { pyo_DEALLOC TriggerDummy_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TriggerDummy_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp; TriggerDummy *self; self = (TriggerDummy *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TriggerDummy_compute_next_data_frame); self->mode_func_ptr = TriggerDummy_setProcMode; static char *kwlist[] = {"input", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &inputtmp)) Py_RETURN_NONE; INIT_INPUT_TRIGGER_STREAM PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TriggerDummy_getServer(TriggerDummy* self) { GET_SERVER }; static PyObject * TriggerDummy_getStream(TriggerDummy* self) { GET_STREAM }; static PyObject * TriggerDummy_setMul(TriggerDummy *self, PyObject *arg) { SET_MUL }; static PyObject * TriggerDummy_setAdd(TriggerDummy *self, PyObject *arg) { SET_ADD }; static PyObject * TriggerDummy_setSub(TriggerDummy *self, PyObject *arg) { SET_SUB }; static PyObject * TriggerDummy_setDiv(TriggerDummy *self, PyObject *arg) { SET_DIV }; static PyObject * TriggerDummy_play(TriggerDummy *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TriggerDummy_stop(TriggerDummy *self) { STOP }; static PyObject * TriggerDummy_multiply(TriggerDummy *self, PyObject *arg) { MULTIPLY }; static PyObject * TriggerDummy_inplace_multiply(TriggerDummy *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TriggerDummy_add(TriggerDummy *self, PyObject *arg) { ADD }; static PyObject * TriggerDummy_inplace_add(TriggerDummy *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TriggerDummy_sub(TriggerDummy *self, PyObject *arg) { SUB }; static PyObject * TriggerDummy_inplace_sub(TriggerDummy *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TriggerDummy_div(TriggerDummy *self, PyObject *arg) { DIV }; static PyObject * TriggerDummy_inplace_div(TriggerDummy *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef TriggerDummy_members[] = { {"server", T_OBJECT_EX, offsetof(TriggerDummy, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TriggerDummy, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(TriggerDummy, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TriggerDummy, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TriggerDummy_methods[] = { {"getServer", (PyCFunction)TriggerDummy_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TriggerDummy_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TriggerDummy_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)TriggerDummy_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)TriggerDummy_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TriggerDummy_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TriggerDummy_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TriggerDummy_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TriggerDummy_as_number = { (binaryfunc)TriggerDummy_add, /*nb_add*/ (binaryfunc)TriggerDummy_sub, /*nb_subtract*/ (binaryfunc)TriggerDummy_multiply, /*nb_multiply*/ (binaryfunc)TriggerDummy_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TriggerDummy_inplace_add, /*inplace_add*/ (binaryfunc)TriggerDummy_inplace_sub, /*inplace_subtract*/ (binaryfunc)TriggerDummy_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TriggerDummy_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TriggerDummyType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TriggerDummy_base", /*tp_name*/ sizeof(TriggerDummy), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TriggerDummy_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TriggerDummy_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TriggerDummy objects. Sends trigger at the end of playback.", /* tp_doc */ (traverseproc)TriggerDummy_traverse, /* tp_traverse */ (inquiry)TriggerDummy_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TriggerDummy_methods, /* tp_methods */ TriggerDummy_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TriggerDummy_new, /* tp_new */ };pyo/src/objects/0000755000175000017500000000000012652732202013076 5ustar tiagotiagopyo/src/objects/oscbankmodule.c0000644000175000017500000007557212652732202016110 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "tablemodule.h" /*******************/ /***** OscBank ******/ /*******************/ static MYFLT OscBank_clip(MYFLT x, int size) { if (x >= size) { x -= (int)(x / size) * size; } else if (x < 0) { x += ((int)(-x / size) + 1) * size; } return x; } typedef struct { pyo_audio_HEAD PyObject *table; PyObject *freq; Stream *freq_stream; PyObject *spread; Stream *spread_stream; PyObject *slope; Stream *slope_stream; PyObject *frndf; Stream *frndf_stream; PyObject *frnda; Stream *frnda_stream; PyObject *arndf; Stream *arndf_stream; PyObject *arnda; Stream *arnda_stream; int stages; int fjit; int modebuffer[9]; MYFLT *pointerPos; MYFLT *frequencies; MYFLT lastFreq; MYFLT lastSpread; int lastFjit; MYFLT amplitude; /* frequency randoms */ MYFLT ftime; MYFLT finc; MYFLT *fOldValues; MYFLT *fValues; MYFLT *fDiffs; /* amplitude randoms */ MYFLT atime; MYFLT ainc; MYFLT *aOldValues; MYFLT *aValues; MYFLT *aDiffs; } OscBank; static void OscBank_setFrequencies(OscBank *self, MYFLT freq, MYFLT spread) { int i, seed; MYFLT rnd; MYFLT scl = freq * spread; if (self->fjit == 1) { seed = rand(); for (i=0; istages; i++) { seed = (seed * 15625 + 1) & 0xFFFF; rnd = seed * 1.52587890625e-07 - 0.005 + 1.0; self->frequencies[i] = (freq + scl * i) * rnd; /* printf("harm %d : %f Hz\n", i, self->frequencies[i]); */ } } else { for (i=0; istages; i++) { self->frequencies[i] = freq + scl * i; /* printf("harm %d : %f Hz\n", i, self->frequencies[i]); */ } } } static void OscBank_pickNewFrnds(OscBank *self, MYFLT frndf, MYFLT frnda) { int i, seed; self->ftime -= 1.0; self->finc = frndf / self->sr * self->bufsize; if (frnda < 0) frnda = 0.0; else if (frnda > 1.0) frnda = 1.0; seed = rand(); for (i=0; istages; i++) { self->fOldValues[i] = self->fValues[i]; seed = (seed * 15625 + 1) & 0xFFFF; self->fValues[i] = (seed - 0x8000) * 3.0517578125e-05 * frnda * self->frequencies[i]; self->fDiffs[i] = self->fValues[i] - self->fOldValues[i]; } } static void OscBank_pickNewArnds(OscBank *self, MYFLT arndf, MYFLT arnda) { int i, seed; self->atime -= 1.0; self->ainc = arndf / self->sr * self->bufsize; if (arnda < 0) arnda = 0.0; else if (arnda > 1.0) arnda = 1.0; seed = rand(); for (i=0; istages; i++) { self->aOldValues[i] = self->aValues[i]; seed = (seed * 15625 + 1) & 0xFFFF; self->aValues[i] = seed * 1.52587890625e-05 * arnda; self->aDiffs[i] = self->aValues[i] - self->aOldValues[i]; } } static void OscBank_readframes(OscBank *self) { MYFLT freq, spread, slope, frndf, frnda, arndf, arnda, amp, modamp, pos, inc, x, y, fpart; int i, j, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT tabscl = size / self->sr; for (i=0; ibufsize; i++) { self->data[i] = 0.0; } if (self->modebuffer[2] == 0) freq = PyFloat_AS_DOUBLE(self->freq); else freq = Stream_getData((Stream *)self->freq_stream)[0]; if (self->modebuffer[3] == 0) spread = PyFloat_AS_DOUBLE(self->spread); else spread = Stream_getData((Stream *)self->spread_stream)[0]; if (self->modebuffer[4] == 0) slope = PyFloat_AS_DOUBLE(self->slope); else slope = Stream_getData((Stream *)self->slope_stream)[0]; if (self->modebuffer[5] == 0) frndf = PyFloat_AS_DOUBLE(self->frndf); else frndf = Stream_getData((Stream *)self->frndf_stream)[0]; if (self->modebuffer[6] == 0) frnda = PyFloat_AS_DOUBLE(self->frnda); else frnda = Stream_getData((Stream *)self->frnda_stream)[0]; if (self->modebuffer[7] == 0) arndf = PyFloat_AS_DOUBLE(self->arndf); else arndf = Stream_getData((Stream *)self->arndf_stream)[0]; if (self->modebuffer[8] == 0) arnda = PyFloat_AS_DOUBLE(self->arnda); else arnda = Stream_getData((Stream *)self->arnda_stream)[0]; if (freq != self->lastFreq || spread != self->lastSpread) { self->lastFreq = freq; self->lastSpread = spread; OscBank_setFrequencies(self, freq, spread); } if (self->fjit != self->lastFjit) { self->lastFjit = self->fjit; OscBank_setFrequencies(self, freq, spread); if (self->fjit == 0) { for (i=0; istages; i++) { self->pointerPos[i] = 0.0; } } } if (frnda == 0.0 && arnda == 0.0) { amp = self->amplitude; for (j=0; jstages; j++) { inc = self->frequencies[j] * tabscl; pos = self->pointerPos[j]; for (i=0; ibufsize; i++) { pos = OscBank_clip(pos, size); ipart = (int)pos; fpart = pos - ipart; x = tablelist[ipart]; y = tablelist[ipart+1]; self->data[i] += (x + (y - x) * fpart) * amp; pos += inc; } self->pointerPos[j] = pos; amp *= slope; } } else if (frnda != 0.0 && arnda != 0.0) { if (self->ftime >= 1.0) { OscBank_pickNewFrnds(self, frndf, frnda); } if (self->atime >= 1.0) { OscBank_pickNewArnds(self, arndf, arnda); } amp = self->amplitude; for (j=0; jstages; j++) { inc = (self->frequencies[j] + (self->fOldValues[j] + self->fDiffs[j] * self->ftime)) * tabscl; pos = self->pointerPos[j]; modamp = (1.0 - arnda) + (self->aOldValues[j] + self->aDiffs[j] * self->atime); for (i=0; ibufsize; i++) { pos = OscBank_clip(pos, size); ipart = (int)pos; fpart = pos - ipart; x = tablelist[ipart]; y = tablelist[ipart+1]; self->data[i] += (x + (y - x) * fpart) * amp * modamp; pos += inc; } self->pointerPos[j] = pos; amp *= slope; } self->ftime += self->finc; self->atime += self->ainc; } else if (frnda != 0.0 && arnda == 0.0) { if (self->ftime >= 1.0) { OscBank_pickNewFrnds(self, frndf, frnda); } amp = self->amplitude; for (j=0; jstages; j++) { inc = (self->frequencies[j] + (self->fOldValues[j] + self->fDiffs[j] * self->ftime)) * tabscl; pos = self->pointerPos[j]; for (i=0; ibufsize; i++) { pos = OscBank_clip(pos, size); ipart = (int)pos; fpart = pos - ipart; x = tablelist[ipart]; y = tablelist[ipart+1]; self->data[i] += (x + (y - x) * fpart) * amp; pos += inc; } self->pointerPos[j] = pos; amp *= slope; } self->ftime += self->finc; } else if (frnda == 0.0 && arnda != 0.0) { if (self->atime >= 1.0) { OscBank_pickNewArnds(self, arndf, arnda); } amp = self->amplitude; for (j=0; jstages; j++) { inc = self->frequencies[j] * tabscl; pos = self->pointerPos[j]; modamp = (1.0 - arnda) + (self->aOldValues[j] + self->aDiffs[j] * self->atime); for (i=0; ibufsize; i++) { pos = OscBank_clip(pos, size); ipart = (int)pos; fpart = pos - ipart; x = tablelist[ipart]; y = tablelist[ipart+1]; self->data[i] += (x + (y - x) * fpart) * amp * modamp; pos += inc; } self->pointerPos[j] = pos; amp *= slope; } self->atime += self->ainc; } } static void OscBank_postprocessing_ii(OscBank *self) { POST_PROCESSING_II }; static void OscBank_postprocessing_ai(OscBank *self) { POST_PROCESSING_AI }; static void OscBank_postprocessing_ia(OscBank *self) { POST_PROCESSING_IA }; static void OscBank_postprocessing_aa(OscBank *self) { POST_PROCESSING_AA }; static void OscBank_postprocessing_ireva(OscBank *self) { POST_PROCESSING_IREVA }; static void OscBank_postprocessing_areva(OscBank *self) { POST_PROCESSING_AREVA }; static void OscBank_postprocessing_revai(OscBank *self) { POST_PROCESSING_REVAI }; static void OscBank_postprocessing_revaa(OscBank *self) { POST_PROCESSING_REVAA }; static void OscBank_postprocessing_revareva(OscBank *self) { POST_PROCESSING_REVAREVA }; static void OscBank_setProcMode(OscBank *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = OscBank_readframes; switch (muladdmode) { case 0: self->muladd_func_ptr = OscBank_postprocessing_ii; break; case 1: self->muladd_func_ptr = OscBank_postprocessing_ai; break; case 2: self->muladd_func_ptr = OscBank_postprocessing_revai; break; case 10: self->muladd_func_ptr = OscBank_postprocessing_ia; break; case 11: self->muladd_func_ptr = OscBank_postprocessing_aa; break; case 12: self->muladd_func_ptr = OscBank_postprocessing_revaa; break; case 20: self->muladd_func_ptr = OscBank_postprocessing_ireva; break; case 21: self->muladd_func_ptr = OscBank_postprocessing_areva; break; case 22: self->muladd_func_ptr = OscBank_postprocessing_revareva; break; } } static void OscBank_compute_next_data_frame(OscBank *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int OscBank_traverse(OscBank *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->spread); Py_VISIT(self->spread_stream); Py_VISIT(self->slope); Py_VISIT(self->slope_stream); Py_VISIT(self->frndf); Py_VISIT(self->frndf_stream); Py_VISIT(self->frnda); Py_VISIT(self->frnda_stream); Py_VISIT(self->arndf); Py_VISIT(self->arndf_stream); Py_VISIT(self->arnda); Py_VISIT(self->arnda_stream); return 0; } static int OscBank_clear(OscBank *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->spread); Py_CLEAR(self->spread_stream); Py_CLEAR(self->slope); Py_CLEAR(self->slope_stream); Py_CLEAR(self->frndf); Py_CLEAR(self->frndf_stream); Py_CLEAR(self->frnda); Py_CLEAR(self->frnda_stream); Py_CLEAR(self->arndf); Py_CLEAR(self->arndf_stream); Py_CLEAR(self->arnda); Py_CLEAR(self->arnda_stream); return 0; } static void OscBank_dealloc(OscBank* self) { pyo_DEALLOC free(self->pointerPos); free(self->frequencies); free(self->fOldValues); free(self->fValues); free(self->fDiffs); free(self->aOldValues); free(self->aValues); free(self->aDiffs); OscBank_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * OscBank_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *tabletmp, *freqtmp=NULL, *spreadtmp=NULL, *slopetmp=NULL, *frndftmp=NULL, *frndatmp=NULL, *arndftmp=NULL, *arndatmp=NULL, *multmp=NULL, *addtmp=NULL; OscBank *self; self = (OscBank *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(100.0); self->spread = PyFloat_FromDouble(1.0); self->slope = PyFloat_FromDouble(0.9); self->frndf = PyFloat_FromDouble(1.0); self->frnda = PyFloat_FromDouble(0.0); self->arndf = PyFloat_FromDouble(1.0); self->arnda = PyFloat_FromDouble(0.0); self->stages = 24; self->fjit = 0; self->lastFreq = self->lastSpread = -1.0; self->lastFjit = -1; self->ftime = 1.0; self->finc = 0.0; self->atime = 1.0; self->ainc = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->modebuffer[5] = 0; self->modebuffer[6] = 0; self->modebuffer[7] = 0; self->modebuffer[8] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, OscBank_compute_next_data_frame); self->mode_func_ptr = OscBank_setProcMode; static char *kwlist[] = {"table", "freq", "spread", "slope", "frndf", "frnda", "arndf", "arnda", "num", "fjit", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOOOOiiOO", kwlist, &tabletmp, &freqtmp, &spreadtmp, &slopetmp, &frndftmp, &frndatmp, &arndftmp, &arndatmp, &self->stages, &self->fjit, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of OscBank must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (spreadtmp) { PyObject_CallMethod((PyObject *)self, "setSpread", "O", spreadtmp); } if (slopetmp) { PyObject_CallMethod((PyObject *)self, "setSlope", "O", slopetmp); } if (frndftmp) { PyObject_CallMethod((PyObject *)self, "setFrndf", "O", frndftmp); } if (frndatmp) { PyObject_CallMethod((PyObject *)self, "setFrnda", "O", frndatmp); } if (arndftmp) { PyObject_CallMethod((PyObject *)self, "setArndf", "O", arndftmp); } if (arndatmp) { PyObject_CallMethod((PyObject *)self, "setArnda", "O", arndatmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); self->pointerPos = (MYFLT *)realloc(self->pointerPos, self->stages * sizeof(MYFLT)); self->frequencies = (MYFLT *)realloc(self->frequencies, self->stages * sizeof(MYFLT)); self->fOldValues = (MYFLT *)realloc(self->fOldValues, self->stages * sizeof(MYFLT)); self->fValues = (MYFLT *)realloc(self->fValues, self->stages * sizeof(MYFLT)); self->fDiffs = (MYFLT *)realloc(self->fDiffs, self->stages * sizeof(MYFLT)); self->aOldValues = (MYFLT *)realloc(self->aOldValues, self->stages * sizeof(MYFLT)); self->aValues = (MYFLT *)realloc(self->aValues, self->stages * sizeof(MYFLT)); self->aDiffs = (MYFLT *)realloc(self->aDiffs, self->stages * sizeof(MYFLT)); for (i=0; istages; i++) { self->pointerPos[i] = self->frequencies[i] = self->fOldValues[i] = self->fValues[i] = self->fDiffs[i] = self->aOldValues[i] = self->aValues[i] = self->aDiffs[i] = 0.0; } self->amplitude = 1. / self->stages; Server_generateSeed((Server *)self->server, OSCBANK_ID); return (PyObject *)self; } static PyObject * OscBank_getServer(OscBank* self) { GET_SERVER }; static PyObject * OscBank_getStream(OscBank* self) { GET_STREAM }; static PyObject * OscBank_setMul(OscBank *self, PyObject *arg) { SET_MUL }; static PyObject * OscBank_setAdd(OscBank *self, PyObject *arg) { SET_ADD }; static PyObject * OscBank_setSub(OscBank *self, PyObject *arg) { SET_SUB }; static PyObject * OscBank_setDiv(OscBank *self, PyObject *arg) { SET_DIV }; static PyObject * OscBank_play(OscBank *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * OscBank_out(OscBank *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * OscBank_stop(OscBank *self) { STOP }; static PyObject * OscBank_multiply(OscBank *self, PyObject *arg) { MULTIPLY }; static PyObject * OscBank_inplace_multiply(OscBank *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * OscBank_add(OscBank *self, PyObject *arg) { ADD }; static PyObject * OscBank_inplace_add(OscBank *self, PyObject *arg) { INPLACE_ADD }; static PyObject * OscBank_sub(OscBank *self, PyObject *arg) { SUB }; static PyObject * OscBank_inplace_sub(OscBank *self, PyObject *arg) { INPLACE_SUB }; static PyObject * OscBank_div(OscBank *self, PyObject *arg) { DIV }; static PyObject * OscBank_inplace_div(OscBank *self, PyObject *arg) { INPLACE_DIV }; static PyObject * OscBank_getTable(OscBank *self) { Py_INCREF(self->table); return self->table; }; static PyObject * OscBank_setTable(OscBank *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * OscBank_setFreq(OscBank *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * OscBank_setSpread(OscBank *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->spread); if (isNumber == 1) { self->spread = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->spread = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->spread, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->spread_stream); self->spread_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * OscBank_setSlope(OscBank *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->slope); if (isNumber == 1) { self->slope = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->slope = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->slope, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->slope_stream); self->slope_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * OscBank_setFrndf(OscBank *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->frndf); if (isNumber == 1) { self->frndf = PyNumber_Float(tmp); self->modebuffer[5] = 0; } else { self->frndf = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->frndf, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->frndf_stream); self->frndf_stream = (Stream *)streamtmp; self->modebuffer[5] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * OscBank_setFrnda(OscBank *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->frnda); if (isNumber == 1) { self->frnda = PyNumber_Float(tmp); self->modebuffer[6] = 0; } else { self->frnda = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->frnda, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->frnda_stream); self->frnda_stream = (Stream *)streamtmp; self->modebuffer[6] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * OscBank_setArndf(OscBank *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->arndf); if (isNumber == 1) { self->arndf = PyNumber_Float(tmp); self->modebuffer[7] = 0; } else { self->arndf = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->arndf, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->arndf_stream); self->arndf_stream = (Stream *)streamtmp; self->modebuffer[7] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * OscBank_setArnda(OscBank *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->arnda); if (isNumber == 1) { self->arnda = PyNumber_Float(tmp); self->modebuffer[8] = 0; } else { self->arnda = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->arnda, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->arnda_stream); self->arnda_stream = (Stream *)streamtmp; self->modebuffer[8] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * OscBank_setFjit(OscBank *self, PyObject *arg) { int isInt = PyInt_Check(arg); if (isInt) { self->fjit = PyInt_AS_LONG(arg); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef OscBank_members[] = { {"server", T_OBJECT_EX, offsetof(OscBank, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(OscBank, stream), 0, "Stream object."}, {"table", T_OBJECT_EX, offsetof(OscBank, table), 0, "Waveform table."}, {"freq", T_OBJECT_EX, offsetof(OscBank, freq), 0, "Base frequency in Hertz."}, {"spread", T_OBJECT_EX, offsetof(OscBank, spread), 0, "Frequencies spreading factor."}, {"slope", T_OBJECT_EX, offsetof(OscBank, slope), 0, "Amplitude slope factor."}, {"frndf", T_OBJECT_EX, offsetof(OscBank, frndf), 0, "Frequency of random frequency changes."}, {"frnda", T_OBJECT_EX, offsetof(OscBank, frnda), 0, "Amplitude of random frequency changes."}, {"mul", T_OBJECT_EX, offsetof(OscBank, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(OscBank, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef OscBank_methods[] = { {"getTable", (PyCFunction)OscBank_getTable, METH_NOARGS, "Returns waveform table object."}, {"getServer", (PyCFunction)OscBank_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)OscBank_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)OscBank_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)OscBank_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)OscBank_stop, METH_NOARGS, "Stops computing."}, {"setTable", (PyCFunction)OscBank_setTable, METH_O, "Sets oscillator table."}, {"setFreq", (PyCFunction)OscBank_setFreq, METH_O, "Sets base frequency in Hertz."}, {"setSpread", (PyCFunction)OscBank_setSpread, METH_O, "Sets spreading factor."}, {"setSlope", (PyCFunction)OscBank_setSlope, METH_O, "Sets oscillators amplitude slope factor."}, {"setFrndf", (PyCFunction)OscBank_setFrndf, METH_O, "Sets frequency of random frequency changes."}, {"setFrnda", (PyCFunction)OscBank_setFrnda, METH_O, "Sets amplitude of random frequency changes."}, {"setArndf", (PyCFunction)OscBank_setArndf, METH_O, "Sets frequency of random amplitude changes."}, {"setArnda", (PyCFunction)OscBank_setArnda, METH_O, "Sets amplitude of random amplitude changes."}, {"setFjit", (PyCFunction)OscBank_setFjit, METH_O, "Sets frequencies jitter on/off switch."}, {"setMul", (PyCFunction)OscBank_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)OscBank_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)OscBank_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)OscBank_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods OscBank_as_number = { (binaryfunc)OscBank_add, /*nb_add*/ (binaryfunc)OscBank_sub, /*nb_subtract*/ (binaryfunc)OscBank_multiply, /*nb_multiply*/ (binaryfunc)OscBank_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)OscBank_inplace_add, /*inplace_add*/ (binaryfunc)OscBank_inplace_sub, /*inplace_subtract*/ (binaryfunc)OscBank_inplace_multiply, /*inplace_multiply*/ (binaryfunc)OscBank_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject OscBankType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.OscBank_base", /*tp_name*/ sizeof(OscBank), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)OscBank_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &OscBank_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "OscBank objects. Oscillator bank.", /* tp_doc */ (traverseproc)OscBank_traverse, /* tp_traverse */ (inquiry)OscBank_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ OscBank_methods, /* tp_methods */ OscBank_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ OscBank_new, /* tp_new */ }; pyo/src/objects/fftmodule.c0000644000175000017500000046107012652732202015237 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "fft.h" #include "wind.h" #include "sndfile.h" static int isPowerOfTwo(int x) { return (x != 0) && ((x & (x - 1)) == 0); } typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int size; int hsize; int hopsize; int wintype; int incount; MYFLT *inframe; MYFLT *outframe; MYFLT *window; MYFLT **twiddle; MYFLT *twiddle2; MYFLT *buffer_streams; } FFTMain; static void FFTMain_realloc_memories(FFTMain *self) { int i, n8; self->hsize = self->size / 2; n8 = self->size >> 3; self->inframe = (MYFLT *)realloc(self->inframe, self->size * sizeof(MYFLT)); self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT)); for (i=0; isize; i++) self->inframe[i] = self->outframe[i] = 0.0; self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, 3 * self->bufsize * sizeof(MYFLT)); for (i=0; i<(self->bufsize*3); i++) self->buffer_streams[i] = 0.0; self->twiddle = (MYFLT **)realloc(self->twiddle, 4 * sizeof(MYFLT *)); for(i=0; i<4; i++) self->twiddle[i] = (MYFLT *)malloc(n8 * sizeof(MYFLT)); fft_compute_split_twiddle(self->twiddle, self->size); self->twiddle2 = (MYFLT *)realloc(self->twiddle2, self->size * sizeof(MYFLT)); fft_compute_radix2_twiddle(self->twiddle2, self->size); self->window = (MYFLT *)realloc(self->window, self->size * sizeof(MYFLT)); gen_window(self->window, self->size, self->wintype); self->incount = -self->hopsize; } static void FFTMain_filters(FFTMain *self) { int i, incount; MYFLT *in = Stream_getData((Stream *)self->input_stream); incount = self->incount; for (i=0; ibufsize; i++) { if (incount >= 0) { self->inframe[incount] = in[i] * self->window[incount]; if (incount < self->hsize) { self->buffer_streams[i] = self->outframe[incount]; if (incount) self->buffer_streams[i+self->bufsize] = self->outframe[self->size - incount]; else self->buffer_streams[i+self->bufsize] = 0.0; } else if (incount == self->hsize) self->buffer_streams[i] = self->outframe[incount]; else self->buffer_streams[i] = self->buffer_streams[i+self->bufsize] = 0.0; self->buffer_streams[i+self->bufsize*2] = (MYFLT)incount; } incount++; if (incount >= self->size) { incount -= self->size; realfft_split(self->inframe, self->outframe, self->size, self->twiddle); } } /* for (i=0; ibufsize; i++) { if (incount >= 0) { self->inframe[incount] = in[i] * self->window[incount]; if (incount < self->hsize) { self->buffer_streams[i] = self->outframe[incount*2]; self->buffer_streams[i+self->bufsize] = self->outframe[incount*2+1]; } else self->buffer_streams[i] = self->buffer_streams[i+self->bufsize] = 0.0; self->buffer_streams[i+self->bufsize*2] = (MYFLT)incount; } incount++; if (incount >= self->size) { incount -= self->size; realfft_packed(self->inframe, self->outframe, self->size, self->twiddle2); } } */ self->incount = incount; } MYFLT * FFTMain_getSamplesBuffer(FFTMain *self) { return (MYFLT *)self->buffer_streams; } static void FFTMain_setProcMode(FFTMain *self) { self->proc_func_ptr = FFTMain_filters; } static void FFTMain_compute_next_data_frame(FFTMain *self) { (*self->proc_func_ptr)(self); } static int FFTMain_traverse(FFTMain *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int FFTMain_clear(FFTMain *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void FFTMain_dealloc(FFTMain* self) { int i; pyo_DEALLOC free(self->inframe); free(self->outframe); free(self->window); free(self->buffer_streams); for(i=0; i<4; i++) { free(self->twiddle[i]); } free(self->twiddle); free(self->twiddle2); FFTMain_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * FFTMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp; FFTMain *self; self = (FFTMain *)type->tp_alloc(type, 0); self->size = 1024; self->wintype = 2; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, FFTMain_compute_next_data_frame); self->mode_func_ptr = FFTMain_setProcMode; static char *kwlist[] = {"input", "size", "hopsize", "wintype", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iii", kwlist, &inputtmp, &self->size, &self->hopsize, &self->wintype)) Py_RETURN_NONE; INIT_INPUT_STREAM PyObject_CallMethod(self->server, "addStream", "O", self->stream); FFTMain_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * FFTMain_getServer(FFTMain* self) { GET_SERVER }; static PyObject * FFTMain_getStream(FFTMain* self) { GET_STREAM }; static PyObject * FFTMain_play(FFTMain *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * FFTMain_stop(FFTMain *self) { STOP }; static PyObject * FFTMain_setSize(FFTMain *self, PyObject *args, PyObject *kwds) { int size, hopsize; static char *kwlist[] = {"size", "hopsize", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, &size, &hopsize)) { Py_INCREF(Py_None); return Py_None; } if (isPowerOfTwo(size)) { self->size = size; self->hopsize = hopsize; FFTMain_realloc_memories(self); } else printf("FFT size must be a power of two!\n"); Py_INCREF(Py_None); return Py_None; } static PyObject * FFTMain_setWinType(FFTMain *self, PyObject *arg) { if (PyLong_Check(arg) || PyInt_Check(arg)) { self->wintype = PyLong_AsLong(arg); gen_window(self->window, self->size, self->wintype); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef FFTMain_members[] = { {"server", T_OBJECT_EX, offsetof(FFTMain, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(FFTMain, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(FFTMain, input), 0, "FFT sound object."}, {NULL} /* Sentinel */ }; static PyMethodDef FFTMain_methods[] = { {"getServer", (PyCFunction)FFTMain_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)FFTMain_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)FFTMain_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)FFTMain_stop, METH_NOARGS, "Stops computing."}, {"setSize", (PyCFunction)FFTMain_setSize, METH_VARARGS|METH_KEYWORDS, "Sets a new FFT size."}, {"setWinType", (PyCFunction)FFTMain_setWinType, METH_O, "Sets a new window."}, {NULL} /* Sentinel */ }; PyTypeObject FFTMainType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.FFTMain_base", /*tp_name*/ sizeof(FFTMain), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)FFTMain_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "FFTMain objects. FFT transform.", /* tp_doc */ (traverseproc)FFTMain_traverse, /* tp_traverse */ (inquiry)FFTMain_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ FFTMain_methods, /* tp_methods */ FFTMain_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ FFTMain_new, /* tp_new */ }; /************************************************************************************************/ /* FFT streamer object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD FFTMain *mainSplitter; int modebuffer[2]; int chnl; // 0 = real, 1 = imag, 2 = bin } FFT; static void FFT_postprocessing_ii(FFT *self) { POST_PROCESSING_II }; static void FFT_postprocessing_ai(FFT *self) { POST_PROCESSING_AI }; static void FFT_postprocessing_ia(FFT *self) { POST_PROCESSING_IA }; static void FFT_postprocessing_aa(FFT *self) { POST_PROCESSING_AA }; static void FFT_postprocessing_ireva(FFT *self) { POST_PROCESSING_IREVA }; static void FFT_postprocessing_areva(FFT *self) { POST_PROCESSING_AREVA }; static void FFT_postprocessing_revai(FFT *self) { POST_PROCESSING_REVAI }; static void FFT_postprocessing_revaa(FFT *self) { POST_PROCESSING_REVAA }; static void FFT_postprocessing_revareva(FFT *self) { POST_PROCESSING_REVAREVA }; static void FFT_setProcMode(FFT *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = FFT_postprocessing_ii; break; case 1: self->muladd_func_ptr = FFT_postprocessing_ai; break; case 2: self->muladd_func_ptr = FFT_postprocessing_revai; break; case 10: self->muladd_func_ptr = FFT_postprocessing_ia; break; case 11: self->muladd_func_ptr = FFT_postprocessing_aa; break; case 12: self->muladd_func_ptr = FFT_postprocessing_revaa; break; case 20: self->muladd_func_ptr = FFT_postprocessing_ireva; break; case 21: self->muladd_func_ptr = FFT_postprocessing_areva; break; case 22: self->muladd_func_ptr = FFT_postprocessing_revareva; break; } } static void FFT_compute_next_data_frame(FFT *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = FFTMain_getSamplesBuffer((FFTMain *)self->mainSplitter); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int FFT_traverse(FFT *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainSplitter); return 0; } static int FFT_clear(FFT *self) { pyo_CLEAR Py_CLEAR(self->mainSplitter); return 0; } static void FFT_dealloc(FFT* self) { pyo_DEALLOC FFT_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * FFT_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; FFT *self; self = (FFT *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, FFT_compute_next_data_frame); self->mode_func_ptr = FFT_setProcMode; static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainSplitter); Py_INCREF(maintmp); self->mainSplitter = (FFTMain *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * FFT_getServer(FFT* self) { GET_SERVER }; static PyObject * FFT_getStream(FFT* self) { GET_STREAM }; static PyObject * FFT_setMul(FFT *self, PyObject *arg) { SET_MUL }; static PyObject * FFT_setAdd(FFT *self, PyObject *arg) { SET_ADD }; static PyObject * FFT_setSub(FFT *self, PyObject *arg) { SET_SUB }; static PyObject * FFT_setDiv(FFT *self, PyObject *arg) { SET_DIV }; static PyObject * FFT_play(FFT *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * FFT_stop(FFT *self) { STOP }; static PyObject * FFT_multiply(FFT *self, PyObject *arg) { MULTIPLY }; static PyObject * FFT_inplace_multiply(FFT *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * FFT_add(FFT *self, PyObject *arg) { ADD }; static PyObject * FFT_inplace_add(FFT *self, PyObject *arg) { INPLACE_ADD }; static PyObject * FFT_sub(FFT *self, PyObject *arg) { SUB }; static PyObject * FFT_inplace_sub(FFT *self, PyObject *arg) { INPLACE_SUB }; static PyObject * FFT_div(FFT *self, PyObject *arg) { DIV }; static PyObject * FFT_inplace_div(FFT *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef FFT_members[] = { {"server", T_OBJECT_EX, offsetof(FFT, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(FFT, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(FFT, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(FFT, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef FFT_methods[] = { {"getServer", (PyCFunction)FFT_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)FFT_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)FFT_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)FFT_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)FFT_setMul, METH_O, "Sets FFT mul factor."}, {"setAdd", (PyCFunction)FFT_setAdd, METH_O, "Sets FFT add factor."}, {"setSub", (PyCFunction)FFT_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)FFT_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods FFT_as_number = { (binaryfunc)FFT_add, /*nb_add*/ (binaryfunc)FFT_sub, /*nb_subtract*/ (binaryfunc)FFT_multiply, /*nb_multiply*/ (binaryfunc)FFT_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)FFT_inplace_add, /*inplace_add*/ (binaryfunc)FFT_inplace_sub, /*inplace_subtract*/ (binaryfunc)FFT_inplace_multiply, /*inplace_multiply*/ (binaryfunc)FFT_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject FFTType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.FFT_base", /*tp_name*/ sizeof(FFT), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)FFT_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &FFT_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "FFT objects. Reads one band (real, imag or bins) from a FFT transform.", /* tp_doc */ (traverseproc)FFT_traverse, /* tp_traverse */ (inquiry)FFT_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ FFT_methods, /* tp_methods */ FFT_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ FFT_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *inreal; Stream *inreal_stream; PyObject *inimag; Stream *inimag_stream; int size; int hsize; int hopsize; int wintype; int incount; MYFLT *inframe; MYFLT *outframe; MYFLT *window; MYFLT **twiddle; MYFLT *twiddle2; int modebuffer[2]; } IFFT; static void IFFT_realloc_memories(IFFT *self) { int i, n8; self->hsize = self->size / 2; n8 = self->size >> 3; self->inframe = (MYFLT *)realloc(self->inframe, self->size * sizeof(MYFLT)); self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT)); for (i=0; isize; i++) self->inframe[i] = self->outframe[i] = 0.0; self->twiddle = (MYFLT **)realloc(self->twiddle, 4 * sizeof(MYFLT *)); for(i=0; i<4; i++) self->twiddle[i] = (MYFLT *)malloc(n8 * sizeof(MYFLT)); fft_compute_split_twiddle(self->twiddle, self->size); self->twiddle2 = (MYFLT *)realloc(self->twiddle2, self->size * sizeof(MYFLT)); fft_compute_radix2_twiddle(self->twiddle2, self->size); self->window = (MYFLT *)realloc(self->window, self->size * sizeof(MYFLT)); gen_window(self->window, self->size, self->wintype); self->incount = -self->hopsize; } static void IFFT_filters(IFFT *self) { int i, incount; MYFLT data; MYFLT *inreal = Stream_getData((Stream *)self->inreal_stream); MYFLT *inimag = Stream_getData((Stream *)self->inimag_stream); incount = self->incount; for (i=0; ibufsize; i++) { if (incount >= 0) { if (incount < self->hsize) { self->inframe[incount] = inreal[i]; if (incount) self->inframe[self->size - incount] = inimag[i]; } else if (incount == self->hsize) self->inframe[incount] = inreal[i]; data = self->outframe[incount] * self->window[incount]; self->data[i] = data; } incount++; if (incount >= self->size) { incount -= self->size; irealfft_split(self->inframe, self->outframe, self->size, self->twiddle); } } /* for (i=0; ibufsize; i++) { if (incount >= 0) { if (incount < self->hsize) { self->inframe[incount*2] = inreal[i]; self->inframe[incount*2+1] = inimag[i]; } self->data[i] = self->outframe[incount] * self->window[incount]; } incount++; if (incount >= self->size) { incount -= self->size; irealfft_packed(self->inframe, self->outframe, self->size, self->twiddle2); } } */ self->incount = incount; } static void IFFT_postprocessing_ii(IFFT *self) { POST_PROCESSING_II }; static void IFFT_postprocessing_ai(IFFT *self) { POST_PROCESSING_AI }; static void IFFT_postprocessing_ia(IFFT *self) { POST_PROCESSING_IA }; static void IFFT_postprocessing_aa(IFFT *self) { POST_PROCESSING_AA }; static void IFFT_postprocessing_ireva(IFFT *self) { POST_PROCESSING_IREVA }; static void IFFT_postprocessing_areva(IFFT *self) { POST_PROCESSING_AREVA }; static void IFFT_postprocessing_revai(IFFT *self) { POST_PROCESSING_REVAI }; static void IFFT_postprocessing_revaa(IFFT *self) { POST_PROCESSING_REVAA }; static void IFFT_postprocessing_revareva(IFFT *self) { POST_PROCESSING_REVAREVA }; static void IFFT_setProcMode(IFFT *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = IFFT_filters; switch (muladdmode) { case 0: self->muladd_func_ptr = IFFT_postprocessing_ii; break; case 1: self->muladd_func_ptr = IFFT_postprocessing_ai; break; case 2: self->muladd_func_ptr = IFFT_postprocessing_revai; break; case 10: self->muladd_func_ptr = IFFT_postprocessing_ia; break; case 11: self->muladd_func_ptr = IFFT_postprocessing_aa; break; case 12: self->muladd_func_ptr = IFFT_postprocessing_revaa; break; case 20: self->muladd_func_ptr = IFFT_postprocessing_ireva; break; case 21: self->muladd_func_ptr = IFFT_postprocessing_areva; break; case 22: self->muladd_func_ptr = IFFT_postprocessing_revareva; break; } } static void IFFT_compute_next_data_frame(IFFT *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int IFFT_traverse(IFFT *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->inreal); Py_VISIT(self->inreal_stream); Py_VISIT(self->inimag); Py_VISIT(self->inimag_stream); return 0; } static int IFFT_clear(IFFT *self) { pyo_CLEAR Py_CLEAR(self->inreal); Py_CLEAR(self->inreal_stream); Py_CLEAR(self->inimag); Py_CLEAR(self->inimag_stream); return 0; } static void IFFT_dealloc(IFFT* self) { int i; pyo_DEALLOC free(self->inframe); free(self->outframe); free(self->window); for(i=0; i<4; i++) { free(self->twiddle[i]); } free(self->twiddle); free(self->twiddle2); IFFT_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * IFFT_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inrealtmp, *inreal_streamtmp, *inimagtmp, *inimag_streamtmp, *multmp=NULL, *addtmp=NULL; IFFT *self; self = (IFFT *)type->tp_alloc(type, 0); self->size = 1024; self->wintype = 2; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, IFFT_compute_next_data_frame); self->mode_func_ptr = IFFT_setProcMode; static char *kwlist[] = {"inreal", "inimag", "size", "hopsize", "wintype", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|iiiOO", kwlist, &inrealtmp, &inimagtmp, &self->size, &self->hopsize, &self->wintype, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->inimag); self->inimag = inimagtmp; inimag_streamtmp = PyObject_CallMethod((PyObject *)self->inimag, "_getStream", NULL); Py_INCREF(inimag_streamtmp); Py_XDECREF(self->inimag_stream); self->inimag_stream = (Stream *)inimag_streamtmp; Py_XDECREF(self->inreal); self->inreal = inrealtmp; inreal_streamtmp = PyObject_CallMethod((PyObject *)self->inreal, "_getStream", NULL); Py_INCREF(inreal_streamtmp); Py_XDECREF(self->inreal_stream); self->inreal_stream = (Stream *)inreal_streamtmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); IFFT_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * IFFT_getServer(IFFT* self) { GET_SERVER }; static PyObject * IFFT_getStream(IFFT* self) { GET_STREAM }; static PyObject * IFFT_setMul(IFFT *self, PyObject *arg) { SET_MUL }; static PyObject * IFFT_setAdd(IFFT *self, PyObject *arg) { SET_ADD }; static PyObject * IFFT_setSub(IFFT *self, PyObject *arg) { SET_SUB }; static PyObject * IFFT_setDiv(IFFT *self, PyObject *arg) { SET_DIV }; static PyObject * IFFT_play(IFFT *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * IFFT_out(IFFT *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * IFFT_stop(IFFT *self) { STOP }; static PyObject * IFFT_multiply(IFFT *self, PyObject *arg) { MULTIPLY }; static PyObject * IFFT_inplace_multiply(IFFT *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * IFFT_add(IFFT *self, PyObject *arg) { ADD }; static PyObject * IFFT_inplace_add(IFFT *self, PyObject *arg) { INPLACE_ADD }; static PyObject * IFFT_sub(IFFT *self, PyObject *arg) { SUB }; static PyObject * IFFT_inplace_sub(IFFT *self, PyObject *arg) { INPLACE_SUB }; static PyObject * IFFT_div(IFFT *self, PyObject *arg) { DIV }; static PyObject * IFFT_inplace_div(IFFT *self, PyObject *arg) { INPLACE_DIV }; static PyObject * IFFT_setSize(IFFT *self, PyObject *args, PyObject *kwds) { int size, hopsize; static char *kwlist[] = {"size", "hopsize", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, &size, &hopsize)) { Py_INCREF(Py_None); return Py_None; } if (isPowerOfTwo(size)) { self->size = size; self->hopsize = hopsize; IFFT_realloc_memories(self); } else printf("IFFT size must be a power of two!\n"); Py_INCREF(Py_None); return Py_None; } static PyObject * IFFT_setWinType(IFFT *self, PyObject *arg) { if (PyLong_Check(arg) || PyInt_Check(arg)) { self->wintype = PyLong_AsLong(arg); gen_window(self->window, self->size, self->wintype); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef IFFT_members[] = { {"server", T_OBJECT_EX, offsetof(IFFT, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(IFFT, stream), 0, "Stream object."}, {"inreal", T_OBJECT_EX, offsetof(IFFT, inreal), 0, "Real input."}, {"inimag", T_OBJECT_EX, offsetof(IFFT, inimag), 0, "Imaginary input."}, {"mul", T_OBJECT_EX, offsetof(IFFT, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(IFFT, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef IFFT_methods[] = { {"getServer", (PyCFunction)IFFT_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)IFFT_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)IFFT_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)IFFT_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)IFFT_stop, METH_NOARGS, "Stops computing."}, {"setSize", (PyCFunction)IFFT_setSize, METH_VARARGS|METH_KEYWORDS, "Sets a new IFFT size."}, {"setWinType", (PyCFunction)IFFT_setWinType, METH_O, "Sets a new window."}, {"setMul", (PyCFunction)IFFT_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)IFFT_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)IFFT_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)IFFT_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods IFFT_as_number = { (binaryfunc)IFFT_add, /*nb_add*/ (binaryfunc)IFFT_sub, /*nb_subtract*/ (binaryfunc)IFFT_multiply, /*nb_multiply*/ (binaryfunc)IFFT_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)IFFT_inplace_add, /*inplace_add*/ (binaryfunc)IFFT_inplace_sub, /*inplace_subtract*/ (binaryfunc)IFFT_inplace_multiply, /*inplace_multiply*/ (binaryfunc)IFFT_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject IFFTType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.IFFT_base", /*tp_name*/ sizeof(IFFT), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)IFFT_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &IFFT_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "IFFT objects. Synthesize audio from an FFT real and imaginary parts.", /* tp_doc */ (traverseproc)IFFT_traverse, /* tp_traverse */ (inquiry)IFFT_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ IFFT_methods, /* tp_methods */ IFFT_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ IFFT_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; /* real input */ Stream *input_stream; PyObject *input2; /* imag input */ Stream *input2_stream; int modebuffer[2]; int chnl; // 0 = mag, 1 = ang } CarToPol; static void CarToPol_generate(CarToPol *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); if (self->chnl == 0) { for (i=0; ibufsize; i++) { self->data[i] = MYSQRT(in[i]*in[i] + in2[i]*in2[i]); } } else { for (i=0; ibufsize; i++) { self->data[i] = MYATAN2(in2[i], in[i]); } } } static void CarToPol_postprocessing_ii(CarToPol *self) { POST_PROCESSING_II }; static void CarToPol_postprocessing_ai(CarToPol *self) { POST_PROCESSING_AI }; static void CarToPol_postprocessing_ia(CarToPol *self) { POST_PROCESSING_IA }; static void CarToPol_postprocessing_aa(CarToPol *self) { POST_PROCESSING_AA }; static void CarToPol_postprocessing_ireva(CarToPol *self) { POST_PROCESSING_IREVA }; static void CarToPol_postprocessing_areva(CarToPol *self) { POST_PROCESSING_AREVA }; static void CarToPol_postprocessing_revai(CarToPol *self) { POST_PROCESSING_REVAI }; static void CarToPol_postprocessing_revaa(CarToPol *self) { POST_PROCESSING_REVAA }; static void CarToPol_postprocessing_revareva(CarToPol *self) { POST_PROCESSING_REVAREVA }; static void CarToPol_setProcMode(CarToPol *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = CarToPol_generate; switch (muladdmode) { case 0: self->muladd_func_ptr = CarToPol_postprocessing_ii; break; case 1: self->muladd_func_ptr = CarToPol_postprocessing_ai; break; case 2: self->muladd_func_ptr = CarToPol_postprocessing_revai; break; case 10: self->muladd_func_ptr = CarToPol_postprocessing_ia; break; case 11: self->muladd_func_ptr = CarToPol_postprocessing_aa; break; case 12: self->muladd_func_ptr = CarToPol_postprocessing_revaa; break; case 20: self->muladd_func_ptr = CarToPol_postprocessing_ireva; break; case 21: self->muladd_func_ptr = CarToPol_postprocessing_areva; break; case 22: self->muladd_func_ptr = CarToPol_postprocessing_revareva; break; } } static void CarToPol_compute_next_data_frame(CarToPol *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int CarToPol_traverse(CarToPol *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->input2); Py_VISIT(self->input2_stream); return 0; } static int CarToPol_clear(CarToPol *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->input2); Py_CLEAR(self->input2_stream); return 0; } static void CarToPol_dealloc(CarToPol* self) { pyo_DEALLOC CarToPol_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * CarToPol_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *multmp=NULL, *addtmp=NULL; CarToPol *self; self = (CarToPol *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, CarToPol_compute_next_data_frame); self->mode_func_ptr = CarToPol_setProcMode; static char *kwlist[] = {"input", "input2", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOi|OO", kwlist, &inputtmp, &input2tmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_XDECREF(self->input2); self->input2 = input2tmp; input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL); Py_INCREF(input2_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (Stream *)input2_streamtmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * CarToPol_getServer(CarToPol* self) { GET_SERVER }; static PyObject * CarToPol_getStream(CarToPol* self) { GET_STREAM }; static PyObject * CarToPol_setMul(CarToPol *self, PyObject *arg) { SET_MUL }; static PyObject * CarToPol_setAdd(CarToPol *self, PyObject *arg) { SET_ADD }; static PyObject * CarToPol_setSub(CarToPol *self, PyObject *arg) { SET_SUB }; static PyObject * CarToPol_setDiv(CarToPol *self, PyObject *arg) { SET_DIV }; static PyObject * CarToPol_play(CarToPol *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * CarToPol_stop(CarToPol *self) { STOP }; static PyObject * CarToPol_multiply(CarToPol *self, PyObject *arg) { MULTIPLY }; static PyObject * CarToPol_inplace_multiply(CarToPol *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * CarToPol_add(CarToPol *self, PyObject *arg) { ADD }; static PyObject * CarToPol_inplace_add(CarToPol *self, PyObject *arg) { INPLACE_ADD }; static PyObject * CarToPol_sub(CarToPol *self, PyObject *arg) { SUB }; static PyObject * CarToPol_inplace_sub(CarToPol *self, PyObject *arg) { INPLACE_SUB }; static PyObject * CarToPol_div(CarToPol *self, PyObject *arg) { DIV }; static PyObject * CarToPol_inplace_div(CarToPol *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef CarToPol_members[] = { {"server", T_OBJECT_EX, offsetof(CarToPol, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(CarToPol, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(CarToPol, input), 0, "Real sound object."}, {"input2", T_OBJECT_EX, offsetof(CarToPol, input2), 0, "Imaginary sound object."}, {"mul", T_OBJECT_EX, offsetof(CarToPol, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(CarToPol, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef CarToPol_methods[] = { {"getServer", (PyCFunction)CarToPol_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)CarToPol_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)CarToPol_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)CarToPol_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)CarToPol_setMul, METH_O, "Sets CarToPol mul factor."}, {"setAdd", (PyCFunction)CarToPol_setAdd, METH_O, "Sets CarToPol add factor."}, {"setSub", (PyCFunction)CarToPol_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)CarToPol_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods CarToPol_as_number = { (binaryfunc)CarToPol_add, /*nb_add*/ (binaryfunc)CarToPol_sub, /*nb_subtract*/ (binaryfunc)CarToPol_multiply, /*nb_multiply*/ (binaryfunc)CarToPol_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)CarToPol_inplace_add, /*inplace_add*/ (binaryfunc)CarToPol_inplace_sub, /*inplace_subtract*/ (binaryfunc)CarToPol_inplace_multiply, /*inplace_multiply*/ (binaryfunc)CarToPol_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject CarToPolType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.CarToPol_base", /*tp_name*/ sizeof(CarToPol), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)CarToPol_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &CarToPol_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "CarToPol objects. Cartesian to polar transform.", /* tp_doc */ (traverseproc)CarToPol_traverse, /* tp_traverse */ (inquiry)CarToPol_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ CarToPol_methods, /* tp_methods */ CarToPol_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ CarToPol_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; /* mag input */ Stream *input_stream; PyObject *input2; /* ang input */ Stream *input2_stream; int modebuffer[2]; int chnl; // 0 = real, 1 = imag } PolToCar; static void PolToCar_generate(PolToCar *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); if (self->chnl == 0) { for (i=0; ibufsize; i++) { self->data[i] = in[i] * MYCOS(in2[i]); } } else { for (i=0; ibufsize; i++) { self->data[i] = in[i] * MYSIN(in2[i]); } } } static void PolToCar_postprocessing_ii(PolToCar *self) { POST_PROCESSING_II }; static void PolToCar_postprocessing_ai(PolToCar *self) { POST_PROCESSING_AI }; static void PolToCar_postprocessing_ia(PolToCar *self) { POST_PROCESSING_IA }; static void PolToCar_postprocessing_aa(PolToCar *self) { POST_PROCESSING_AA }; static void PolToCar_postprocessing_ireva(PolToCar *self) { POST_PROCESSING_IREVA }; static void PolToCar_postprocessing_areva(PolToCar *self) { POST_PROCESSING_AREVA }; static void PolToCar_postprocessing_revai(PolToCar *self) { POST_PROCESSING_REVAI }; static void PolToCar_postprocessing_revaa(PolToCar *self) { POST_PROCESSING_REVAA }; static void PolToCar_postprocessing_revareva(PolToCar *self) { POST_PROCESSING_REVAREVA }; static void PolToCar_setProcMode(PolToCar *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = PolToCar_generate; switch (muladdmode) { case 0: self->muladd_func_ptr = PolToCar_postprocessing_ii; break; case 1: self->muladd_func_ptr = PolToCar_postprocessing_ai; break; case 2: self->muladd_func_ptr = PolToCar_postprocessing_revai; break; case 10: self->muladd_func_ptr = PolToCar_postprocessing_ia; break; case 11: self->muladd_func_ptr = PolToCar_postprocessing_aa; break; case 12: self->muladd_func_ptr = PolToCar_postprocessing_revaa; break; case 20: self->muladd_func_ptr = PolToCar_postprocessing_ireva; break; case 21: self->muladd_func_ptr = PolToCar_postprocessing_areva; break; case 22: self->muladd_func_ptr = PolToCar_postprocessing_revareva; break; } } static void PolToCar_compute_next_data_frame(PolToCar *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int PolToCar_traverse(PolToCar *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->input2); Py_VISIT(self->input2_stream); return 0; } static int PolToCar_clear(PolToCar *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->input2); Py_CLEAR(self->input2_stream); return 0; } static void PolToCar_dealloc(PolToCar* self) { pyo_DEALLOC PolToCar_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PolToCar_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *multmp=NULL, *addtmp=NULL; PolToCar *self; self = (PolToCar *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PolToCar_compute_next_data_frame); self->mode_func_ptr = PolToCar_setProcMode; static char *kwlist[] = {"input", "input2", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOi|OO", kwlist, &inputtmp, &input2tmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_XDECREF(self->input2); self->input2 = input2tmp; input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL); Py_INCREF(input2_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (Stream *)input2_streamtmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PolToCar_getServer(PolToCar* self) { GET_SERVER }; static PyObject * PolToCar_getStream(PolToCar* self) { GET_STREAM }; static PyObject * PolToCar_setMul(PolToCar *self, PyObject *arg) { SET_MUL }; static PyObject * PolToCar_setAdd(PolToCar *self, PyObject *arg) { SET_ADD }; static PyObject * PolToCar_setSub(PolToCar *self, PyObject *arg) { SET_SUB }; static PyObject * PolToCar_setDiv(PolToCar *self, PyObject *arg) { SET_DIV }; static PyObject * PolToCar_play(PolToCar *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PolToCar_stop(PolToCar *self) { STOP }; static PyObject * PolToCar_multiply(PolToCar *self, PyObject *arg) { MULTIPLY }; static PyObject * PolToCar_inplace_multiply(PolToCar *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * PolToCar_add(PolToCar *self, PyObject *arg) { ADD }; static PyObject * PolToCar_inplace_add(PolToCar *self, PyObject *arg) { INPLACE_ADD }; static PyObject * PolToCar_sub(PolToCar *self, PyObject *arg) { SUB }; static PyObject * PolToCar_inplace_sub(PolToCar *self, PyObject *arg) { INPLACE_SUB }; static PyObject * PolToCar_div(PolToCar *self, PyObject *arg) { DIV }; static PyObject * PolToCar_inplace_div(PolToCar *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef PolToCar_members[] = { {"server", T_OBJECT_EX, offsetof(PolToCar, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PolToCar, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(PolToCar, input), 0, "Magnitude sound object."}, {"input2", T_OBJECT_EX, offsetof(PolToCar, input2), 0, "Angle sound object."}, {"mul", T_OBJECT_EX, offsetof(PolToCar, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(PolToCar, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef PolToCar_methods[] = { {"getServer", (PyCFunction)PolToCar_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PolToCar_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)PolToCar_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PolToCar_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)PolToCar_setMul, METH_O, "Sets PolToCar mul factor."}, {"setAdd", (PyCFunction)PolToCar_setAdd, METH_O, "Sets PolToCar add factor."}, {"setSub", (PyCFunction)PolToCar_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)PolToCar_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods PolToCar_as_number = { (binaryfunc)PolToCar_add, /*nb_add*/ (binaryfunc)PolToCar_sub, /*nb_subtract*/ (binaryfunc)PolToCar_multiply, /*nb_multiply*/ (binaryfunc)PolToCar_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)PolToCar_inplace_add, /*inplace_add*/ (binaryfunc)PolToCar_inplace_sub, /*inplace_subtract*/ (binaryfunc)PolToCar_inplace_multiply, /*inplace_multiply*/ (binaryfunc)PolToCar_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject PolToCarType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PolToCar_base", /*tp_name*/ sizeof(PolToCar), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PolToCar_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &PolToCar_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PolToCar objects. Polar to cartesian transform.", /* tp_doc */ (traverseproc)PolToCar_traverse, /* tp_traverse */ (inquiry)PolToCar_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PolToCar_methods, /* tp_methods */ PolToCar_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PolToCar_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; int inputSize; int modebuffer[2]; int frameSize; int overlaps; int hopsize; int count; MYFLT **frameBuffer; MYFLT *buffer_streams; } FrameDeltaMain; static void FrameDeltaMain_generate(FrameDeltaMain *self) { int i, j, which, where; MYFLT curPhase, lastPhase, diff; MYFLT ins[self->overlaps][self->bufsize]; for (j=0; joverlaps; j++) { MYFLT *in = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->input, j), "_getStream", NULL)); for (i=0; ibufsize; i++) { ins[j][i] = in[i]; } } for (i=0; ibufsize; i++) { for (j=0; joverlaps; j++) { curPhase = ins[j][i]; which = j - 1; if (which < 0) which = self->overlaps - 1; where = self->count - self->hopsize; if (where < 0) where += self->frameSize; lastPhase = self->frameBuffer[which][where]; diff = curPhase - lastPhase; while (diff < -PI) { diff += TWOPI; } while (diff > PI) { diff -= TWOPI; } self->frameBuffer[j][self->count] = curPhase; self->buffer_streams[i+j*self->bufsize] = diff; } self->count++; if (self->count >= self->frameSize) self->count = 0; } } MYFLT * FrameDeltaMain_getSamplesBuffer(FrameDeltaMain *self) { return (MYFLT *)self->buffer_streams; } static void FrameDeltaMain_setProcMode(FrameDeltaMain *self) { self->proc_func_ptr = FrameDeltaMain_generate; } static void FrameDeltaMain_compute_next_data_frame(FrameDeltaMain *self) { (*self->proc_func_ptr)(self); } static int FrameDeltaMain_traverse(FrameDeltaMain *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); return 0; } static int FrameDeltaMain_clear(FrameDeltaMain *self) { pyo_CLEAR Py_CLEAR(self->input); return 0; } static void FrameDeltaMain_dealloc(FrameDeltaMain* self) { int i; pyo_DEALLOC for (i=0; ioverlaps; i++) { free(self->frameBuffer[i]); } free(self->frameBuffer); free(self->buffer_streams); FrameDeltaMain_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * FrameDeltaMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, j; PyObject *inputtmp; FrameDeltaMain *self; self = (FrameDeltaMain *)type->tp_alloc(type, 0); self->count = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, FrameDeltaMain_compute_next_data_frame); self->mode_func_ptr = FrameDeltaMain_setProcMode; static char *kwlist[] = {"input", "frameSize", "overlaps", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oii", kwlist, &inputtmp, &self->frameSize, &self->overlaps)) Py_RETURN_NONE; if (inputtmp) { PyObject_CallMethod((PyObject *)self, "setInput", "O", inputtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->hopsize = self->frameSize / self->overlaps; self->frameBuffer = (MYFLT **)realloc(self->frameBuffer, self->overlaps * sizeof(MYFLT *)); for(i=0; ioverlaps; i++) { self->frameBuffer[i] = (MYFLT *)malloc(self->frameSize * sizeof(MYFLT)); for (j=0; jframeSize; j++) { self->frameBuffer[i][j] = 0.0; } } self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->overlaps * self->bufsize * sizeof(MYFLT)); for (i=0; i<(self->overlaps*self->bufsize); i++) { self->buffer_streams[i] = 0.0; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * FrameDeltaMain_getServer(FrameDeltaMain* self) { GET_SERVER }; static PyObject * FrameDeltaMain_getStream(FrameDeltaMain* self) { GET_STREAM }; static PyObject * FrameDeltaMain_play(FrameDeltaMain *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * FrameDeltaMain_stop(FrameDeltaMain *self) { STOP }; static PyObject * FrameDeltaMain_setInput(FrameDeltaMain *self, PyObject *arg) { PyObject *tmp; if (! PyList_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The inputs attribute must be a list."); Py_INCREF(Py_None); return Py_None; } tmp = arg; self->inputSize = PyList_Size(tmp); Py_INCREF(tmp); Py_XDECREF(self->input); self->input = tmp; Py_INCREF(Py_None); return Py_None; } static PyObject * FrameDeltaMain_setFrameSize(FrameDeltaMain *self, PyObject *arg) { int i, j, tmp; if (PyInt_Check(arg)) { tmp = PyLong_AsLong(arg); if (isPowerOfTwo(tmp)) { self->frameSize = tmp; self->hopsize = self->frameSize / self->overlaps; self->frameBuffer = (MYFLT **)realloc(self->frameBuffer, self->overlaps * sizeof(MYFLT *)); for(i=0; ioverlaps; i++) { self->frameBuffer[i] = (MYFLT *)malloc(self->frameSize * sizeof(MYFLT)); for (j=0; jframeSize; j++) { self->frameBuffer[i][j] = 0.0; } } self->count = 0; } } else printf("frameSize must be a power of two!\n"); Py_INCREF(Py_None); return Py_None; } static PyMemberDef FrameDeltaMain_members[] = { {"server", T_OBJECT_EX, offsetof(FrameDeltaMain, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(FrameDeltaMain, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(FrameDeltaMain, input), 0, "Phase input object."}, {NULL} /* Sentinel */ }; static PyMethodDef FrameDeltaMain_methods[] = { {"getServer", (PyCFunction)FrameDeltaMain_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)FrameDeltaMain_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)FrameDeltaMain_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)FrameDeltaMain_stop, METH_NOARGS, "Stops computing."}, {"setInput", (PyCFunction)FrameDeltaMain_setInput, METH_O, "Sets list of input streams."}, {"setFrameSize", (PyCFunction)FrameDeltaMain_setFrameSize, METH_O, "Sets frame size."}, {NULL} /* Sentinel */ }; PyTypeObject FrameDeltaMainType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.FrameDeltaMain_base", /*tp_name*/ sizeof(FrameDeltaMain), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)FrameDeltaMain_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "FrameDeltaMain objects. Compute the phase difference between successive frames.", /* tp_doc */ (traverseproc)FrameDeltaMain_traverse, /* tp_traverse */ (inquiry)FrameDeltaMain_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ FrameDeltaMain_methods, /* tp_methods */ FrameDeltaMain_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ FrameDeltaMain_new, /* tp_new */ }; /************************************************************************************************/ /* FrameDelta streamer object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD FrameDeltaMain *mainSplitter; int modebuffer[2]; int chnl; // panning order } FrameDelta; static void FrameDelta_postprocessing_ii(FrameDelta *self) { POST_PROCESSING_II }; static void FrameDelta_postprocessing_ai(FrameDelta *self) { POST_PROCESSING_AI }; static void FrameDelta_postprocessing_ia(FrameDelta *self) { POST_PROCESSING_IA }; static void FrameDelta_postprocessing_aa(FrameDelta *self) { POST_PROCESSING_AA }; static void FrameDelta_postprocessing_ireva(FrameDelta *self) { POST_PROCESSING_IREVA }; static void FrameDelta_postprocessing_areva(FrameDelta *self) { POST_PROCESSING_AREVA }; static void FrameDelta_postprocessing_revai(FrameDelta *self) { POST_PROCESSING_REVAI }; static void FrameDelta_postprocessing_revaa(FrameDelta *self) { POST_PROCESSING_REVAA }; static void FrameDelta_postprocessing_revareva(FrameDelta *self) { POST_PROCESSING_REVAREVA }; static void FrameDelta_setProcMode(FrameDelta *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = FrameDelta_postprocessing_ii; break; case 1: self->muladd_func_ptr = FrameDelta_postprocessing_ai; break; case 2: self->muladd_func_ptr = FrameDelta_postprocessing_revai; break; case 10: self->muladd_func_ptr = FrameDelta_postprocessing_ia; break; case 11: self->muladd_func_ptr = FrameDelta_postprocessing_aa; break; case 12: self->muladd_func_ptr = FrameDelta_postprocessing_revaa; break; case 20: self->muladd_func_ptr = FrameDelta_postprocessing_ireva; break; case 21: self->muladd_func_ptr = FrameDelta_postprocessing_areva; break; case 22: self->muladd_func_ptr = FrameDelta_postprocessing_revareva; break; } } static void FrameDelta_compute_next_data_frame(FrameDelta *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = FrameDeltaMain_getSamplesBuffer((FrameDeltaMain *)self->mainSplitter); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int FrameDelta_traverse(FrameDelta *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainSplitter); return 0; } static int FrameDelta_clear(FrameDelta *self) { pyo_CLEAR Py_CLEAR(self->mainSplitter); return 0; } static void FrameDelta_dealloc(FrameDelta* self) { pyo_DEALLOC FrameDelta_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * FrameDelta_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; FrameDelta *self; self = (FrameDelta *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, FrameDelta_compute_next_data_frame); self->mode_func_ptr = FrameDelta_setProcMode; static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainSplitter); Py_INCREF(maintmp); self->mainSplitter = (FrameDeltaMain *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * FrameDelta_getServer(FrameDelta* self) { GET_SERVER }; static PyObject * FrameDelta_getStream(FrameDelta* self) { GET_STREAM }; static PyObject * FrameDelta_setMul(FrameDelta *self, PyObject *arg) { SET_MUL }; static PyObject * FrameDelta_setAdd(FrameDelta *self, PyObject *arg) { SET_ADD }; static PyObject * FrameDelta_setSub(FrameDelta *self, PyObject *arg) { SET_SUB }; static PyObject * FrameDelta_setDiv(FrameDelta *self, PyObject *arg) { SET_DIV }; static PyObject * FrameDelta_play(FrameDelta *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * FrameDelta_out(FrameDelta *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * FrameDelta_stop(FrameDelta *self) { STOP }; static PyObject * FrameDelta_multiply(FrameDelta *self, PyObject *arg) { MULTIPLY }; static PyObject * FrameDelta_inplace_multiply(FrameDelta *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * FrameDelta_add(FrameDelta *self, PyObject *arg) { ADD }; static PyObject * FrameDelta_inplace_add(FrameDelta *self, PyObject *arg) { INPLACE_ADD }; static PyObject * FrameDelta_sub(FrameDelta *self, PyObject *arg) { SUB }; static PyObject * FrameDelta_inplace_sub(FrameDelta *self, PyObject *arg) { INPLACE_SUB }; static PyObject * FrameDelta_div(FrameDelta *self, PyObject *arg) { DIV }; static PyObject * FrameDelta_inplace_div(FrameDelta *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef FrameDelta_members[] = { {"server", T_OBJECT_EX, offsetof(FrameDelta, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(FrameDelta, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(FrameDelta, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(FrameDelta, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef FrameDelta_methods[] = { {"getServer", (PyCFunction)FrameDelta_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)FrameDelta_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)FrameDelta_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)FrameDelta_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)FrameDelta_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)FrameDelta_setMul, METH_O, "Sets FrameDelta mul factor."}, {"setAdd", (PyCFunction)FrameDelta_setAdd, METH_O, "Sets FrameDelta add factor."}, {"setSub", (PyCFunction)FrameDelta_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)FrameDelta_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods FrameDelta_as_number = { (binaryfunc)FrameDelta_add, /*nb_add*/ (binaryfunc)FrameDelta_sub, /*nb_subtract*/ (binaryfunc)FrameDelta_multiply, /*nb_multiply*/ (binaryfunc)FrameDelta_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)FrameDelta_inplace_add, /*inplace_add*/ (binaryfunc)FrameDelta_inplace_sub, /*inplace_subtract*/ (binaryfunc)FrameDelta_inplace_multiply, /*inplace_multiply*/ (binaryfunc)FrameDelta_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject FrameDeltaType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.FrameDelta_base", /*tp_name*/ sizeof(FrameDelta), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)FrameDelta_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &FrameDelta_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "FrameDelta objects. Reads one band from a FrameDeltaMain object.", /* tp_doc */ (traverseproc)FrameDelta_traverse, /* tp_traverse */ (inquiry)FrameDelta_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ FrameDelta_methods, /* tp_methods */ FrameDelta_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ FrameDelta_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; int inputSize; int modebuffer[2]; int frameSize; int overlaps; int hopsize; int count; MYFLT **frameBuffer; MYFLT *buffer_streams; } FrameAccumMain; static void FrameAccumMain_generate(FrameAccumMain *self) { int i, j, which, where; MYFLT curPhase, lastPhase, diff; MYFLT ins[self->overlaps][self->bufsize]; for (j=0; joverlaps; j++) { MYFLT *in = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->input, j), "_getStream", NULL)); for (i=0; ibufsize; i++) { ins[j][i] = in[i]; } } for (i=0; ibufsize; i++) { for (j=0; joverlaps; j++) { curPhase = ins[j][i]; which = j - 1; if (which < 0) which = self->overlaps - 1; where = self->count - self->hopsize; if (where < 0) where += self->frameSize; lastPhase = self->frameBuffer[which][where]; diff = curPhase + lastPhase; self->frameBuffer[j][self->count] = diff; self->buffer_streams[i+j*self->bufsize] = diff; } self->count++; if (self->count >= self->frameSize) self->count = 0; } } MYFLT * FrameAccumMain_getSamplesBuffer(FrameAccumMain *self) { return (MYFLT *)self->buffer_streams; } static void FrameAccumMain_setProcMode(FrameAccumMain *self) { self->proc_func_ptr = FrameAccumMain_generate; } static void FrameAccumMain_compute_next_data_frame(FrameAccumMain *self) { (*self->proc_func_ptr)(self); } static int FrameAccumMain_traverse(FrameAccumMain *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); return 0; } static int FrameAccumMain_clear(FrameAccumMain *self) { pyo_CLEAR Py_CLEAR(self->input); return 0; } static void FrameAccumMain_dealloc(FrameAccumMain* self) { int i; pyo_DEALLOC for (i=0; ioverlaps; i++) { free(self->frameBuffer[i]); } free(self->frameBuffer); free(self->buffer_streams); FrameAccumMain_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * FrameAccumMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, j; PyObject *inputtmp; FrameAccumMain *self; self = (FrameAccumMain *)type->tp_alloc(type, 0); self->count = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, FrameAccumMain_compute_next_data_frame); self->mode_func_ptr = FrameAccumMain_setProcMode; static char *kwlist[] = {"input", "framesize", "overlaps", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oii", kwlist, &inputtmp, &self->frameSize, &self->overlaps)) Py_RETURN_NONE; if (inputtmp) { PyObject_CallMethod((PyObject *)self, "setInput", "O", inputtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->hopsize = self->frameSize / self->overlaps; self->frameBuffer = (MYFLT **)realloc(self->frameBuffer, self->overlaps * sizeof(MYFLT *)); for(i=0; ioverlaps; i++) { self->frameBuffer[i] = (MYFLT *)malloc(self->frameSize * sizeof(MYFLT)); for (j=0; jframeSize; j++) { self->frameBuffer[i][j] = 0.0; } } self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->overlaps * self->bufsize * sizeof(MYFLT)); for (i=0; i<(self->overlaps*self->bufsize); i++) { self->buffer_streams[i] = 0.0; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * FrameAccumMain_getServer(FrameAccumMain* self) { GET_SERVER }; static PyObject * FrameAccumMain_getStream(FrameAccumMain* self) { GET_STREAM }; static PyObject * FrameAccumMain_play(FrameAccumMain *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * FrameAccumMain_stop(FrameAccumMain *self) { STOP }; static PyObject * FrameAccumMain_setInput(FrameAccumMain *self, PyObject *arg) { PyObject *tmp; if (! PyList_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The inputs attribute must be a list."); Py_INCREF(Py_None); return Py_None; } tmp = arg; self->inputSize = PyList_Size(tmp); Py_INCREF(tmp); Py_XDECREF(self->input); self->input = tmp; Py_INCREF(Py_None); return Py_None; } static PyObject * FrameAccumMain_setFrameSize(FrameAccumMain *self, PyObject *arg) { int i, j, tmp; if (PyInt_Check(arg)) { tmp = PyLong_AsLong(arg); if (isPowerOfTwo(tmp)) { self->frameSize = tmp; self->hopsize = self->frameSize / self->overlaps; self->frameBuffer = (MYFLT **)realloc(self->frameBuffer, self->overlaps * sizeof(MYFLT *)); for(i=0; ioverlaps; i++) { self->frameBuffer[i] = (MYFLT *)malloc(self->frameSize * sizeof(MYFLT)); for (j=0; jframeSize; j++) { self->frameBuffer[i][j] = 0.0; } } self->count = 0; } } else printf("frameSize must be a power of two!\n"); Py_INCREF(Py_None); return Py_None; } static PyMemberDef FrameAccumMain_members[] = { {"server", T_OBJECT_EX, offsetof(FrameAccumMain, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(FrameAccumMain, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(FrameAccumMain, input), 0, "Phase input object."}, {NULL} /* Sentinel */ }; static PyMethodDef FrameAccumMain_methods[] = { {"getServer", (PyCFunction)FrameAccumMain_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)FrameAccumMain_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)FrameAccumMain_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)FrameAccumMain_stop, METH_NOARGS, "Stops computing."}, {"setInput", (PyCFunction)FrameAccumMain_setInput, METH_O, "Sets list of input streams."}, {"setFrameSize", (PyCFunction)FrameAccumMain_setFrameSize, METH_O, "Sets frame size."}, {NULL} /* Sentinel */ }; PyTypeObject FrameAccumMainType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.FrameAccumMain_base", /*tp_name*/ sizeof(FrameAccumMain), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)FrameAccumMain_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "FrameAccumMain objects. Integrate the phase difference between successive frames.", /* tp_doc */ (traverseproc)FrameAccumMain_traverse, /* tp_traverse */ (inquiry)FrameAccumMain_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ FrameAccumMain_methods, /* tp_methods */ FrameAccumMain_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ FrameAccumMain_new, /* tp_new */ }; /************************************************************************************************/ /* FrameAccum streamer object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD FrameAccumMain *mainSplitter; int modebuffer[2]; int chnl; // panning order } FrameAccum; static void FrameAccum_postprocessing_ii(FrameAccum *self) { POST_PROCESSING_II }; static void FrameAccum_postprocessing_ai(FrameAccum *self) { POST_PROCESSING_AI }; static void FrameAccum_postprocessing_ia(FrameAccum *self) { POST_PROCESSING_IA }; static void FrameAccum_postprocessing_aa(FrameAccum *self) { POST_PROCESSING_AA }; static void FrameAccum_postprocessing_ireva(FrameAccum *self) { POST_PROCESSING_IREVA }; static void FrameAccum_postprocessing_areva(FrameAccum *self) { POST_PROCESSING_AREVA }; static void FrameAccum_postprocessing_revai(FrameAccum *self) { POST_PROCESSING_REVAI }; static void FrameAccum_postprocessing_revaa(FrameAccum *self) { POST_PROCESSING_REVAA }; static void FrameAccum_postprocessing_revareva(FrameAccum *self) { POST_PROCESSING_REVAREVA }; static void FrameAccum_setProcMode(FrameAccum *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = FrameAccum_postprocessing_ii; break; case 1: self->muladd_func_ptr = FrameAccum_postprocessing_ai; break; case 2: self->muladd_func_ptr = FrameAccum_postprocessing_revai; break; case 10: self->muladd_func_ptr = FrameAccum_postprocessing_ia; break; case 11: self->muladd_func_ptr = FrameAccum_postprocessing_aa; break; case 12: self->muladd_func_ptr = FrameAccum_postprocessing_revaa; break; case 20: self->muladd_func_ptr = FrameAccum_postprocessing_ireva; break; case 21: self->muladd_func_ptr = FrameAccum_postprocessing_areva; break; case 22: self->muladd_func_ptr = FrameAccum_postprocessing_revareva; break; } } static void FrameAccum_compute_next_data_frame(FrameAccum *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = FrameAccumMain_getSamplesBuffer((FrameAccumMain *)self->mainSplitter); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int FrameAccum_traverse(FrameAccum *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainSplitter); return 0; } static int FrameAccum_clear(FrameAccum *self) { pyo_CLEAR Py_CLEAR(self->mainSplitter); return 0; } static void FrameAccum_dealloc(FrameAccum* self) { pyo_DEALLOC FrameAccum_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * FrameAccum_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; FrameAccum *self; self = (FrameAccum *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, FrameAccum_compute_next_data_frame); self->mode_func_ptr = FrameAccum_setProcMode; static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainSplitter); Py_INCREF(maintmp); self->mainSplitter = (FrameAccumMain *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * FrameAccum_getServer(FrameAccum* self) { GET_SERVER }; static PyObject * FrameAccum_getStream(FrameAccum* self) { GET_STREAM }; static PyObject * FrameAccum_setMul(FrameAccum *self, PyObject *arg) { SET_MUL }; static PyObject * FrameAccum_setAdd(FrameAccum *self, PyObject *arg) { SET_ADD }; static PyObject * FrameAccum_setSub(FrameAccum *self, PyObject *arg) { SET_SUB }; static PyObject * FrameAccum_setDiv(FrameAccum *self, PyObject *arg) { SET_DIV }; static PyObject * FrameAccum_play(FrameAccum *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * FrameAccum_out(FrameAccum *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * FrameAccum_stop(FrameAccum *self) { STOP }; static PyObject * FrameAccum_multiply(FrameAccum *self, PyObject *arg) { MULTIPLY }; static PyObject * FrameAccum_inplace_multiply(FrameAccum *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * FrameAccum_add(FrameAccum *self, PyObject *arg) { ADD }; static PyObject * FrameAccum_inplace_add(FrameAccum *self, PyObject *arg) { INPLACE_ADD }; static PyObject * FrameAccum_sub(FrameAccum *self, PyObject *arg) { SUB }; static PyObject * FrameAccum_inplace_sub(FrameAccum *self, PyObject *arg) { INPLACE_SUB }; static PyObject * FrameAccum_div(FrameAccum *self, PyObject *arg) { DIV }; static PyObject * FrameAccum_inplace_div(FrameAccum *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef FrameAccum_members[] = { {"server", T_OBJECT_EX, offsetof(FrameAccum, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(FrameAccum, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(FrameAccum, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(FrameAccum, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef FrameAccum_methods[] = { {"getServer", (PyCFunction)FrameAccum_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)FrameAccum_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)FrameAccum_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)FrameAccum_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)FrameAccum_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)FrameAccum_setMul, METH_O, "Sets FrameAccum mul factor."}, {"setAdd", (PyCFunction)FrameAccum_setAdd, METH_O, "Sets FrameAccum add factor."}, {"setSub", (PyCFunction)FrameAccum_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)FrameAccum_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods FrameAccum_as_number = { (binaryfunc)FrameAccum_add, /*nb_add*/ (binaryfunc)FrameAccum_sub, /*nb_subtract*/ (binaryfunc)FrameAccum_multiply, /*nb_multiply*/ (binaryfunc)FrameAccum_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)FrameAccum_inplace_add, /*inplace_add*/ (binaryfunc)FrameAccum_inplace_sub, /*inplace_subtract*/ (binaryfunc)FrameAccum_inplace_multiply, /*inplace_multiply*/ (binaryfunc)FrameAccum_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject FrameAccumType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.FrameAccum_base", /*tp_name*/ sizeof(FrameAccum), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)FrameAccum_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &FrameAccum_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "FrameAccum objects. Reads one band from a FrameAccumMain object.", /* tp_doc */ (traverseproc)FrameAccum_traverse, /* tp_traverse */ (inquiry)FrameAccum_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ FrameAccum_methods, /* tp_methods */ FrameAccum_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ FrameAccum_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; PyObject *up; Stream *up_stream; PyObject *down; Stream *down_stream; PyObject *damp; Stream *damp_stream; int inputSize; int modebuffer[5]; int frameSize; int overlaps; int hopsize; int count; MYFLT **frameBuffer; MYFLT *buffer_streams; } VectralMain; static void VectralMain_generate(VectralMain *self) { int i, j, which, where, bin, halfSize; MYFLT curMag, lastMag, diff, slope, up, down, damp; halfSize = self->frameSize / 2; if (self->modebuffer[2] == 0) up = PyFloat_AS_DOUBLE(self->up); else up = Stream_getData((Stream *)self->up_stream)[0]; if (up < 0.001) up = 0.001; else if (up > 1.0) up = 1.0; up = MYPOW(up, 4.0); if (self->modebuffer[3] == 0) down = PyFloat_AS_DOUBLE(self->down); else down = Stream_getData((Stream *)self->down_stream)[0]; if (down < 0.001) down = 0.001; else if (down > 1.0) down = 1.0; down = MYPOW(down, 4.0); if (self->modebuffer[4] == 0) damp = PyFloat_AS_DOUBLE(self->damp); else damp = Stream_getData((Stream *)self->damp_stream)[0]; if (damp < 0.) damp = 0.; else if (damp > 1.0) damp = 1.0; damp = damp * 0.1 + 0.9; MYFLT ins[self->overlaps][self->bufsize]; for (j=0; joverlaps; j++) { MYFLT *in = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->input, j), "_getStream", NULL)); for (i=0; ibufsize; i++) { ins[j][i] = in[i]; } } for (i=0; ibufsize; i++) { for (j=0; joverlaps; j++) { which = j - 1; if (which < 0) which = self->overlaps - 1; where = self->count - self->hopsize; if (where < 0) where += self->frameSize; bin = self->count - (self->hopsize * j); if (bin < 0) bin += self->frameSize; slope = MYPOW(damp, (MYFLT)(bin % halfSize)); curMag = ins[j][i] * slope; lastMag = self->frameBuffer[which][where]; diff = curMag - lastMag; if (diff < 0.0) curMag = curMag * down + lastMag * (1.0 - down); else if (diff >= 0.0) curMag = curMag * up + lastMag * (1.0 - up); self->frameBuffer[j][self->count] = curMag; self->buffer_streams[i+j*self->bufsize] = curMag; } self->count++; if (self->count >= self->frameSize) self->count = 0; } } MYFLT * VectralMain_getSamplesBuffer(VectralMain *self) { return (MYFLT *)self->buffer_streams; } static void VectralMain_setProcMode(VectralMain *self) { self->proc_func_ptr = VectralMain_generate; } static void VectralMain_compute_next_data_frame(VectralMain *self) { (*self->proc_func_ptr)(self); } static int VectralMain_traverse(VectralMain *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->up); Py_VISIT(self->up_stream); Py_VISIT(self->down); Py_VISIT(self->down_stream); Py_VISIT(self->damp); Py_VISIT(self->damp_stream); return 0; } static int VectralMain_clear(VectralMain *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->up); Py_CLEAR(self->up_stream); Py_CLEAR(self->down); Py_CLEAR(self->down_stream); Py_CLEAR(self->damp); Py_CLEAR(self->damp_stream); return 0; } static void VectralMain_dealloc(VectralMain* self) { int i; pyo_DEALLOC for (i=0; ioverlaps; i++) { free(self->frameBuffer[i]); } free(self->frameBuffer); free(self->buffer_streams); VectralMain_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * VectralMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, j; PyObject *inputtmp, *uptmp=NULL, *downtmp=NULL, *damptmp=NULL; VectralMain *self; self = (VectralMain *)type->tp_alloc(type, 0); self->up = PyFloat_FromDouble(1.0); self->down = PyFloat_FromDouble(0.7); self->damp = PyFloat_FromDouble(0.9); self->count = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, VectralMain_compute_next_data_frame); self->mode_func_ptr = VectralMain_setProcMode; static char *kwlist[] = {"input", "frameSize", "overlaps", "up", "down", "damp", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oii|OOO", kwlist, &inputtmp, &self->frameSize, &self->overlaps, &uptmp, &downtmp, &damptmp)) Py_RETURN_NONE; if (inputtmp) { PyObject_CallMethod((PyObject *)self, "setInput", "O", inputtmp); } if (uptmp) { PyObject_CallMethod((PyObject *)self, "setUp", "O", uptmp); } if (downtmp) { PyObject_CallMethod((PyObject *)self, "setDown", "O", downtmp); } if (damptmp) { PyObject_CallMethod((PyObject *)self, "setDamp", "O", damptmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->hopsize = self->frameSize / self->overlaps; self->frameBuffer = (MYFLT **)realloc(self->frameBuffer, self->overlaps * sizeof(MYFLT *)); for(i=0; ioverlaps; i++) { self->frameBuffer[i] = (MYFLT *)malloc(self->frameSize * sizeof(MYFLT)); for (j=0; jframeSize; j++) { self->frameBuffer[i][j] = 0.0; } } self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->overlaps * self->bufsize * sizeof(MYFLT)); for (i=0; i<(self->overlaps*self->bufsize); i++) { self->buffer_streams[i] = 0.0; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * VectralMain_getServer(VectralMain* self) { GET_SERVER }; static PyObject * VectralMain_getStream(VectralMain* self) { GET_STREAM }; static PyObject * VectralMain_play(VectralMain *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * VectralMain_stop(VectralMain *self) { STOP }; static PyObject * VectralMain_setInput(VectralMain *self, PyObject *arg) { PyObject *tmp; if (! PyList_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The inputs attribute must be a list."); Py_INCREF(Py_None); return Py_None; } tmp = arg; self->inputSize = PyList_Size(tmp); Py_INCREF(tmp); Py_XDECREF(self->input); self->input = tmp; Py_INCREF(Py_None); return Py_None; } static PyObject * VectralMain_setFrameSize(VectralMain *self, PyObject *arg) { int i, j, tmp; if (PyInt_Check(arg)) { tmp = PyLong_AsLong(arg); if (isPowerOfTwo(tmp)) { self->frameSize = tmp; self->hopsize = self->frameSize / self->overlaps; self->frameBuffer = (MYFLT **)realloc(self->frameBuffer, self->overlaps * sizeof(MYFLT *)); for(i=0; ioverlaps; i++) { self->frameBuffer[i] = (MYFLT *)malloc(self->frameSize * sizeof(MYFLT)); for (j=0; jframeSize; j++) { self->frameBuffer[i][j] = 0.0; } } self->count = 0; } } else printf("frameSize must be a power of two!\n"); Py_INCREF(Py_None); return Py_None; } static PyObject * VectralMain_setUp(VectralMain *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->up); if (isNumber == 1) { self->up = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->up = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->up, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->up_stream); self->up_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * VectralMain_setDown(VectralMain *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->down); if (isNumber == 1) { self->down = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->down = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->down, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->down_stream); self->down_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * VectralMain_setDamp(VectralMain *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->damp); if (isNumber == 1) { self->damp = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->damp = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->damp, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->damp_stream); self->damp_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef VectralMain_members[] = { {"server", T_OBJECT_EX, offsetof(VectralMain, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(VectralMain, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(VectralMain, input), 0, "Phase input object."}, {NULL} /* Sentinel */ }; static PyMethodDef VectralMain_methods[] = { {"getServer", (PyCFunction)VectralMain_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)VectralMain_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)VectralMain_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)VectralMain_stop, METH_NOARGS, "Stops computing."}, {"setInput", (PyCFunction)VectralMain_setInput, METH_O, "Sets list of input streams."}, {"setFrameSize", (PyCFunction)VectralMain_setFrameSize, METH_O, "Sets frame size."}, {"setUp", (PyCFunction)VectralMain_setUp, METH_O, "Sets clipping upward factor."}, {"setDown", (PyCFunction)VectralMain_setDown, METH_O, "Sets clipping downward factor."}, {"setDamp", (PyCFunction)VectralMain_setDamp, METH_O, "Sets high frequencies damping factor."}, {NULL} /* Sentinel */ }; PyTypeObject VectralMainType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.VectralMain_base", /*tp_name*/ sizeof(VectralMain), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)VectralMain_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "VectralMain objects. Smoothing between successive magnitude FFT frames.", /* tp_doc */ (traverseproc)VectralMain_traverse, /* tp_traverse */ (inquiry)VectralMain_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ VectralMain_methods, /* tp_methods */ VectralMain_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ VectralMain_new, /* tp_new */ }; /************************************************************************************************/ /* Vectral streamer object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD VectralMain *mainSplitter; int modebuffer[2]; int chnl; // panning order } Vectral; static void Vectral_postprocessing_ii(Vectral *self) { POST_PROCESSING_II }; static void Vectral_postprocessing_ai(Vectral *self) { POST_PROCESSING_AI }; static void Vectral_postprocessing_ia(Vectral *self) { POST_PROCESSING_IA }; static void Vectral_postprocessing_aa(Vectral *self) { POST_PROCESSING_AA }; static void Vectral_postprocessing_ireva(Vectral *self) { POST_PROCESSING_IREVA }; static void Vectral_postprocessing_areva(Vectral *self) { POST_PROCESSING_AREVA }; static void Vectral_postprocessing_revai(Vectral *self) { POST_PROCESSING_REVAI }; static void Vectral_postprocessing_revaa(Vectral *self) { POST_PROCESSING_REVAA }; static void Vectral_postprocessing_revareva(Vectral *self) { POST_PROCESSING_REVAREVA }; static void Vectral_setProcMode(Vectral *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Vectral_postprocessing_ii; break; case 1: self->muladd_func_ptr = Vectral_postprocessing_ai; break; case 2: self->muladd_func_ptr = Vectral_postprocessing_revai; break; case 10: self->muladd_func_ptr = Vectral_postprocessing_ia; break; case 11: self->muladd_func_ptr = Vectral_postprocessing_aa; break; case 12: self->muladd_func_ptr = Vectral_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Vectral_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Vectral_postprocessing_areva; break; case 22: self->muladd_func_ptr = Vectral_postprocessing_revareva; break; } } static void Vectral_compute_next_data_frame(Vectral *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = VectralMain_getSamplesBuffer((VectralMain *)self->mainSplitter); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int Vectral_traverse(Vectral *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainSplitter); return 0; } static int Vectral_clear(Vectral *self) { pyo_CLEAR Py_CLEAR(self->mainSplitter); return 0; } static void Vectral_dealloc(Vectral* self) { pyo_DEALLOC Vectral_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Vectral_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; Vectral *self; self = (Vectral *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Vectral_compute_next_data_frame); self->mode_func_ptr = Vectral_setProcMode; static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainSplitter); Py_INCREF(maintmp); self->mainSplitter = (VectralMain *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Vectral_getServer(Vectral* self) { GET_SERVER }; static PyObject * Vectral_getStream(Vectral* self) { GET_STREAM }; static PyObject * Vectral_setMul(Vectral *self, PyObject *arg) { SET_MUL }; static PyObject * Vectral_setAdd(Vectral *self, PyObject *arg) { SET_ADD }; static PyObject * Vectral_setSub(Vectral *self, PyObject *arg) { SET_SUB }; static PyObject * Vectral_setDiv(Vectral *self, PyObject *arg) { SET_DIV }; static PyObject * Vectral_play(Vectral *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Vectral_out(Vectral *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Vectral_stop(Vectral *self) { STOP }; static PyObject * Vectral_multiply(Vectral *self, PyObject *arg) { MULTIPLY }; static PyObject * Vectral_inplace_multiply(Vectral *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Vectral_add(Vectral *self, PyObject *arg) { ADD }; static PyObject * Vectral_inplace_add(Vectral *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Vectral_sub(Vectral *self, PyObject *arg) { SUB }; static PyObject * Vectral_inplace_sub(Vectral *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Vectral_div(Vectral *self, PyObject *arg) { DIV }; static PyObject * Vectral_inplace_div(Vectral *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Vectral_members[] = { {"server", T_OBJECT_EX, offsetof(Vectral, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Vectral, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Vectral, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Vectral, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Vectral_methods[] = { {"getServer", (PyCFunction)Vectral_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Vectral_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Vectral_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Vectral_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Vectral_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Vectral_setMul, METH_O, "Sets Vectral mul factor."}, {"setAdd", (PyCFunction)Vectral_setAdd, METH_O, "Sets Vectral add factor."}, {"setSub", (PyCFunction)Vectral_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Vectral_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Vectral_as_number = { (binaryfunc)Vectral_add, /*nb_add*/ (binaryfunc)Vectral_sub, /*nb_subtract*/ (binaryfunc)Vectral_multiply, /*nb_multiply*/ (binaryfunc)Vectral_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Vectral_inplace_add, /*inplace_add*/ (binaryfunc)Vectral_inplace_sub, /*inplace_subtract*/ (binaryfunc)Vectral_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Vectral_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject VectralType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Vectral_base", /*tp_name*/ sizeof(Vectral), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Vectral_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Vectral_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Vectral objects. Reads one band from a VectralMain object.", /* tp_doc */ (traverseproc)Vectral_traverse, /* tp_traverse */ (inquiry)Vectral_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Vectral_methods, /* tp_methods */ Vectral_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Vectral_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *bal; Stream *bal_stream; char *impulse_path; int chnl; int size; int size2; int hsize; int incount; int num_iter; int current_iter; int impulse_len; MYFLT *inframe; MYFLT *outframe; MYFLT *last_half_frame; MYFLT **twiddle; MYFLT *input_buffer; MYFLT *output_buffer; MYFLT **impulse_real; MYFLT **impulse_imag; MYFLT **accum_real; MYFLT **accum_imag; MYFLT *real; MYFLT *imag; int modebuffer[3]; } CvlVerb; static void CvlVerb_alloc_memories(CvlVerb *self) { int i, n8; self->hsize = self->size / 2; self->size2 = self->size * 2; n8 = self->size2 >> 3; self->real = (MYFLT *)realloc(self->real, self->size * sizeof(MYFLT)); self->imag = (MYFLT *)realloc(self->imag, self->size * sizeof(MYFLT)); self->inframe = (MYFLT *)realloc(self->inframe, self->size2 * sizeof(MYFLT)); self->outframe = (MYFLT *)realloc(self->outframe, self->size2 * sizeof(MYFLT)); self->last_half_frame = (MYFLT *)realloc(self->last_half_frame, self->size * sizeof(MYFLT)); self->input_buffer = (MYFLT *)realloc(self->input_buffer, self->size * sizeof(MYFLT)); self->output_buffer = (MYFLT *)realloc(self->output_buffer, self->size2 * sizeof(MYFLT)); for (i=0; isize2; i++) self->inframe[i] = self->outframe[i] = self->output_buffer[i] = 0.0; for (i=0; isize; i++) self->last_half_frame[i] = self->input_buffer[i] = 0.0; self->twiddle = (MYFLT **)realloc(self->twiddle, 4 * sizeof(MYFLT *)); for(i=0; i<4; i++) self->twiddle[i] = (MYFLT *)malloc(n8 * sizeof(MYFLT)); fft_compute_split_twiddle(self->twiddle, self->size2); } static void CvlVerb_analyse_impulse(CvlVerb *self) { SNDFILE *sf; SF_INFO info; int i, j, snd_size, snd_sr, snd_chnls, num_items, num; MYFLT *tmp, *tmp2, *inframe, *outframe; info.format = 0; sf = sf_open(self->impulse_path, SFM_READ, &info); if (sf == NULL) { printf("CvlVerb failed to open the impulse file %s.\n", self->impulse_path); return; } snd_size = info.frames; snd_sr = info.samplerate; snd_chnls = info.channels; num_items = snd_size * snd_chnls; if (snd_sr != self->sr) { printf("CvlVerb warning : Impulse sampling rate does't match the sampling rate of the server.\n"); } self->num_iter = (int)MYCEIL((MYFLT)snd_size / self->size); self->impulse_len = self->num_iter * self->size; tmp = (MYFLT *)malloc(num_items * sizeof(MYFLT)); tmp2 = (MYFLT *)malloc(self->impulse_len * sizeof(MYFLT)); sf_seek(sf, 0, SEEK_SET); num = SF_READ(sf, tmp, num_items); sf_close(sf); for (i=0; ichnl]; } for (i=snd_size; iimpulse_len; i++) { tmp2[i] = 0.0; } self->impulse_real = (MYFLT **)realloc(self->impulse_real, self->num_iter * sizeof(MYFLT *)); self->impulse_imag = (MYFLT **)realloc(self->impulse_imag, self->num_iter * sizeof(MYFLT *)); self->accum_real = (MYFLT **)realloc(self->accum_real, self->num_iter * sizeof(MYFLT *)); self->accum_imag = (MYFLT **)realloc(self->accum_imag, self->num_iter * sizeof(MYFLT *)); for(i=0; inum_iter; i++) { self->impulse_real[i] = (MYFLT *)malloc(self->size * sizeof(MYFLT)); self->impulse_imag[i] = (MYFLT *)malloc(self->size * sizeof(MYFLT)); self->accum_real[i] = (MYFLT *)malloc(self->size * sizeof(MYFLT)); self->accum_imag[i] = (MYFLT *)malloc(self->size * sizeof(MYFLT)); for (j=0; jsize; j++) { self->accum_real[i][j] = 0.0; self->accum_imag[i][j] = 0.0; } } inframe = (MYFLT *)malloc(self->size2 * sizeof(MYFLT)); outframe = (MYFLT *)malloc(self->size2 * sizeof(MYFLT)); for (j=0; jnum_iter; j++) { num = j * self->size; for (i=0; isize; i++) { inframe[i] = tmp2[num+i]; } for (i=self->size; isize2; i++) { inframe[i] = 0.0; } realfft_split(inframe, outframe, self->size2, self->twiddle); self->impulse_real[j][0] = outframe[0]; self->impulse_imag[j][0] = 0.0; for (i=1; isize; i++) { self->impulse_real[j][i] = outframe[i]; self->impulse_imag[j][i] = outframe[self->size2 - i]; } } free(tmp); free(tmp2); free(inframe); free(outframe); } static void CvlVerb_process_i(CvlVerb *self) { int i, j, k; MYFLT gdry; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT bal = PyFloat_AS_DOUBLE(self->bal); if (bal < 0) bal = 0.0; else if (bal > 1) bal = 1.0; gdry = 1.0 - bal; for (i=0; ibufsize; i++) { self->input_buffer[self->incount] = in[i]; self->data[i] = (self->output_buffer[self->incount] * 100 * bal) + (in[i] * gdry); self->incount++; if (self->incount == self->size) { self->incount = 0; k = self->current_iter - 1; if (k < 0) k += self->num_iter; for (i=0; isize; i++) { self->accum_real[k][i] = self->accum_imag[k][i] = 0.0; self->inframe[i] = self->last_half_frame[i]; self->inframe[i+self->size] = self->last_half_frame[i] = self->input_buffer[i]; } realfft_split(self->inframe, self->outframe, self->size2, self->twiddle); self->real[0] = self->outframe[0]; self->imag[0] = 0.0; for (i=1; isize; i++) { self->real[i] = self->outframe[i]; self->imag[i] = self->outframe[self->size2 - i]; } for (j=0; jnum_iter; j++) { k = self->current_iter + j; if (k >= self->num_iter) k -= self->num_iter; for (i=0; isize; i++) { self->accum_real[k][i] += self->real[i] * self->impulse_real[j][i] - self->imag[i] * self->impulse_imag[j][i]; self->accum_imag[k][i] += self->real[i] * self->impulse_imag[j][i] + self->imag[i] * self->impulse_real[j][i]; } } self->inframe[0] = self->accum_real[self->current_iter][0]; self->inframe[self->size] = 0.0; for (i=1; isize; i++) { self->inframe[i] = self->accum_real[self->current_iter][i]; self->inframe[self->size2 - i] = self->accum_imag[self->current_iter][i]; } irealfft_split(self->inframe, self->outframe, self->size2, self->twiddle); for (i=0; isize; i++) { self->output_buffer[i] = self->outframe[i+self->size]; } self->current_iter++; if (self->current_iter == self->num_iter) self->current_iter = 0; } } } static void CvlVerb_process_a(CvlVerb *self) { int i, j, k; MYFLT gwet, gdry; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *bal = Stream_getData((Stream *)self->bal_stream); for (i=0; ibufsize; i++) { gwet = bal[i]; if (gwet < 0) gwet = 0.0; else if (gwet > 1) gwet = 1.0; gdry = 1.0 - gwet; self->input_buffer[self->incount] = in[i]; self->data[i] = (self->output_buffer[self->incount] * 100 * gwet) + in[i] * gdry; self->incount++; if (self->incount == self->size) { self->incount = 0; k = self->current_iter - 1; if (k < 0) k += self->num_iter; for (i=0; isize; i++) { self->accum_real[k][i] = self->accum_imag[k][i] = 0.0; self->inframe[i] = self->last_half_frame[i]; self->inframe[i+self->size] = self->last_half_frame[i] = self->input_buffer[i]; } realfft_split(self->inframe, self->outframe, self->size2, self->twiddle); self->real[0] = self->outframe[0]; self->imag[0] = 0.0; for (i=1; isize; i++) { self->real[i] = self->outframe[i]; self->imag[i] = self->outframe[self->size2 - i]; } for (j=0; jnum_iter; j++) { k = self->current_iter + j; if (k >= self->num_iter) k -= self->num_iter; for (i=0; isize; i++) { self->accum_real[k][i] += self->real[i] * self->impulse_real[j][i] - self->imag[i] * self->impulse_imag[j][i]; self->accum_imag[k][i] += self->real[i] * self->impulse_imag[j][i] + self->imag[i] * self->impulse_real[j][i]; } } self->inframe[0] = self->accum_real[self->current_iter][0]; self->inframe[self->size] = 0.0; for (i=1; isize; i++) { self->inframe[i] = self->accum_real[self->current_iter][i]; self->inframe[self->size2 - i] = self->accum_imag[self->current_iter][i]; } irealfft_split(self->inframe, self->outframe, self->size2, self->twiddle); for (i=0; isize; i++) { self->output_buffer[i] = self->outframe[i+self->size]; } self->current_iter++; if (self->current_iter == self->num_iter) self->current_iter = 0; } } } static void CvlVerb_postprocessing_ii(CvlVerb *self) { POST_PROCESSING_II }; static void CvlVerb_postprocessing_ai(CvlVerb *self) { POST_PROCESSING_AI }; static void CvlVerb_postprocessing_ia(CvlVerb *self) { POST_PROCESSING_IA }; static void CvlVerb_postprocessing_aa(CvlVerb *self) { POST_PROCESSING_AA }; static void CvlVerb_postprocessing_ireva(CvlVerb *self) { POST_PROCESSING_IREVA }; static void CvlVerb_postprocessing_areva(CvlVerb *self) { POST_PROCESSING_AREVA }; static void CvlVerb_postprocessing_revai(CvlVerb *self) { POST_PROCESSING_REVAI }; static void CvlVerb_postprocessing_revaa(CvlVerb *self) { POST_PROCESSING_REVAA }; static void CvlVerb_postprocessing_revareva(CvlVerb *self) { POST_PROCESSING_REVAREVA }; static void CvlVerb_setProcMode(CvlVerb *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = CvlVerb_process_i; break; case 1: self->proc_func_ptr = CvlVerb_process_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = CvlVerb_postprocessing_ii; break; case 1: self->muladd_func_ptr = CvlVerb_postprocessing_ai; break; case 2: self->muladd_func_ptr = CvlVerb_postprocessing_revai; break; case 10: self->muladd_func_ptr = CvlVerb_postprocessing_ia; break; case 11: self->muladd_func_ptr = CvlVerb_postprocessing_aa; break; case 12: self->muladd_func_ptr = CvlVerb_postprocessing_revaa; break; case 20: self->muladd_func_ptr = CvlVerb_postprocessing_ireva; break; case 21: self->muladd_func_ptr = CvlVerb_postprocessing_areva; break; case 22: self->muladd_func_ptr = CvlVerb_postprocessing_revareva; break; } } static void CvlVerb_compute_next_data_frame(CvlVerb *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int CvlVerb_traverse(CvlVerb *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->bal); Py_VISIT(self->bal_stream); return 0; } static int CvlVerb_clear(CvlVerb *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->bal); Py_CLEAR(self->bal_stream); return 0; } static void CvlVerb_dealloc(CvlVerb* self) { int i; pyo_DEALLOC free(self->inframe); free(self->outframe); free(self->input_buffer); free(self->output_buffer); free(self->last_half_frame); for(i=0; i<4; i++) { free(self->twiddle[i]); } free(self->twiddle); for(i=0; inum_iter; i++) { free(self->impulse_real[i]); free(self->impulse_imag[i]); free(self->accum_real[i]); free(self->accum_imag[i]); } free(self->impulse_real); free(self->impulse_imag); free(self->accum_real); free(self->accum_imag); free(self->real); free(self->imag); CvlVerb_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * CvlVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, k; PyObject *inputtmp, *input_streamtmp, *baltmp=NULL, *multmp=NULL, *addtmp=NULL; CvlVerb *self; self = (CvlVerb *)type->tp_alloc(type, 0); self->bal = PyFloat_FromDouble(0.25); self->size = 1024; self->chnl = 0; self->incount = 0; self->current_iter = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, CvlVerb_compute_next_data_frame); self->mode_func_ptr = CvlVerb_setProcMode; static char *kwlist[] = {"input", "impulse", "bal", "size", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Os|OiiOO", kwlist, &inputtmp, &self->impulse_path, &baltmp, &self->size, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; if (self->size < self->bufsize) { printf("Warning : CvlVerb size less than buffer size!\nCvlVerb size set to buffersize: %d\n", self->bufsize); self->size = self->bufsize; } k = 1; while (k < self->size) k <<= 1; self->size = k; INIT_INPUT_STREAM if (baltmp) { PyObject_CallMethod((PyObject *)self, "setBal", "O", baltmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); CvlVerb_alloc_memories(self); CvlVerb_analyse_impulse(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * CvlVerb_setBal(CvlVerb *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->bal); if (isNumber == 1) { self->bal = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->bal = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->bal, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->bal_stream); self->bal_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * CvlVerb_getServer(CvlVerb* self) { GET_SERVER }; static PyObject * CvlVerb_getStream(CvlVerb* self) { GET_STREAM }; static PyObject * CvlVerb_setMul(CvlVerb *self, PyObject *arg) { SET_MUL }; static PyObject * CvlVerb_setAdd(CvlVerb *self, PyObject *arg) { SET_ADD }; static PyObject * CvlVerb_setSub(CvlVerb *self, PyObject *arg) { SET_SUB }; static PyObject * CvlVerb_setDiv(CvlVerb *self, PyObject *arg) { SET_DIV }; static PyObject * CvlVerb_play(CvlVerb *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * CvlVerb_out(CvlVerb *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * CvlVerb_stop(CvlVerb *self) { STOP }; static PyObject * CvlVerb_multiply(CvlVerb *self, PyObject *arg) { MULTIPLY }; static PyObject * CvlVerb_inplace_multiply(CvlVerb *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * CvlVerb_add(CvlVerb *self, PyObject *arg) { ADD }; static PyObject * CvlVerb_inplace_add(CvlVerb *self, PyObject *arg) { INPLACE_ADD }; static PyObject * CvlVerb_sub(CvlVerb *self, PyObject *arg) { SUB }; static PyObject * CvlVerb_inplace_sub(CvlVerb *self, PyObject *arg) { INPLACE_SUB }; static PyObject * CvlVerb_div(CvlVerb *self, PyObject *arg) { DIV }; static PyObject * CvlVerb_inplace_div(CvlVerb *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef CvlVerb_members[] = { {"server", T_OBJECT_EX, offsetof(CvlVerb, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(CvlVerb, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(CvlVerb, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(CvlVerb, add), 0, "Add factor."}, {"input", T_OBJECT_EX, offsetof(CvlVerb, input), 0, "Input sound object."}, {"bal", T_OBJECT_EX, offsetof(CvlVerb, bal), 0, "Wet/dry balance."}, {NULL} /* Sentinel */ }; static PyMethodDef CvlVerb_methods[] = { {"getServer", (PyCFunction)CvlVerb_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)CvlVerb_getStream, METH_NOARGS, "Returns stream object."}, {"out", (PyCFunction)CvlVerb_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"play", (PyCFunction)CvlVerb_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)CvlVerb_stop, METH_NOARGS, "Stops computing."}, {"setBal", (PyCFunction)CvlVerb_setBal, METH_O, "Sets wet/dry balance."}, {"setMul", (PyCFunction)CvlVerb_setMul, METH_O, "Sets CvlVerb mul factor."}, {"setAdd", (PyCFunction)CvlVerb_setAdd, METH_O, "Sets CvlVerb add factor."}, {"setSub", (PyCFunction)CvlVerb_setSub, METH_O, "Sets CvlVerb add factor."}, {"setDiv", (PyCFunction)CvlVerb_setDiv, METH_O, "Sets CvlVerb mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods CvlVerb_as_number = { (binaryfunc)CvlVerb_add, /*nb_add*/ (binaryfunc)CvlVerb_sub, /*nb_subtract*/ (binaryfunc)CvlVerb_multiply, /*nb_multiply*/ (binaryfunc)CvlVerb_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)CvlVerb_inplace_add, /*inplace_add*/ (binaryfunc)CvlVerb_inplace_sub, /*inplace_subtract*/ (binaryfunc)CvlVerb_inplace_multiply, /*inplace_multiply*/ (binaryfunc)CvlVerb_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject CvlVerbType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.CvlVerb_base", /*tp_name*/ sizeof(CvlVerb), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)CvlVerb_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &CvlVerb_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "CvlVerb objects. FFT transform.", /* tp_doc */ (traverseproc)CvlVerb_traverse, /* tp_traverse */ (inquiry)CvlVerb_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ CvlVerb_methods, /* tp_methods */ CvlVerb_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ CvlVerb_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int size; int hsize; int wintype; int incount; int freqone; int freqtwo; int width; int height; int fscaling; /* frequency scaling : 0 = lin, 1 = log */ int mscaling; /* magnitude scaling : 0 = lin, 1 = log */ MYFLT gain; MYFLT oneOverSr; MYFLT freqPerBin; MYFLT *input_buffer; MYFLT *inframe; MYFLT *outframe; MYFLT *magnitude; MYFLT *last_magnitude; MYFLT *tmpmag; MYFLT *window; MYFLT **twiddle; } Spectrum; static void Spectrum_realloc_memories(Spectrum *self) { int i, n8; self->hsize = self->size / 2; n8 = self->size >> 3; self->input_buffer = (MYFLT *)realloc(self->input_buffer, self->size * sizeof(MYFLT)); self->inframe = (MYFLT *)realloc(self->inframe, self->size * sizeof(MYFLT)); self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT)); for (i=0; isize; i++) self->input_buffer[i] = self->inframe[i] = self->outframe[i] = 0.0; self->magnitude = (MYFLT *)realloc(self->magnitude, self->hsize * sizeof(MYFLT)); self->last_magnitude = (MYFLT *)realloc(self->last_magnitude, self->hsize * sizeof(MYFLT)); self->tmpmag = (MYFLT *)realloc(self->tmpmag, (self->hsize+6) * sizeof(MYFLT)); for (i=0; ihsize; i++) self->magnitude[i] = self->last_magnitude[i] = self->tmpmag[i+3] = 0.0; self->twiddle = (MYFLT **)realloc(self->twiddle, 4 * sizeof(MYFLT *)); for(i=0; i<4; i++) self->twiddle[i] = (MYFLT *)malloc(n8 * sizeof(MYFLT)); fft_compute_split_twiddle(self->twiddle, self->size); self->window = (MYFLT *)realloc(self->window, self->size * sizeof(MYFLT)); gen_window(self->window, self->size, self->wintype); self->incount = self->hsize; self->freqPerBin = self->sr / self->size; } static PyObject * Spectrum_display(Spectrum *self) { int i, p1, b1, b2, bins; MYFLT pos, step, frac, iw, mag, h4; MYFLT logmin, logrange; PyObject *points, *tuple; b1 = (int)(self->freqone / self->freqPerBin); b2 = (int)(self->freqtwo / self->freqPerBin); bins = b2 - b1; step = bins / (MYFLT)(self->width); iw = 1.0 / (MYFLT)(self->width); h4 = self->height * 0.75; points = PyList_New(self->width+2); tuple = PyTuple_New(2); PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->height)); PyList_SET_ITEM(points, 0, tuple); tuple = PyTuple_New(2); PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(self->width)); PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->height)); PyList_SET_ITEM(points, self->width+1, tuple); if (!self->fscaling && !self->mscaling) { for (i=0; iwidth; i++) { pos = i * step + b1; p1 = (int)pos; frac = pos - p1; tuple = PyTuple_New(2); mag = ((self->magnitude[p1] + (self->magnitude[p1+1] - self->magnitude[p1]) * frac) * self->gain * 4 * h4); PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(i)); PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->height - (int)mag)); PyList_SET_ITEM(points, i+1, tuple); } } else if (!self->fscaling && self->mscaling) { for (i=0; iwidth; i++) { pos = i * step + b1; p1 = (int)pos; frac = pos - p1; tuple = PyTuple_New(2); mag = ((self->magnitude[p1] + (self->magnitude[p1+1] - self->magnitude[p1]) * frac) * 0.7 * self->gain); mag = mag > 0.001 ? mag : 0.001; mag = (60.0 + (20.0 * MYLOG10(mag))) * 0.01666 * h4; PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(i)); PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->height - (int)mag)); PyList_SET_ITEM(points, i+1, tuple); } } else if (self->fscaling && !self->mscaling) { if (self->freqone <= 20.0) self->freqone = 20.0; logmin = MYLOG10(self->freqone); logrange = MYLOG10(self->freqtwo) - logmin; for (i=0; iwidth; i++) { pos = MYPOW(10.0, i * iw * logrange + logmin) / self->freqPerBin; p1 = (int)pos; frac = pos - p1; tuple = PyTuple_New(2); mag = ((self->magnitude[p1] + (self->magnitude[p1+1] - self->magnitude[p1]) * frac) * self->gain * 4 * h4); PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(i)); PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->height - (int)mag)); PyList_SET_ITEM(points, i+1, tuple); } } else { if (self->freqone <= 20.0) self->freqone = 20.0; logmin = MYLOG10(self->freqone); logrange = MYLOG10(self->freqtwo) - logmin; for (i=0; iwidth; i++) { pos = MYPOW(10.0, i * iw * logrange + logmin) / self->freqPerBin; p1 = (int)pos; frac = pos - p1; tuple = PyTuple_New(2); mag = ((self->magnitude[p1] + (self->magnitude[p1+1] - self->magnitude[p1]) * frac) * 0.7 * self->gain); mag = mag > 0.001 ? mag : 0.001; mag = (60.0 + (20.0 * MYLOG10(mag))) * 0.01666 * self->height; PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(i)); PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->height - (int)mag)); PyList_SET_ITEM(points, i+1, tuple); } } return points; } static void Spectrum_filters(Spectrum *self) { int i, j = 0, impos = 0; MYFLT tmp = 0.0; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->input_buffer[self->incount] = in[i]; self->incount++; if (self->incount == self->size) { for (j=0; jsize; j++) { self->inframe[j] = self->input_buffer[j] * self->window[j]; } self->incount = self->hsize; realfft_split(self->inframe, self->outframe, self->size, self->twiddle); self->tmpmag[0] = self->tmpmag[1] = self->tmpmag[2] = 0.0; self->tmpmag[self->hsize] = self->tmpmag[self->hsize+1] = self->tmpmag[self->hsize+2] = 0.0; self->tmpmag[3] = MYSQRT(self->outframe[0]*self->outframe[0]); for (j=1; jhsize; j++) { impos = self->size - j; tmp = MYSQRT(self->outframe[j]*self->outframe[j] + self->outframe[impos]*self->outframe[impos]) * 2; self->tmpmag[j+3] = self->last_magnitude[j] = tmp + self->last_magnitude[j] * 0.5; } for (j=0; jhsize; j++) { tmp = (self->tmpmag[j] + self->tmpmag[j+6]) * 0.05 + (self->tmpmag[j+1] + self->tmpmag[j+5]) * 0.15 + (self->tmpmag[j+2] + self->tmpmag[j+4])* 0.3 + self->tmpmag[j+3] * 0.5; self->magnitude[j] = tmp; self->input_buffer[j] = self->input_buffer[j+self->hsize]; } } } } static void Spectrum_setProcMode(Spectrum *self) { self->proc_func_ptr = Spectrum_filters; } static void Spectrum_compute_next_data_frame(Spectrum *self) { (*self->proc_func_ptr)(self); } static int Spectrum_traverse(Spectrum *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Spectrum_clear(Spectrum *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Spectrum_dealloc(Spectrum* self) { int i; pyo_DEALLOC free(self->input_buffer); free(self->inframe); free(self->outframe); free(self->window); free(self->magnitude); free(self->last_magnitude); free(self->tmpmag); for(i=0; i<4; i++) { free(self->twiddle[i]); } free(self->twiddle); Spectrum_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Spectrum_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, k; PyObject *inputtmp, *input_streamtmp; Spectrum *self; self = (Spectrum *)type->tp_alloc(type, 0); self->size = 1024; self->wintype = 2; INIT_OBJECT_COMMON self->gain = 1.0; self->oneOverSr = 1.0 / self->sr; self->freqone = 0.0; self->freqtwo = self->sr * 0.5; self->width = 500; self->height = 400; self->fscaling = 0; self->mscaling = 1; Stream_setFunctionPtr(self->stream, Spectrum_compute_next_data_frame); self->mode_func_ptr = Spectrum_setProcMode; static char *kwlist[] = {"input", "size", "wintype", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|ii", kwlist, &inputtmp, &self->size, &self->wintype)) Py_RETURN_NONE; INIT_INPUT_STREAM PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (!isPowerOfTwo(self->size)) { k = 1; while (k < self->size) k *= 2; self->size = k; printf("size must be a power-of-2, using the next power-of-2 greater than size : %d\n", self->size); } Spectrum_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Spectrum_getServer(Spectrum* self) { GET_SERVER }; static PyObject * Spectrum_getStream(Spectrum* self) { GET_STREAM }; static PyObject * Spectrum_play(Spectrum *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Spectrum_stop(Spectrum *self) { STOP }; static PyObject * Spectrum_setSize(Spectrum *self, PyObject *arg) { int tmp; if (PyLong_Check(arg) || PyInt_Check(arg)) { tmp = PyInt_AsLong(arg); if (isPowerOfTwo(tmp)) { self->size = tmp; Spectrum_realloc_memories(self); } else printf("FFT size must be a power of two!\n"); } Py_INCREF(Py_None); return Py_None; } static PyObject * Spectrum_setWinType(Spectrum *self, PyObject *arg) { if (PyLong_Check(arg) || PyInt_Check(arg)) { self->wintype = PyLong_AsLong(arg); gen_window(self->window, self->size, self->wintype); } Py_INCREF(Py_None); return Py_None; } static PyObject * Spectrum_setLowbound(Spectrum *self, PyObject *arg) { MYFLT tmp; if (PyNumber_Check(arg)) { tmp = PyFloat_AsDouble(arg); if (tmp >= 0.0 && tmp <= 0.5) self->freqone = tmp * self->sr; else self->freqone = 0.0; } else self->freqone = 0.0; return PyFloat_FromDouble(MYFLOOR(self->freqone / self->freqPerBin) * self->freqPerBin); } static PyObject * Spectrum_getLowfreq(Spectrum *self) { return PyFloat_FromDouble(self->freqone); } static PyObject * Spectrum_setHighbound(Spectrum *self, PyObject *arg) { MYFLT tmp; if (PyNumber_Check(arg)) { tmp = PyFloat_AsDouble(arg); if (tmp >= 0.0 && tmp <= 0.5) self->freqtwo = tmp * self->sr; else self->freqtwo = self->sr * 0.5; } else self->freqtwo = self->sr * 0.5; return PyFloat_FromDouble(MYFLOOR(self->freqtwo / self->freqPerBin) * self->freqPerBin); } static PyObject * Spectrum_getHighfreq(Spectrum *self) { return PyFloat_FromDouble(self->freqtwo); } static PyObject * Spectrum_setWidth(Spectrum *self, PyObject *arg) { if (PyInt_Check(arg) || PyLong_Check(arg)) self->width = PyLong_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * Spectrum_setHeight(Spectrum *self, PyObject *arg) { if (PyInt_Check(arg) || PyLong_Check(arg)) self->height = PyLong_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * Spectrum_setFscaling(Spectrum *self, PyObject *arg) { if (PyInt_Check(arg) || PyLong_Check(arg)) self->fscaling = PyLong_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * Spectrum_setMscaling(Spectrum *self, PyObject *arg) { if (PyInt_Check(arg) || PyLong_Check(arg)) self->mscaling = PyLong_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * Spectrum_setGain(Spectrum *self, PyObject *arg) { if (PyNumber_Check(arg)) self->gain = PyFloat_AsDouble(arg); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Spectrum_members[] = { {"server", T_OBJECT_EX, offsetof(Spectrum, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Spectrum, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Spectrum, input), 0, "FFT sound object."}, {NULL} /* Sentinel */ }; static PyMethodDef Spectrum_methods[] = { {"getServer", (PyCFunction)Spectrum_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Spectrum_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Spectrum_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Spectrum_stop, METH_NOARGS, "Stops computing."}, {"setSize", (PyCFunction)Spectrum_setSize, METH_O, "Sets a new FFT size."}, {"setWinType", (PyCFunction)Spectrum_setWinType, METH_O, "Sets a new window."}, {"setLowbound", (PyCFunction)Spectrum_setLowbound, METH_O, "Sets the first frequency to display."}, {"setHighbound", (PyCFunction)Spectrum_setHighbound, METH_O, "Sets the last frequency to display."}, {"setWidth", (PyCFunction)Spectrum_setWidth, METH_O, "Sets the width of the display."}, {"setHeight", (PyCFunction)Spectrum_setHeight, METH_O, "Sets the height of the display."}, {"setFscaling", (PyCFunction)Spectrum_setFscaling, METH_O, "Sets the frequency scaling of the display."}, {"setMscaling", (PyCFunction)Spectrum_setMscaling, METH_O, "Sets the magnitude scaling of the display."}, {"setGain", (PyCFunction)Spectrum_setGain, METH_O, "Sets the magnitude gain of the display."}, {"display", (PyCFunction)Spectrum_display, METH_NOARGS, "Gets points to display."}, {"getLowfreq", (PyCFunction)Spectrum_getLowfreq, METH_NOARGS, "Returns the lowest frequency to display."}, {"getHighfreq", (PyCFunction)Spectrum_getHighfreq, METH_NOARGS, "Returns the highest frequency to display."}, {NULL} /* Sentinel */ }; PyTypeObject SpectrumType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Spectrum_base", /*tp_name*/ sizeof(Spectrum), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Spectrum_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Spectrum objects. FFT spectrum analyser.", /* tp_doc */ (traverseproc)Spectrum_traverse, /* tp_traverse */ (inquiry)Spectrum_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Spectrum_methods, /* tp_methods */ Spectrum_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Spectrum_new, /* tp_new */ };pyo/src/objects/selectmodule.c0000644000175000017500000005544412652732202015743 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; long value; MYFLT last_value; int modebuffer[2]; // need at least 2 slots for mul & add } Select; static void Select_selector(Select *self) { MYFLT val, inval; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { inval = in[i]; if (inval == self->value && inval != self->last_value) val = 1; else val = 0; self->last_value = inval; self->data[i] = val; } } static void Select_postprocessing_ii(Select *self) { POST_PROCESSING_II }; static void Select_postprocessing_ai(Select *self) { POST_PROCESSING_AI }; static void Select_postprocessing_ia(Select *self) { POST_PROCESSING_IA }; static void Select_postprocessing_aa(Select *self) { POST_PROCESSING_AA }; static void Select_postprocessing_ireva(Select *self) { POST_PROCESSING_IREVA }; static void Select_postprocessing_areva(Select *self) { POST_PROCESSING_AREVA }; static void Select_postprocessing_revai(Select *self) { POST_PROCESSING_REVAI }; static void Select_postprocessing_revaa(Select *self) { POST_PROCESSING_REVAA }; static void Select_postprocessing_revareva(Select *self) { POST_PROCESSING_REVAREVA }; static void Select_setProcMode(Select *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Select_selector; switch (muladdmode) { case 0: self->muladd_func_ptr = Select_postprocessing_ii; break; case 1: self->muladd_func_ptr = Select_postprocessing_ai; break; case 2: self->muladd_func_ptr = Select_postprocessing_revai; break; case 10: self->muladd_func_ptr = Select_postprocessing_ia; break; case 11: self->muladd_func_ptr = Select_postprocessing_aa; break; case 12: self->muladd_func_ptr = Select_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Select_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Select_postprocessing_areva; break; case 22: self->muladd_func_ptr = Select_postprocessing_revareva; break; } } static void Select_compute_next_data_frame(Select *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Select_traverse(Select *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Select_clear(Select *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Select_dealloc(Select* self) { pyo_DEALLOC Select_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Select_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; Select *self; self = (Select *)type->tp_alloc(type, 0); self->value = 0; self->last_value = -99.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Select_compute_next_data_frame); self->mode_func_ptr = Select_setProcMode; static char *kwlist[] = {"input", "value", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &inputtmp, &self->value, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Select_getServer(Select* self) { GET_SERVER }; static PyObject * Select_getStream(Select* self) { GET_STREAM }; static PyObject * Select_setMul(Select *self, PyObject *arg) { SET_MUL }; static PyObject * Select_setAdd(Select *self, PyObject *arg) { SET_ADD }; static PyObject * Select_setSub(Select *self, PyObject *arg) { SET_SUB }; static PyObject * Select_setDiv(Select *self, PyObject *arg) { SET_DIV }; static PyObject * Select_play(Select *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Select_stop(Select *self) { STOP }; static PyObject * Select_multiply(Select *self, PyObject *arg) { MULTIPLY }; static PyObject * Select_inplace_multiply(Select *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Select_add(Select *self, PyObject *arg) { ADD }; static PyObject * Select_inplace_add(Select *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Select_sub(Select *self, PyObject *arg) { SUB }; static PyObject * Select_inplace_sub(Select *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Select_div(Select *self, PyObject *arg) { DIV }; static PyObject * Select_inplace_div(Select *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Select_setValue(Select *self, PyObject *arg) { ASSERT_ARG_NOT_NULL if (PyLong_Check(arg) || PyInt_Check(arg)) { self->value = PyLong_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Select_members[] = { {"server", T_OBJECT_EX, offsetof(Select, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Select, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Select, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Select, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Select_methods[] = { {"getServer", (PyCFunction)Select_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Select_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Select_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Select_stop, METH_NOARGS, "Stops computing."}, {"setValue", (PyCFunction)Select_setValue, METH_O, "Sets value to select."}, {"setMul", (PyCFunction)Select_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)Select_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)Select_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Select_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Select_as_number = { (binaryfunc)Select_add, /*nb_add*/ (binaryfunc)Select_sub, /*nb_subtract*/ (binaryfunc)Select_multiply, /*nb_multiply*/ (binaryfunc)Select_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Select_inplace_add, /*inplace_add*/ (binaryfunc)Select_inplace_sub, /*inplace_subtract*/ (binaryfunc)Select_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Select_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SelectType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Select_base", /*tp_name*/ sizeof(Select), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Select_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Select_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Select objects. Watch input and send a trig on a selected value.", /* tp_doc */ (traverseproc)Select_traverse, /* tp_traverse */ (inquiry)Select_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Select_methods, /* tp_methods */ Select_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Select_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; MYFLT last_value; int modebuffer[2]; // need at least 2 slots for mul & add } Change; static void Change_selector(Change *self) { MYFLT val, inval; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { inval = in[i]; if (inval < (self->last_value - 0.00001) || inval > (self->last_value + 0.00001)) { self->last_value = inval; val = 1; } else val = 0; self->data[i] = val; } } static void Change_postprocessing_ii(Change *self) { POST_PROCESSING_II }; static void Change_postprocessing_ai(Change *self) { POST_PROCESSING_AI }; static void Change_postprocessing_ia(Change *self) { POST_PROCESSING_IA }; static void Change_postprocessing_aa(Change *self) { POST_PROCESSING_AA }; static void Change_postprocessing_ireva(Change *self) { POST_PROCESSING_IREVA }; static void Change_postprocessing_areva(Change *self) { POST_PROCESSING_AREVA }; static void Change_postprocessing_revai(Change *self) { POST_PROCESSING_REVAI }; static void Change_postprocessing_revaa(Change *self) { POST_PROCESSING_REVAA }; static void Change_postprocessing_revareva(Change *self) { POST_PROCESSING_REVAREVA }; static void Change_setProcMode(Change *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Change_selector; switch (muladdmode) { case 0: self->muladd_func_ptr = Change_postprocessing_ii; break; case 1: self->muladd_func_ptr = Change_postprocessing_ai; break; case 2: self->muladd_func_ptr = Change_postprocessing_revai; break; case 10: self->muladd_func_ptr = Change_postprocessing_ia; break; case 11: self->muladd_func_ptr = Change_postprocessing_aa; break; case 12: self->muladd_func_ptr = Change_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Change_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Change_postprocessing_areva; break; case 22: self->muladd_func_ptr = Change_postprocessing_revareva; break; } } static void Change_compute_next_data_frame(Change *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Change_traverse(Change *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Change_clear(Change *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Change_dealloc(Change* self) { pyo_DEALLOC Change_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Change_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; Change *self; self = (Change *)type->tp_alloc(type, 0); self->last_value = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Change_compute_next_data_frame); self->mode_func_ptr = Change_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Change_getServer(Change* self) { GET_SERVER }; static PyObject * Change_getStream(Change* self) { GET_STREAM }; static PyObject * Change_setMul(Change *self, PyObject *arg) { SET_MUL }; static PyObject * Change_setAdd(Change *self, PyObject *arg) { SET_ADD }; static PyObject * Change_setSub(Change *self, PyObject *arg) { SET_SUB }; static PyObject * Change_setDiv(Change *self, PyObject *arg) { SET_DIV }; static PyObject * Change_play(Change *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Change_stop(Change *self) { STOP }; static PyObject * Change_multiply(Change *self, PyObject *arg) { MULTIPLY }; static PyObject * Change_inplace_multiply(Change *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Change_add(Change *self, PyObject *arg) { ADD }; static PyObject * Change_inplace_add(Change *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Change_sub(Change *self, PyObject *arg) { SUB }; static PyObject * Change_inplace_sub(Change *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Change_div(Change *self, PyObject *arg) { DIV }; static PyObject * Change_inplace_div(Change *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Change_members[] = { {"server", T_OBJECT_EX, offsetof(Change, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Change, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Change, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Change, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Change_methods[] = { {"getServer", (PyCFunction)Change_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Change_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Change_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Change_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Change_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)Change_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)Change_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Change_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Change_as_number = { (binaryfunc)Change_add, /*nb_add*/ (binaryfunc)Change_sub, /*nb_subtract*/ (binaryfunc)Change_multiply, /*nb_multiply*/ (binaryfunc)Change_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Change_inplace_add, /*inplace_add*/ (binaryfunc)Change_inplace_sub, /*inplace_subtract*/ (binaryfunc)Change_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Change_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ChangeType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Change_base", /*tp_name*/ sizeof(Change), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Change_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Change_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Change objects. Send a trig whenever input value changed.", /* tp_doc */ (traverseproc)Change_traverse, /* tp_traverse */ (inquiry)Change_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Change_methods, /* tp_methods */ Change_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Change_new, /* tp_new */ };pyo/src/objects/recordmodule.c0000644000175000017500000014725212652732202015741 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "sndfile.h" #include "interpolation.h" /************/ /* Record */ /************/ typedef struct { pyo_audio_HEAD PyObject *input_list; PyObject *input_stream_list; int chnls; int buffering; int count; int listlen; char *recpath; SNDFILE *recfile; SF_INFO recinfo; MYFLT *buffer; } Record; static void Record_process(Record *self) { int i, j, chnl, offset, totlen; MYFLT *in; totlen = self->chnls*self->bufsize*self->buffering; if (self->count == self->buffering) { self->count = 0; for (i=0; ibuffer[i] = 0.0; } } offset = self->bufsize * self->chnls * self->count; for (j=0; jlistlen; j++) { chnl = j % self->chnls; in = Stream_getData((Stream *)PyList_GET_ITEM(self->input_stream_list, j)); for (i=0; ibufsize; i++) { self->buffer[i*self->chnls+chnl+offset] += in[i]; } } self->count++; if (self->count == self->buffering) SF_WRITE(self->recfile, self->buffer, totlen); } static void Record_setProcMode(Record *self) { self->proc_func_ptr = Record_process; } static void Record_compute_next_data_frame(Record *self) { (*self->proc_func_ptr)(self); } static int Record_traverse(Record *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input_list); Py_VISIT(self->input_stream_list); return 0; } static int Record_clear(Record *self) { pyo_CLEAR Py_CLEAR(self->input_list); Py_CLEAR(self->input_stream_list); return 0; } static void Record_dealloc(Record* self) { if (Stream_getStreamActive(self->stream)) PyObject_CallMethod((PyObject *)self, "stop", NULL); pyo_DEALLOC free(self->buffer); Record_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Record_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, buflen; int fileformat = 0; int sampletype = 0; PyObject *input_listtmp; Record *self; self = (Record *)type->tp_alloc(type, 0); self->chnls = 2; self->buffering = 4; self->count = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Record_compute_next_data_frame); self->mode_func_ptr = Record_setProcMode; static char *kwlist[] = {"input", "filename", "chnls", "fileformat", "sampletype", "buffering", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Os|iiii", kwlist, &input_listtmp, &self->recpath, &self->chnls, &fileformat, &sampletype, &self->buffering)) Py_RETURN_NONE; Py_XDECREF(self->input_list); self->input_list = input_listtmp; self->listlen = PyList_Size(self->input_list); self->input_stream_list = PyList_New(self->listlen); for (i=0; ilistlen; i++) { PyList_SET_ITEM(self->input_stream_list, i, PyObject_CallMethod(PyList_GET_ITEM(self->input_list, i), "_getStream", NULL)); } /* Prepare sfinfo */ self->recinfo.samplerate = (int)self->sr; self->recinfo.channels = self->chnls; switch (fileformat) { case 0: self->recinfo.format = SF_FORMAT_WAV; break; case 1: self->recinfo.format = SF_FORMAT_AIFF; break; case 2: self->recinfo.format = SF_FORMAT_AU; break; case 3: self->recinfo.format = SF_FORMAT_RAW; break; case 4: self->recinfo.format = SF_FORMAT_SD2; break; case 5: self->recinfo.format = SF_FORMAT_FLAC; break; case 6: self->recinfo.format = SF_FORMAT_CAF; break; case 7: self->recinfo.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS; break; } if (fileformat != 7) { switch (sampletype) { case 0: self->recinfo.format = self->recinfo.format | SF_FORMAT_PCM_16; break; case 1: self->recinfo.format = self->recinfo.format | SF_FORMAT_PCM_24; break; case 2: self->recinfo.format = self->recinfo.format | SF_FORMAT_PCM_32; break; case 3: self->recinfo.format = self->recinfo.format | SF_FORMAT_FLOAT; break; case 4: self->recinfo.format = self->recinfo.format | SF_FORMAT_DOUBLE; break; case 5: self->recinfo.format = self->recinfo.format | SF_FORMAT_ULAW; break; case 6: self->recinfo.format = self->recinfo.format | SF_FORMAT_ALAW; break; } } /* Open the output file. */ if (! (self->recfile = sf_open(self->recpath, SFM_WRITE, &self->recinfo))) { printf ("Not able to open output file %s.\n", self->recpath); Py_RETURN_NONE; } buflen = self->bufsize * self->chnls * self->buffering; self->buffer = (MYFLT *)realloc(self->buffer, buflen * sizeof(MYFLT)); for (i=0; ibuffer[i] = 0.; } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Record_getServer(Record* self) { GET_SERVER }; static PyObject * Record_getStream(Record* self) { GET_STREAM }; static PyObject * Record_play(Record *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Record_stop(Record *self) { sf_close(self->recfile); STOP }; static PyMemberDef Record_members[] = { {"server", T_OBJECT_EX, offsetof(Record, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Record, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Record, input_list), 0, "Input sound base object list."}, {NULL} /* Sentinel */ }; static PyMethodDef Record_methods[] = { {"getServer", (PyCFunction)Record_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Record_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Record_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Record_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject RecordType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Record_base", /*tp_name*/ sizeof(Record), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Record_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Record objects. Records its audio input in a file.", /* tp_doc */ (traverseproc)Record_traverse, /* tp_traverse */ (inquiry)Record_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Record_methods, /* tp_methods */ Record_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Record_new, /* tp_new */ }; /************/ /* ControlRec */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *tmp_list; MYFLT dur; int rate; int modulo; long count; long time; long size; MYFLT *buffer; } ControlRec; static void ControlRec_process(ControlRec *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->dur > 0.0) { for (i=0; ibufsize; i++) { if ((self->time % self->modulo) == 0 && self->count < self->size) { self->buffer[self->count] = in[i]; self->count++; } self->time++; if (self->count >= self->size) PyObject_CallMethod((PyObject *)self, "stop", NULL); } } else { for (i=0; ibufsize; i++) { if ((self->time % self->modulo) == 0) { PyList_Append(self->tmp_list, PyFloat_FromDouble(in[i])); } self->time++; } } } static void ControlRec_setProcMode(ControlRec *self) { self->proc_func_ptr = ControlRec_process; } static void ControlRec_compute_next_data_frame(ControlRec *self) { (*self->proc_func_ptr)(self); } static int ControlRec_traverse(ControlRec *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->tmp_list); return 0; } static int ControlRec_clear(ControlRec *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->tmp_list); return 0; } static void ControlRec_dealloc(ControlRec* self) { pyo_DEALLOC if (self->buffer != NULL) free(self->buffer); ControlRec_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * ControlRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; long j; PyObject *inputtmp, *input_streamtmp; ControlRec *self; self = (ControlRec *)type->tp_alloc(type, 0); self->dur = 0.0; self->rate = 1000; self->tmp_list = PyList_New(0); INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, ControlRec_compute_next_data_frame); self->mode_func_ptr = ControlRec_setProcMode; static char *kwlist[] = {"input", "rate", "dur", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_IF, kwlist, &inputtmp, &self->rate, &self->dur)) Py_RETURN_NONE; INIT_INPUT_STREAM PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (self->dur > 0.0) { self->size = (long)(self->dur * self->rate + 1); self->buffer = (MYFLT *)realloc(self->buffer, self->size * sizeof(MYFLT)); for (j=0; jsize; j++) { self->buffer[j] = 0.0; } } self->modulo = (int)(self->sr / self->rate); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * ControlRec_getServer(ControlRec* self) { GET_SERVER }; static PyObject * ControlRec_getStream(ControlRec* self) { GET_STREAM }; static PyObject * ControlRec_play(ControlRec *self, PyObject *args, PyObject *kwds) { self->count = self->time = 0; PLAY }; static PyObject * ControlRec_stop(ControlRec *self) { STOP }; static PyObject * ControlRec_getData(ControlRec *self) { int i; PyObject *data, *point; MYFLT time, timescl = 1.0 / self->rate; if (self->dur > 0.0) { data = PyList_New(self->size); for (i=0; isize; i++) { time = i * timescl; point = PyTuple_New(2); PyTuple_SET_ITEM(point, 0, PyFloat_FromDouble(time)); PyTuple_SET_ITEM(point, 1, PyFloat_FromDouble(self->buffer[i])); PyList_SetItem(data, i, point); } } else { Py_ssize_t size = PyList_Size(self->tmp_list); data = PyList_New(size); for (i=0; itmp_list, i)); PyList_SetItem(data, i, point); } } return data; } static PyMemberDef ControlRec_members[] = { {"server", T_OBJECT_EX, offsetof(ControlRec, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(ControlRec, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(ControlRec, input), 0, "Input sound."}, {NULL} /* Sentinel */ }; static PyMethodDef ControlRec_methods[] = { {"getServer", (PyCFunction)ControlRec_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)ControlRec_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)ControlRec_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)ControlRec_stop, METH_NOARGS, "Stops computing."}, {"getData", (PyCFunction)ControlRec_getData, METH_NOARGS, "Returns list of sampled points."}, {NULL} /* Sentinel */ }; PyTypeObject ControlRecType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.ControlRec_base", /*tp_name*/ sizeof(ControlRec), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)ControlRec_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "ControlRec objects. Records control signal with user-defined sampling rate.", /* tp_doc */ (traverseproc)ControlRec_traverse, /* tp_traverse */ (inquiry)ControlRec_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ ControlRec_methods, /* tp_methods */ ControlRec_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ ControlRec_new, /* tp_new */ }; /**************/ /* ControlRead object */ /**************/ typedef struct { pyo_audio_HEAD MYFLT *values; int rate; int modulo; int loop; int go; int modebuffer[2]; long count; long time; long size; MYFLT *trigsBuffer; TriggerStream *trig_stream; int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */ MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int); } ControlRead; static void ControlRead_readframes_i(ControlRead *self) { MYFLT fpart; long i, mod; MYFLT invmodulo = 1.0 / self->modulo; if (self->go == 0) PyObject_CallMethod((PyObject *)self, "stop", NULL); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; if (self->go == 1) { mod = self->time % self->modulo; fpart = mod * invmodulo; self->data[i] = (*self->interp_func_ptr)(self->values, (int)self->count, fpart, (int)self->size); } else { mod = -1; self->data[i] = 0.0; } if (mod == 0) { self->count++; if (self->count >= self->size) { self->trigsBuffer[i] = 1.0; if (self->loop == 1) self->count = 0; else self->go = 0; } } self->time++; } } static void ControlRead_postprocessing_ii(ControlRead *self) { POST_PROCESSING_II }; static void ControlRead_postprocessing_ai(ControlRead *self) { POST_PROCESSING_AI }; static void ControlRead_postprocessing_ia(ControlRead *self) { POST_PROCESSING_IA }; static void ControlRead_postprocessing_aa(ControlRead *self) { POST_PROCESSING_AA }; static void ControlRead_postprocessing_ireva(ControlRead *self) { POST_PROCESSING_IREVA }; static void ControlRead_postprocessing_areva(ControlRead *self) { POST_PROCESSING_AREVA }; static void ControlRead_postprocessing_revai(ControlRead *self) { POST_PROCESSING_REVAI }; static void ControlRead_postprocessing_revaa(ControlRead *self) { POST_PROCESSING_REVAA }; static void ControlRead_postprocessing_revareva(ControlRead *self) { POST_PROCESSING_REVAREVA }; static void ControlRead_setProcMode(ControlRead *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = ControlRead_readframes_i; switch (muladdmode) { case 0: self->muladd_func_ptr = ControlRead_postprocessing_ii; break; case 1: self->muladd_func_ptr = ControlRead_postprocessing_ai; break; case 2: self->muladd_func_ptr = ControlRead_postprocessing_revai; break; case 10: self->muladd_func_ptr = ControlRead_postprocessing_ia; break; case 11: self->muladd_func_ptr = ControlRead_postprocessing_aa; break; case 12: self->muladd_func_ptr = ControlRead_postprocessing_revaa; break; case 20: self->muladd_func_ptr = ControlRead_postprocessing_ireva; break; case 21: self->muladd_func_ptr = ControlRead_postprocessing_areva; break; case 22: self->muladd_func_ptr = ControlRead_postprocessing_revareva; break; } } static void ControlRead_compute_next_data_frame(ControlRead *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int ControlRead_traverse(ControlRead *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->trig_stream); return 0; } static int ControlRead_clear(ControlRead *self) { pyo_CLEAR Py_CLEAR(self->trig_stream); return 0; } static void ControlRead_dealloc(ControlRead* self) { pyo_DEALLOC free(self->values); free(self->trigsBuffer); ControlRead_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * ControlRead_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *valuestmp, *multmp=NULL, *addtmp=NULL; ControlRead *self; self = (ControlRead *)type->tp_alloc(type, 0); self->loop = 0; self->rate = 1000; self->interp = 2; self->go = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, ControlRead_compute_next_data_frame); self->mode_func_ptr = ControlRead_setProcMode; static char *kwlist[] = {"values", "rate", "loop", "interp", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iiiOO", kwlist, &valuestmp, &self->rate, &self->loop, &self->interp, &multmp, &addtmp)) Py_RETURN_NONE; if (valuestmp) { PyObject_CallMethod((PyObject *)self, "setValues", "O", valuestmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); self->modulo = (int)(self->sr / self->rate); (*self->mode_func_ptr)(self); SET_INTERP_POINTER return (PyObject *)self; } static PyObject * ControlRead_getServer(ControlRead* self) { GET_SERVER }; static PyObject * ControlRead_getStream(ControlRead* self) { GET_STREAM }; static PyObject * ControlRead_getTriggerStream(ControlRead* self) { GET_TRIGGER_STREAM }; static PyObject * ControlRead_setMul(ControlRead *self, PyObject *arg) { SET_MUL }; static PyObject * ControlRead_setAdd(ControlRead *self, PyObject *arg) { SET_ADD }; static PyObject * ControlRead_setSub(ControlRead *self, PyObject *arg) { SET_SUB }; static PyObject * ControlRead_setDiv(ControlRead *self, PyObject *arg) { SET_DIV }; static PyObject * ControlRead_play(ControlRead *self, PyObject *args, PyObject *kwds) { self->count = self->time = 0; self->go = 1; PLAY }; static PyObject * ControlRead_stop(ControlRead *self) { self->go = 0; STOP }; static PyObject * ControlRead_multiply(ControlRead *self, PyObject *arg) { MULTIPLY }; static PyObject * ControlRead_inplace_multiply(ControlRead *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * ControlRead_add(ControlRead *self, PyObject *arg) { ADD }; static PyObject * ControlRead_inplace_add(ControlRead *self, PyObject *arg) { INPLACE_ADD }; static PyObject * ControlRead_sub(ControlRead *self, PyObject *arg) { SUB }; static PyObject * ControlRead_inplace_sub(ControlRead *self, PyObject *arg) { INPLACE_SUB }; static PyObject * ControlRead_div(ControlRead *self, PyObject *arg) { DIV }; static PyObject * ControlRead_inplace_div(ControlRead *self, PyObject *arg) { INPLACE_DIV }; static PyObject * ControlRead_setValues(ControlRead *self, PyObject *arg) { Py_ssize_t i; ASSERT_ARG_NOT_NULL self->size = PyList_Size(arg); self->values = (MYFLT *)realloc(self->values, self->size * sizeof(MYFLT)); for (i=0; isize; i++) { self->values[i] = PyFloat_AsDouble(PyList_GET_ITEM(arg, i)); } Py_INCREF(Py_None); return Py_None; } static PyObject * ControlRead_setRate(ControlRead *self, PyObject *arg) { ASSERT_ARG_NOT_NULL self->rate = PyInt_AsLong(arg); self->modulo = (int)(self->sr / self->rate); Py_INCREF(Py_None); return Py_None; } static PyObject * ControlRead_setLoop(ControlRead *self, PyObject *arg) { ASSERT_ARG_NOT_NULL self->loop = PyInt_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * ControlRead_setInterp(ControlRead *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->interp = PyInt_AsLong(PyNumber_Int(arg)); } SET_INTERP_POINTER Py_INCREF(Py_None); return Py_None; } static PyMemberDef ControlRead_members[] = { {"server", T_OBJECT_EX, offsetof(ControlRead, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(ControlRead, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(ControlRead, trig_stream), 0, "Trigger Stream object."}, {"mul", T_OBJECT_EX, offsetof(ControlRead, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(ControlRead, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef ControlRead_methods[] = { {"getServer", (PyCFunction)ControlRead_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)ControlRead_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)ControlRead_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"play", (PyCFunction)ControlRead_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)ControlRead_stop, METH_NOARGS, "Stops computing."}, {"setValues", (PyCFunction)ControlRead_setValues, METH_O, "Fill buffer with values in input."}, {"setRate", (PyCFunction)ControlRead_setRate, METH_O, "Sets reading rate."}, {"setLoop", (PyCFunction)ControlRead_setLoop, METH_O, "Sets the looping mode."}, {"setInterp", (PyCFunction)ControlRead_setInterp, METH_O, "Sets reader interpolation mode."}, {"setMul", (PyCFunction)ControlRead_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)ControlRead_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)ControlRead_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)ControlRead_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods ControlRead_as_number = { (binaryfunc)ControlRead_add, /*nb_add*/ (binaryfunc)ControlRead_sub, /*nb_subtract*/ (binaryfunc)ControlRead_multiply, /*nb_multiply*/ (binaryfunc)ControlRead_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)ControlRead_inplace_add, /*inplace_add*/ (binaryfunc)ControlRead_inplace_sub, /*inplace_subtract*/ (binaryfunc)ControlRead_inplace_multiply, /*inplace_multiply*/ (binaryfunc)ControlRead_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ControlReadType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.ControlRead_base", /*tp_name*/ sizeof(ControlRead), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)ControlRead_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &ControlRead_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "ControlRead objects. Generates an oscillatory waveform.", /* tp_doc */ (traverseproc)ControlRead_traverse, /* tp_traverse */ (inquiry)ControlRead_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ ControlRead_methods, /* tp_methods */ ControlRead_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ ControlRead_new, /* tp_new */ }; /************/ /* NoteinRec */ /************/ typedef struct { pyo_audio_HEAD PyObject *inputp; Stream *inputp_stream; PyObject *inputv; Stream *inputv_stream; PyObject *tmp_list_p; PyObject *tmp_list_v; PyObject *tmp_list_t; MYFLT last_pitch; MYFLT last_vel; long time; } NoteinRec; static void NoteinRec_process(NoteinRec *self) { int i; MYFLT pit, vel; MYFLT *inp = Stream_getData((Stream *)self->inputp_stream); MYFLT *inv = Stream_getData((Stream *)self->inputv_stream); for (i=0; ibufsize; i++) { pit = inp[i]; vel = inv[i]; if (pit != self->last_pitch || vel != self->last_vel) { self->last_pitch = pit; self->last_vel = vel; PyList_Append(self->tmp_list_p, PyFloat_FromDouble(pit)); PyList_Append(self->tmp_list_v, PyFloat_FromDouble(vel)); PyList_Append(self->tmp_list_t, PyFloat_FromDouble( (float)self->time / self->sr) ); } self->time++; } } static void NoteinRec_setProcMode(NoteinRec *self) { self->proc_func_ptr = NoteinRec_process; } static void NoteinRec_compute_next_data_frame(NoteinRec *self) { (*self->proc_func_ptr)(self); } static int NoteinRec_traverse(NoteinRec *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->inputp); Py_VISIT(self->inputp_stream); Py_VISIT(self->inputv); Py_VISIT(self->inputv_stream); Py_VISIT(self->tmp_list_p); Py_VISIT(self->tmp_list_v); Py_VISIT(self->tmp_list_t); return 0; } static int NoteinRec_clear(NoteinRec *self) { pyo_CLEAR Py_CLEAR(self->inputp); Py_CLEAR(self->inputp_stream); Py_CLEAR(self->inputv); Py_CLEAR(self->inputv_stream); Py_CLEAR(self->tmp_list_p); Py_CLEAR(self->tmp_list_v); Py_CLEAR(self->tmp_list_t); return 0; } static void NoteinRec_dealloc(NoteinRec* self) { pyo_DEALLOC NoteinRec_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * NoteinRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputptmp, *inputp_streamtmp, *inputvtmp, *inputv_streamtmp; NoteinRec *self; self = (NoteinRec *)type->tp_alloc(type, 0); self->tmp_list_p = PyList_New(0); self->tmp_list_v = PyList_New(0); self->tmp_list_t = PyList_New(0); self->last_pitch = self->last_vel = 0.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, NoteinRec_compute_next_data_frame); self->mode_func_ptr = NoteinRec_setProcMode; static char *kwlist[] = {"inputp", "inputv", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &inputptmp, &inputvtmp)) Py_RETURN_NONE; Py_XDECREF(self->inputp); self->inputp = inputptmp; inputp_streamtmp = PyObject_CallMethod((PyObject *)self->inputp, "_getStream", NULL); Py_INCREF(inputp_streamtmp); Py_XDECREF(self->inputp_stream); self->inputp_stream = (Stream *)inputp_streamtmp; Py_XDECREF(self->inputv); self->inputv = inputvtmp; inputv_streamtmp = PyObject_CallMethod((PyObject *)self->inputv, "_getStream", NULL); Py_INCREF(inputv_streamtmp); Py_XDECREF(self->inputv_stream); self->inputv_stream = (Stream *)inputv_streamtmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * NoteinRec_getServer(NoteinRec* self) { GET_SERVER }; static PyObject * NoteinRec_getStream(NoteinRec* self) { GET_STREAM }; static PyObject * NoteinRec_play(NoteinRec *self, PyObject *args, PyObject *kwds) { self->time = 0; PLAY }; static PyObject * NoteinRec_stop(NoteinRec *self) { STOP }; static PyObject * NoteinRec_getData(NoteinRec *self) { int i; PyObject *data, *point; Py_ssize_t size = PyList_Size(self->tmp_list_p); data = PyList_New(size); for (i=0; itmp_list_t, i)); PyTuple_SET_ITEM(point, 1, PyList_GET_ITEM(self->tmp_list_p, i)); PyTuple_SET_ITEM(point, 2, PyList_GET_ITEM(self->tmp_list_v, i)); PyList_SetItem(data, i, point); } return data; } static PyMemberDef NoteinRec_members[] = { {"server", T_OBJECT_EX, offsetof(NoteinRec, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(NoteinRec, stream), 0, "Stream object."}, {"inputp", T_OBJECT_EX, offsetof(NoteinRec, inputp), 0, "Pitch input."}, {"inputv", T_OBJECT_EX, offsetof(NoteinRec, inputv), 0, "Velocity input."}, {NULL} /* Sentinel */ }; static PyMethodDef NoteinRec_methods[] = { {"getServer", (PyCFunction)NoteinRec_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)NoteinRec_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)NoteinRec_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)NoteinRec_stop, METH_NOARGS, "Stops computing."}, {"getData", (PyCFunction)NoteinRec_getData, METH_NOARGS, "Returns list of sampled points."}, {NULL} /* Sentinel */ }; PyTypeObject NoteinRecType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.NoteinRec_base", /*tp_name*/ sizeof(NoteinRec), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)NoteinRec_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "NoteinRec objects. Records Notein signal with user-defined sampling rate.", /* tp_doc */ (traverseproc)NoteinRec_traverse, /* tp_traverse */ (inquiry)NoteinRec_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ NoteinRec_methods, /* tp_methods */ NoteinRec_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ NoteinRec_new, /* tp_new */ }; /**************/ /* NoteinRead object */ /**************/ typedef struct { pyo_audio_HEAD MYFLT *values; long *timestamps; MYFLT value; int loop; int go; int modebuffer[2]; long count; long time; long size; MYFLT *trigsBuffer; TriggerStream *trig_stream; } NoteinRead; static void NoteinRead_readframes_i(NoteinRead *self) { long i; if (self->go == 0) PyObject_CallMethod((PyObject *)self, "stop", NULL); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; if (self->go == 1) { if (self->time >= self->timestamps[self->count]) { self->value = self->values[self->count]; self->data[i] = self->value; self->count++; } else self->data[i] = self->value; } else self->data[i] = 0.0; if (self->count >= self->size) { self->trigsBuffer[i] = 1.0; if (self->loop == 1) self->time = self->count = 0; else self->go = 0; } self->time++; } } static void NoteinRead_postprocessing_ii(NoteinRead *self) { POST_PROCESSING_II }; static void NoteinRead_postprocessing_ai(NoteinRead *self) { POST_PROCESSING_AI }; static void NoteinRead_postprocessing_ia(NoteinRead *self) { POST_PROCESSING_IA }; static void NoteinRead_postprocessing_aa(NoteinRead *self) { POST_PROCESSING_AA }; static void NoteinRead_postprocessing_ireva(NoteinRead *self) { POST_PROCESSING_IREVA }; static void NoteinRead_postprocessing_areva(NoteinRead *self) { POST_PROCESSING_AREVA }; static void NoteinRead_postprocessing_revai(NoteinRead *self) { POST_PROCESSING_REVAI }; static void NoteinRead_postprocessing_revaa(NoteinRead *self) { POST_PROCESSING_REVAA }; static void NoteinRead_postprocessing_revareva(NoteinRead *self) { POST_PROCESSING_REVAREVA }; static void NoteinRead_setProcMode(NoteinRead *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = NoteinRead_readframes_i; switch (muladdmode) { case 0: self->muladd_func_ptr = NoteinRead_postprocessing_ii; break; case 1: self->muladd_func_ptr = NoteinRead_postprocessing_ai; break; case 2: self->muladd_func_ptr = NoteinRead_postprocessing_revai; break; case 10: self->muladd_func_ptr = NoteinRead_postprocessing_ia; break; case 11: self->muladd_func_ptr = NoteinRead_postprocessing_aa; break; case 12: self->muladd_func_ptr = NoteinRead_postprocessing_revaa; break; case 20: self->muladd_func_ptr = NoteinRead_postprocessing_ireva; break; case 21: self->muladd_func_ptr = NoteinRead_postprocessing_areva; break; case 22: self->muladd_func_ptr = NoteinRead_postprocessing_revareva; break; } } static void NoteinRead_compute_next_data_frame(NoteinRead *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int NoteinRead_traverse(NoteinRead *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->trig_stream); return 0; } static int NoteinRead_clear(NoteinRead *self) { pyo_CLEAR Py_CLEAR(self->trig_stream); return 0; } static void NoteinRead_dealloc(NoteinRead* self) { pyo_DEALLOC free(self->values); free(self->timestamps); free(self->trigsBuffer); NoteinRead_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * NoteinRead_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *valuestmp, *timestampstmp, *multmp=NULL, *addtmp=NULL; NoteinRead *self; self = (NoteinRead *)type->tp_alloc(type, 0); self->value = 0.0; self->loop = 0; self->go = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, NoteinRead_compute_next_data_frame); self->mode_func_ptr = NoteinRead_setProcMode; static char *kwlist[] = {"values", "timestamps", "loop", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|iOO", kwlist, &valuestmp, ×tampstmp, &self->loop, &multmp, &addtmp)) Py_RETURN_NONE; if (valuestmp) { PyObject_CallMethod((PyObject *)self, "setValues", "O", valuestmp); } if (timestampstmp) { PyObject_CallMethod((PyObject *)self, "setTimestamps", "O", timestampstmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * NoteinRead_getServer(NoteinRead* self) { GET_SERVER }; static PyObject * NoteinRead_getStream(NoteinRead* self) { GET_STREAM }; static PyObject * NoteinRead_getTriggerStream(NoteinRead* self) { GET_TRIGGER_STREAM }; static PyObject * NoteinRead_setMul(NoteinRead *self, PyObject *arg) { SET_MUL }; static PyObject * NoteinRead_setAdd(NoteinRead *self, PyObject *arg) { SET_ADD }; static PyObject * NoteinRead_setSub(NoteinRead *self, PyObject *arg) { SET_SUB }; static PyObject * NoteinRead_setDiv(NoteinRead *self, PyObject *arg) { SET_DIV }; static PyObject * NoteinRead_play(NoteinRead *self, PyObject *args, PyObject *kwds) { self->count = self->time = 0; self->go = 1; PLAY }; static PyObject * NoteinRead_stop(NoteinRead *self) { self->go = 0; STOP }; static PyObject * NoteinRead_multiply(NoteinRead *self, PyObject *arg) { MULTIPLY }; static PyObject * NoteinRead_inplace_multiply(NoteinRead *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * NoteinRead_add(NoteinRead *self, PyObject *arg) { ADD }; static PyObject * NoteinRead_inplace_add(NoteinRead *self, PyObject *arg) { INPLACE_ADD }; static PyObject * NoteinRead_sub(NoteinRead *self, PyObject *arg) { SUB }; static PyObject * NoteinRead_inplace_sub(NoteinRead *self, PyObject *arg) { INPLACE_SUB }; static PyObject * NoteinRead_div(NoteinRead *self, PyObject *arg) { DIV }; static PyObject * NoteinRead_inplace_div(NoteinRead *self, PyObject *arg) { INPLACE_DIV }; static PyObject * NoteinRead_setValues(NoteinRead *self, PyObject *arg) { Py_ssize_t i; ASSERT_ARG_NOT_NULL self->size = PyList_Size(arg); self->values = (MYFLT *)realloc(self->values, self->size * sizeof(MYFLT)); for (i=0; isize; i++) { self->values[i] = PyFloat_AsDouble(PyList_GET_ITEM(arg, i)); } Py_INCREF(Py_None); return Py_None; } static PyObject * NoteinRead_setTimestamps(NoteinRead *self, PyObject *arg) { Py_ssize_t i; ASSERT_ARG_NOT_NULL self->size = PyList_Size(arg); self->timestamps = (long *)realloc(self->timestamps, self->size * sizeof(long)); for (i=0; isize; i++) { self->timestamps[i] = (long)(PyFloat_AsDouble(PyList_GET_ITEM(arg, i)) * self->sr); } Py_INCREF(Py_None); return Py_None; } static PyObject * NoteinRead_setLoop(NoteinRead *self, PyObject *arg) { ASSERT_ARG_NOT_NULL self->loop = PyInt_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyMemberDef NoteinRead_members[] = { {"server", T_OBJECT_EX, offsetof(NoteinRead, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(NoteinRead, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(NoteinRead, trig_stream), 0, "Trigger Stream object."}, {"mul", T_OBJECT_EX, offsetof(NoteinRead, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(NoteinRead, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef NoteinRead_methods[] = { {"getServer", (PyCFunction)NoteinRead_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)NoteinRead_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)NoteinRead_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"play", (PyCFunction)NoteinRead_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)NoteinRead_stop, METH_NOARGS, "Stops computing."}, {"setValues", (PyCFunction)NoteinRead_setValues, METH_O, "Fill buffer with values in input."}, {"setTimestamps", (PyCFunction)NoteinRead_setTimestamps, METH_O, "Fill buffer with timestamps in input."}, {"setLoop", (PyCFunction)NoteinRead_setLoop, METH_O, "Sets the looping mode."}, {"setMul", (PyCFunction)NoteinRead_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)NoteinRead_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)NoteinRead_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)NoteinRead_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods NoteinRead_as_number = { (binaryfunc)NoteinRead_add, /*nb_add*/ (binaryfunc)NoteinRead_sub, /*nb_subtract*/ (binaryfunc)NoteinRead_multiply, /*nb_multiply*/ (binaryfunc)NoteinRead_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)NoteinRead_inplace_add, /*inplace_add*/ (binaryfunc)NoteinRead_inplace_sub, /*inplace_subtract*/ (binaryfunc)NoteinRead_inplace_multiply, /*inplace_multiply*/ (binaryfunc)NoteinRead_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject NoteinReadType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.NoteinRead_base", /*tp_name*/ sizeof(NoteinRead), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)NoteinRead_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &NoteinRead_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "NoteinRead objects. Reads a NoteinRec file.", /* tp_doc */ (traverseproc)NoteinRead_traverse, /* tp_traverse */ (inquiry)NoteinRead_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ NoteinRead_methods, /* tp_methods */ NoteinRead_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ NoteinRead_new, /* tp_new */ };pyo/src/objects/tablemodule.c0000644000175000017500000101714012652732202015543 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "sndfile.h" #include "wind.h" #define __TABLE_MODULE #include "tablemodule.h" #undef __TABLE_MODULE /*************************/ /* TableStream structure */ /*************************/ static void TableStream_dealloc(TableStream* self) { self->ob_type->tp_free((PyObject*)self); } static PyObject * TableStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { TableStream *self; MAKE_NEW_TABLESTREAM(self, type, NULL); return (PyObject *)self; } MYFLT * TableStream_getData(TableStream *self) { return (MYFLT *)self->data; } void TableStream_setData(TableStream *self, MYFLT *data) { self->data = data; } int TableStream_getSize(TableStream *self) { return self->size; } void TableStream_setSize(TableStream *self, int size) { self->size = size; } double TableStream_getSamplingRate(TableStream *self) { return self->samplingRate; } void TableStream_setSamplingRate(TableStream *self, double sr) { self->samplingRate = sr; } PyTypeObject TableStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TableStream", /*tp_name*/ sizeof(TableStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TableStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "TableStream objects. For internal use only. Must never be instantiated by the user.", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TableStream_new, /* tp_new */ }; /***********************/ /* HarmTable structure */ /***********************/ typedef struct { pyo_table_HEAD PyObject *amplist; } HarmTable; static void HarmTable_generate(HarmTable *self) { int i, j, ampsize; MYFLT factor, amplitude, val; ampsize = PyList_Size(self->amplist); MYFLT array[ampsize]; for(j=0; jamplist, j)); } factor = 1. / (self->size * 0.5) * PI; for(i=0; isize; i++) { val = 0; for(j=0; jdata[i] = val; } val = self->data[0]; self->data[self->size] = val; } static int HarmTable_traverse(HarmTable *self, visitproc visit, void *arg) { pyo_table_VISIT Py_VISIT(self->amplist); return 0; } static int HarmTable_clear(HarmTable *self) { pyo_table_CLEAR Py_CLEAR(self->amplist); return 0; } static void HarmTable_dealloc(HarmTable* self) { free(self->data); HarmTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * HarmTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *amplist=NULL; HarmTable *self; self = (HarmTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->amplist = PyList_New(0); PyList_Append(self->amplist, PyFloat_FromDouble(1.)); self->size = 8192; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"list", "size", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &list, &self->size)) Py_RETURN_NONE; if (amplist) { Py_INCREF(amplist); Py_DECREF(self->amplist); self->amplist = amplist; } self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); HarmTable_generate(self); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * HarmTable_getServer(HarmTable* self) { GET_SERVER }; static PyObject * HarmTable_getTableStream(HarmTable* self) { GET_TABLE_STREAM }; static PyObject * HarmTable_setData(HarmTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * HarmTable_reset(HarmTable *self) { TABLE_RESET }; static PyObject * HarmTable_normalize(HarmTable *self) { NORMALIZE }; static PyObject * HarmTable_removeDC(HarmTable *self) { REMOVE_DC }; static PyObject * HarmTable_reverse(HarmTable *self) { REVERSE }; static PyObject * HarmTable_invert(HarmTable *self) { INVERT }; static PyObject * HarmTable_rectify(HarmTable *self) { RECTIFY }; static PyObject * HarmTable_bipolarGain(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * HarmTable_lowpass(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * HarmTable_fadein(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * HarmTable_fadeout(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * HarmTable_pow(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * HarmTable_copy(HarmTable *self, PyObject *arg) { COPY }; static PyObject * HarmTable_setTable(HarmTable *self, PyObject *arg) { SET_TABLE }; static PyObject * HarmTable_getTable(HarmTable *self) { GET_TABLE }; static PyObject * HarmTable_getViewTable(HarmTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * HarmTable_put(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * HarmTable_get(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * HarmTable_add(HarmTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * HarmTable_sub(HarmTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * HarmTable_mul(HarmTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * HarmTable_setSize(HarmTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer."); return PyInt_FromLong(-1); } self->size = PyInt_AsLong(value); self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); HarmTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * HarmTable_getSize(HarmTable *self) { return PyInt_FromLong(self->size); }; static PyObject * HarmTable_replace(HarmTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute."); return PyInt_FromLong(-1); } if (! PyList_Check(value)) { PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list."); return PyInt_FromLong(-1); } Py_INCREF(value); Py_DECREF(self->amplist); self->amplist = value; HarmTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef HarmTable_members[] = { {"server", T_OBJECT_EX, offsetof(HarmTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(HarmTable, tablestream), 0, "Table stream object."}, {"amplist", T_OBJECT_EX, offsetof(HarmTable, amplist), 0, "Harmonics amplitude values."}, {NULL} /* Sentinel */ }; static PyMethodDef HarmTable_methods[] = { {"getServer", (PyCFunction)HarmTable_getServer, METH_NOARGS, "Returns server object."}, {"setTable", (PyCFunction)HarmTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)HarmTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)HarmTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)HarmTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"normalize", (PyCFunction)HarmTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"reset", (PyCFunction)HarmTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)HarmTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)HarmTable_reverse, METH_NOARGS, "Reverse the table's data in time."}, {"invert", (PyCFunction)HarmTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)HarmTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)HarmTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)HarmTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)HarmTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)HarmTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)HarmTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"copy", (PyCFunction)HarmTable_copy, METH_O, "Copy data from table given in argument."}, {"setData", (PyCFunction)HarmTable_setData, METH_O, "Sets the table from samples in a text file."}, {"setSize", (PyCFunction)HarmTable_setSize, METH_O, "Sets the size of the table in samples"}, {"getSize", (PyCFunction)HarmTable_getSize, METH_NOARGS, "Return the size of the table in samples"}, {"put", (PyCFunction)HarmTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)HarmTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"replace", (PyCFunction)HarmTable_replace, METH_O, "Sets the harmonics amplitude list and generates a new waveform table."}, {"add", (PyCFunction)HarmTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)HarmTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)HarmTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject HarmTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.HarmTable_base", /*tp_name*/ sizeof(HarmTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)HarmTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "HarmTable objects. Generates a table filled with a waveform whose harmonic content correspond to a given amplitude list values.", /* tp_doc */ (traverseproc)HarmTable_traverse, /* tp_traverse */ (inquiry)HarmTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ HarmTable_methods, /* tp_methods */ HarmTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ HarmTable_new, /* tp_new */ }; /***********************/ /* ChebyTable structure */ /***********************/ typedef struct { pyo_table_HEAD PyObject *amplist; } ChebyTable; static void ChebyTable_generate(ChebyTable *self) { int i, j, ampsize, halfsize; MYFLT amplitude, val, ihalfsize, index, x; ampsize = PyList_Size(self->amplist); if (ampsize > 12) ampsize = 12; MYFLT array[ampsize]; for(j=0; jamplist, j)); } halfsize = self->size / 2; ihalfsize = 1.0 / halfsize; x = 0.0; for(i=0; isize; i++) { val = 0; index = (i - halfsize) * ihalfsize; for(j=0; jdata[i] = val; } val = self->data[self->size-1]; self->data[self->size] = val; } static int ChebyTable_traverse(ChebyTable *self, visitproc visit, void *arg) { pyo_table_VISIT Py_VISIT(self->amplist); return 0; } static int ChebyTable_clear(ChebyTable *self) { pyo_table_CLEAR Py_CLEAR(self->amplist); return 0; } static void ChebyTable_dealloc(ChebyTable* self) { free(self->data); ChebyTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * ChebyTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *amplist=NULL; ChebyTable *self; self = (ChebyTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->amplist = PyList_New(0); PyList_Append(self->amplist, PyFloat_FromDouble(1.)); self->size = 8192; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"list", "size", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &list, &self->size)) Py_RETURN_NONE; if (amplist) { Py_INCREF(amplist); Py_DECREF(self->amplist); self->amplist = amplist; } self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); ChebyTable_generate(self); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * ChebyTable_getServer(ChebyTable* self) { GET_SERVER }; static PyObject * ChebyTable_getTableStream(ChebyTable* self) { GET_TABLE_STREAM }; static PyObject * ChebyTable_setData(ChebyTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * ChebyTable_normalize(ChebyTable *self) { NORMALIZE }; static PyObject * ChebyTable_reset(ChebyTable *self) { TABLE_RESET }; static PyObject * ChebyTable_removeDC(ChebyTable *self) { REMOVE_DC }; static PyObject * ChebyTable_reverse(ChebyTable *self) { REVERSE }; static PyObject * ChebyTable_invert(ChebyTable *self) { INVERT }; static PyObject * ChebyTable_rectify(ChebyTable *self) { RECTIFY }; static PyObject * ChebyTable_bipolarGain(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * ChebyTable_lowpass(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * ChebyTable_fadein(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * ChebyTable_fadeout(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * ChebyTable_pow(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * ChebyTable_copy(ChebyTable *self, PyObject *arg) { COPY }; static PyObject * ChebyTable_setTable(ChebyTable *self, PyObject *arg) { SET_TABLE }; static PyObject * ChebyTable_getTable(ChebyTable *self) { GET_TABLE }; static PyObject * ChebyTable_getViewTable(ChebyTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * ChebyTable_put(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * ChebyTable_get(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * ChebyTable_add(ChebyTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * ChebyTable_sub(ChebyTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * ChebyTable_mul(ChebyTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * ChebyTable_setSize(ChebyTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer."); return PyInt_FromLong(-1); } self->size = PyInt_AsLong(value); self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); ChebyTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * ChebyTable_getSize(ChebyTable *self) { return PyInt_FromLong(self->size); }; static PyObject * ChebyTable_replace(ChebyTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute."); return PyInt_FromLong(-1); } if (! PyList_Check(value)) { PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list."); return PyInt_FromLong(-1); } Py_INCREF(value); Py_DECREF(self->amplist); self->amplist = value; ChebyTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * ChebyTable_getNormTable(ChebyTable *self, PyObject *value) { int i; int halfsize = self->size / 2; MYFLT maxval = 0.0; MYFLT val = 0.0, val2 = 0.0; MYFLT last = 0.0; long sym = PyInt_AS_LONG(value); MYFLT samps[halfsize]; PyObject *samples = PyList_New(halfsize); if (sym == 0) { for (i=0; isize; i++) { if (self->data[i] > maxval) maxval = self->data[i]; } if (maxval > 1.0) { for (i=0; isize; i++) { self->data[i] /= maxval; } } maxval = -1; for (i=0; idata[halfsize+i]); if (val > maxval) maxval = val; if (maxval > 0.0) samps[i] = 1. - maxval; else samps[i] = -1.; } } else { maxval = -1; for (i=0; idata[halfsize-i]); val2 = MYFABS(self->data[halfsize+i]); if (val2 > val) val = val2; if (val > maxval) maxval = val; if (maxval > 0.0) samps[i] = 1. / maxval; else samps[i] = -1.; } } maxval = 0.0; for (i=0; i maxval) maxval = val; } for (i=0; isize / 2 - 1; for(i=0; isize; i++) { val = 0.5 + (MYCOS(TWOPI * (i - halfSize) / self->size) * 0.5); self->data[i] = val; } val = self->data[0]; self->data[self->size] = val; } static int HannTable_traverse(HannTable *self, visitproc visit, void *arg) { pyo_table_VISIT return 0; } static int HannTable_clear(HannTable *self) { pyo_table_CLEAR return 0; } static void HannTable_dealloc(HannTable* self) { free(self->data); HannTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * HannTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { HannTable *self; self = (HannTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->size = 8192; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"size", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &self->size)) Py_RETURN_NONE; self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); HannTable_generate(self); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * HannTable_getServer(HannTable* self) { GET_SERVER }; static PyObject * HannTable_getTableStream(HannTable* self) { GET_TABLE_STREAM }; static PyObject * HannTable_setData(HannTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * HannTable_normalize(HannTable *self) { NORMALIZE }; static PyObject * HannTable_reset(HannTable *self) { TABLE_RESET }; static PyObject * HannTable_removeDC(HannTable *self) { REMOVE_DC }; static PyObject * HannTable_reverse(HannTable *self) { REVERSE }; static PyObject * HannTable_invert(HannTable *self) { INVERT }; static PyObject * HannTable_rectify(HannTable *self) { RECTIFY }; static PyObject * HannTable_bipolarGain(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * HannTable_lowpass(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * HannTable_fadein(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * HannTable_fadeout(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * HannTable_pow(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * HannTable_copy(HannTable *self, PyObject *arg) { COPY }; static PyObject * HannTable_setTable(HannTable *self, PyObject *arg) { SET_TABLE }; static PyObject * HannTable_getTable(HannTable *self) { GET_TABLE }; static PyObject * HannTable_getViewTable(HannTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * HannTable_put(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * HannTable_get(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * HannTable_add(HannTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * HannTable_sub(HannTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * HannTable_mul(HannTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * HannTable_setSize(HannTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer."); return PyInt_FromLong(-1); } self->size = PyInt_AsLong(value); self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); HannTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * HannTable_getSize(HannTable *self) { return PyInt_FromLong(self->size); }; static PyMemberDef HannTable_members[] = { {"server", T_OBJECT_EX, offsetof(HannTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(HannTable, tablestream), 0, "Table stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef HannTable_methods[] = { {"getServer", (PyCFunction)HannTable_getServer, METH_NOARGS, "Returns server object."}, {"copy", (PyCFunction)HannTable_copy, METH_O, "Copy data from table given in argument."}, {"setTable", (PyCFunction)HannTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)HannTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)HannTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)HannTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"setData", (PyCFunction)HannTable_setData, METH_O, "Sets the table from samples in a text file."}, {"normalize", (PyCFunction)HannTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"reset", (PyCFunction)HannTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)HannTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)HannTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)HannTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)HannTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)HannTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)HannTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)HannTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)HannTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)HannTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"setSize", (PyCFunction)HannTable_setSize, METH_O, "Sets the size of the table in samples"}, {"getSize", (PyCFunction)HannTable_getSize, METH_NOARGS, "Return the size of the table in samples"}, {"put", (PyCFunction)HannTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)HannTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"add", (PyCFunction)HannTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)HannTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)HannTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject HannTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.HannTable_base", /*tp_name*/ sizeof(HannTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)HannTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "HannTable objects. Generates a table filled with a hanning function.", /* tp_doc */ (traverseproc)HannTable_traverse, /* tp_traverse */ (inquiry)HannTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ HannTable_methods, /* tp_methods */ HannTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ HannTable_new, /* tp_new */ }; /***********************/ /* SincTable structure */ /***********************/ typedef struct { pyo_table_HEAD MYFLT freq; int windowed; } SincTable; static void SincTable_generate(SincTable *self) { int i, half, halfMinusOne; MYFLT scl, val; half = self->size / 2; if (self->windowed) { halfMinusOne = half - 1; for(i=0; isize; i++) { scl = (MYFLT)(i - half) / half * self->freq; if (scl == 0.0) val = 1.0; else val = (MYSIN(scl) / scl); val *= 0.5 + (MYCOS(TWOPI * (i - halfMinusOne) / self->size) * 0.5); self->data[i] = val; } } else { for(i=0; isize; i++) { scl = (MYFLT)(i - half) / half * self->freq; if (scl == 0.0) val = 1.0; else val = (MYSIN(scl) / scl); self->data[i] = val; } } self->data[self->size] = self->data[0]; } static int SincTable_traverse(SincTable *self, visitproc visit, void *arg) { pyo_table_VISIT return 0; } static int SincTable_clear(SincTable *self) { pyo_table_CLEAR return 0; } static void SincTable_dealloc(SincTable* self) { free(self->data); SincTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SincTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { SincTable *self; self = (SincTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->size = 8192; self->freq = TWOPI; self->windowed = 0; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"freq", "windowed", "size", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FII, kwlist, &self->freq, &self->windowed, &self->size)) Py_RETURN_NONE; self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); SincTable_generate(self); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * SincTable_getServer(SincTable* self) { GET_SERVER }; static PyObject * SincTable_getTableStream(SincTable* self) { GET_TABLE_STREAM }; static PyObject * SincTable_setData(SincTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * SincTable_normalize(SincTable *self) { NORMALIZE }; static PyObject * SincTable_reset(SincTable *self) { TABLE_RESET }; static PyObject * SincTable_removeDC(SincTable *self) { REMOVE_DC }; static PyObject * SincTable_reverse(SincTable *self) { REVERSE }; static PyObject * SincTable_invert(SincTable *self) { INVERT }; static PyObject * SincTable_rectify(SincTable *self) { RECTIFY }; static PyObject * SincTable_bipolarGain(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * SincTable_lowpass(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * SincTable_fadein(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * SincTable_fadeout(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * SincTable_pow(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * SincTable_copy(SincTable *self, PyObject *arg) { COPY }; static PyObject * SincTable_setTable(SincTable *self, PyObject *arg) { SET_TABLE }; static PyObject * SincTable_getTable(SincTable *self) { GET_TABLE }; static PyObject * SincTable_getViewTable(SincTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * SincTable_put(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * SincTable_get(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * SincTable_add(SincTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * SincTable_sub(SincTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * SincTable_mul(SincTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * SincTable_setFreq(SincTable *self, PyObject *value) { if (! PyNumber_Check(value)) { PyErr_SetString(PyExc_TypeError, "The freq attribute value must be a number."); return PyInt_FromLong(-1); } self->freq = PyFloat_AsDouble(value); SincTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SincTable_setWindowed(SincTable *self, PyObject *value) { if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The windowed attribute value must be a boolean."); return PyInt_FromLong(-1); } self->windowed = PyInt_AsLong(value); SincTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SincTable_setSize(SincTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer."); return PyInt_FromLong(-1); } self->size = PyInt_AsLong(value); self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); SincTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SincTable_getSize(SincTable *self) { return PyInt_FromLong(self->size); }; static PyMemberDef SincTable_members[] = { {"server", T_OBJECT_EX, offsetof(SincTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(SincTable, tablestream), 0, "Table stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef SincTable_methods[] = { {"getServer", (PyCFunction)SincTable_getServer, METH_NOARGS, "Returns server object."}, {"copy", (PyCFunction)SincTable_copy, METH_O, "Copy data from table given in argument."}, {"setTable", (PyCFunction)SincTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)SincTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)SincTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)SincTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"setData", (PyCFunction)SincTable_setData, METH_O, "Sets the table from samples in a text file."}, {"normalize", (PyCFunction)SincTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"reset", (PyCFunction)SincTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)SincTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)SincTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)SincTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)SincTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)SincTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)SincTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)SincTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)SincTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)SincTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"setSize", (PyCFunction)SincTable_setSize, METH_O, "Sets the size of the table in samples"}, {"getSize", (PyCFunction)SincTable_getSize, METH_NOARGS, "Return the size of the table in samples"}, {"setFreq", (PyCFunction)SincTable_setFreq, METH_O, "Sets the frequency, in radians, of the sinc function."}, {"setWindowed", (PyCFunction)SincTable_setWindowed, METH_O, "If True, an hanning window is applied on the function."}, {"put", (PyCFunction)SincTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)SincTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"add", (PyCFunction)SincTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)SincTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)SincTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject SincTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SincTable_base", /*tp_name*/ sizeof(SincTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SincTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "SincTable objects. Generates a table filled with a sinc function.", /* tp_doc */ (traverseproc)SincTable_traverse, /* tp_traverse */ (inquiry)SincTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SincTable_methods, /* tp_methods */ SincTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SincTable_new, /* tp_new */ }; /***********************/ /* WinTable structure */ /***********************/ typedef struct { pyo_table_HEAD int type; } WinTable; static void WinTable_generate(WinTable *self) { gen_window(self->data, self->size, self->type); self->data[self->size] = self->data[0]; } static int WinTable_traverse(WinTable *self, visitproc visit, void *arg) { pyo_table_VISIT return 0; } static int WinTable_clear(WinTable *self) { pyo_table_CLEAR return 0; } static void WinTable_dealloc(WinTable* self) { free(self->data); WinTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * WinTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { WinTable *self; self = (WinTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->size = 8192; self->type = 2; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"type", "size", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, &self->type, &self->size)) Py_RETURN_NONE; self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); WinTable_generate(self); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * WinTable_getServer(WinTable* self) { GET_SERVER }; static PyObject * WinTable_getTableStream(WinTable* self) { GET_TABLE_STREAM }; static PyObject * WinTable_setData(WinTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * WinTable_normalize(WinTable *self) { NORMALIZE }; static PyObject * WinTable_reset(WinTable *self) { TABLE_RESET }; static PyObject * WinTable_removeDC(WinTable *self) { REMOVE_DC }; static PyObject * WinTable_reverse(WinTable *self) { REVERSE }; static PyObject * WinTable_invert(WinTable *self) { INVERT }; static PyObject * WinTable_rectify(WinTable *self) { RECTIFY }; static PyObject * WinTable_bipolarGain(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * WinTable_lowpass(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * WinTable_fadein(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * WinTable_fadeout(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * WinTable_pow(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * WinTable_copy(WinTable *self, PyObject *arg) { COPY }; static PyObject * WinTable_setTable(WinTable *self, PyObject *arg) { SET_TABLE }; static PyObject * WinTable_getTable(WinTable *self) { GET_TABLE }; static PyObject * WinTable_getViewTable(WinTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * WinTable_put(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * WinTable_get(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * WinTable_add(WinTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * WinTable_sub(WinTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * WinTable_mul(WinTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * WinTable_setSize(WinTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer."); return PyInt_FromLong(-1); } self->size = PyInt_AsLong(value); self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); WinTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * WinTable_getSize(WinTable *self) { return PyInt_FromLong(self->size); }; static PyObject * WinTable_setType(WinTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the type attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The type attribute value must be an integer."); return PyInt_FromLong(-1); } self->type = PyInt_AsLong(value); WinTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef WinTable_members[] = { {"server", T_OBJECT_EX, offsetof(WinTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(WinTable, tablestream), 0, "Table stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef WinTable_methods[] = { {"getServer", (PyCFunction)WinTable_getServer, METH_NOARGS, "Returns server object."}, {"copy", (PyCFunction)WinTable_copy, METH_O, "Copy data from table given in argument."}, {"setTable", (PyCFunction)WinTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)WinTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)WinTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)WinTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"setData", (PyCFunction)WinTable_setData, METH_O, "Sets the table from samples in a text file."}, {"normalize", (PyCFunction)WinTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"reset", (PyCFunction)WinTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)WinTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)WinTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)WinTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)WinTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)WinTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)WinTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)WinTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)WinTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)WinTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"setSize", (PyCFunction)WinTable_setSize, METH_O, "Sets the size of the table in samples"}, {"getSize", (PyCFunction)WinTable_getSize, METH_NOARGS, "Return the size of the table in samples"}, {"setType", (PyCFunction)WinTable_setType, METH_O, "Sets the type of the table."}, {"put", (PyCFunction)WinTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)WinTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"add", (PyCFunction)WinTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)WinTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)WinTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject WinTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.WinTable_base", /*tp_name*/ sizeof(WinTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)WinTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "WinTable objects. Generates a table filled with a hanning function.", /* tp_doc */ (traverseproc)WinTable_traverse, /* tp_traverse */ (inquiry)WinTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ WinTable_methods, /* tp_methods */ WinTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ WinTable_new, /* tp_new */ }; /***********************/ /* ParaTable structure */ /***********************/ typedef struct { pyo_table_HEAD } ParaTable; static void ParaTable_generate(ParaTable *self) { int i, sizeMinusOne; MYFLT rdur, rdur2, level, slope, curve; sizeMinusOne = self->size - 1; rdur = 1.0 / sizeMinusOne; rdur2 = rdur * rdur; level = 0.0; slope = 4.0 * (rdur - rdur2); curve = -8.0 * rdur2; for(i=0; idata[i] = level; level += slope; slope += curve; } self->data[sizeMinusOne] = self->data[0]; self->data[self->size] = self->data[0]; } static int ParaTable_traverse(ParaTable *self, visitproc visit, void *arg) { pyo_table_VISIT return 0; } static int ParaTable_clear(ParaTable *self) { pyo_table_CLEAR return 0; } static void ParaTable_dealloc(ParaTable* self) { free(self->data); ParaTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * ParaTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { ParaTable *self; self = (ParaTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->size = 8192; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"size", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &self->size)) Py_RETURN_NONE; self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); ParaTable_generate(self); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * ParaTable_getServer(ParaTable* self) { GET_SERVER }; static PyObject * ParaTable_getTableStream(ParaTable* self) { GET_TABLE_STREAM }; static PyObject * ParaTable_setData(ParaTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * ParaTable_normalize(ParaTable *self) { NORMALIZE }; static PyObject * ParaTable_reset(ParaTable *self) { TABLE_RESET }; static PyObject * ParaTable_removeDC(ParaTable *self) { REMOVE_DC }; static PyObject * ParaTable_reverse(ParaTable *self) { REVERSE }; static PyObject * ParaTable_invert(ParaTable *self) { INVERT }; static PyObject * ParaTable_rectify(ParaTable *self) { RECTIFY }; static PyObject * ParaTable_bipolarGain(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * ParaTable_lowpass(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * ParaTable_fadein(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * ParaTable_fadeout(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * ParaTable_pow(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * ParaTable_copy(ParaTable *self, PyObject *arg) { COPY }; static PyObject * ParaTable_setTable(ParaTable *self, PyObject *arg) { SET_TABLE }; static PyObject * ParaTable_getTable(ParaTable *self) { GET_TABLE }; static PyObject * ParaTable_getViewTable(ParaTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * ParaTable_put(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * ParaTable_get(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * ParaTable_add(ParaTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * ParaTable_sub(ParaTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * ParaTable_mul(ParaTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * ParaTable_setSize(ParaTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer."); return PyInt_FromLong(-1); } self->size = PyInt_AsLong(value); self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); ParaTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * ParaTable_getSize(ParaTable *self) { return PyInt_FromLong(self->size); }; static PyMemberDef ParaTable_members[] = { {"server", T_OBJECT_EX, offsetof(ParaTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(ParaTable, tablestream), 0, "Table stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef ParaTable_methods[] = { {"getServer", (PyCFunction)ParaTable_getServer, METH_NOARGS, "Returns server object."}, {"copy", (PyCFunction)ParaTable_copy, METH_O, "Copy data from table given in argument."}, {"setTable", (PyCFunction)ParaTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)ParaTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)ParaTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)ParaTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"setData", (PyCFunction)ParaTable_setData, METH_O, "Sets the table from samples in a text file."}, {"normalize", (PyCFunction)ParaTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"reset", (PyCFunction)ParaTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)ParaTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)ParaTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)ParaTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)ParaTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)ParaTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)ParaTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)ParaTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)ParaTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)ParaTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"setSize", (PyCFunction)ParaTable_setSize, METH_O, "Sets the size of the table in samples"}, {"getSize", (PyCFunction)ParaTable_getSize, METH_NOARGS, "Return the size of the table in samples"}, {"put", (PyCFunction)ParaTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)ParaTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"add", (PyCFunction)ParaTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)ParaTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)ParaTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject ParaTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.ParaTable_base", /*tp_name*/ sizeof(ParaTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)ParaTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "ParaTable objects. Generates a parabola table.", /* tp_doc */ (traverseproc)ParaTable_traverse, /* tp_traverse */ (inquiry)ParaTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ ParaTable_methods, /* tp_methods */ ParaTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ ParaTable_new, /* tp_new */ }; /***********************/ /* LinTable structure */ /***********************/ typedef struct { pyo_table_HEAD PyObject *pointslist; } LinTable; static void LinTable_generate(LinTable *self) { Py_ssize_t i, j, steps; Py_ssize_t listsize; PyObject *tup, *tup2; int x1, y1; MYFLT x2, y2, diff; y1 = 0; y2 = 0.0; listsize = PyList_Size(self->pointslist); for(i=0; i<(listsize-1); i++) { tup = PyList_GET_ITEM(self->pointslist, i); x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0))); x2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1)); tup2 = PyList_GET_ITEM(self->pointslist, i+1); y1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup2, 0))); y2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup2, 1)); steps = y1 - x1; if (steps <= 0) continue; diff = (y2 - x2) / steps; for(j=0; jdata[x1+j] = x2 + diff * j; } } if (y1 < (self->size-1)) { self->data[y1] = y2; for (i=y1; isize; i++) { self->data[i+1] = 0.0; } self->data[self->size] = 0.0; } else { self->data[self->size-1] = y2; self->data[self->size] = y2; } } static int LinTable_traverse(LinTable *self, visitproc visit, void *arg) { pyo_table_VISIT Py_VISIT(self->pointslist); return 0; } static int LinTable_clear(LinTable *self) { pyo_table_CLEAR Py_CLEAR(self->pointslist); return 0; } static void LinTable_dealloc(LinTable* self) { free(self->data); LinTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * LinTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *pointslist=NULL; LinTable *self; self = (LinTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->pointslist = PyList_New(0); self->size = 8192; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"list", "size", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &pointslist, &self->size)) Py_RETURN_NONE; if (pointslist) { Py_INCREF(pointslist); Py_DECREF(self->pointslist); self->pointslist = pointslist; } else { PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(0), PyFloat_FromDouble(0.))); PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(self->size), PyFloat_FromDouble(1.))); } self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); LinTable_generate(self); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * LinTable_getServer(LinTable* self) { GET_SERVER }; static PyObject * LinTable_getTableStream(LinTable* self) { GET_TABLE_STREAM }; static PyObject * LinTable_setData(LinTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * LinTable_normalize(LinTable *self) { NORMALIZE }; static PyObject * LinTable_reset(LinTable *self) { TABLE_RESET }; static PyObject * LinTable_removeDC(LinTable *self) { REMOVE_DC }; static PyObject * LinTable_reverse(LinTable *self) { REVERSE }; static PyObject * LinTable_invert(LinTable *self) { INVERT }; static PyObject * LinTable_rectify(LinTable *self) { RECTIFY }; static PyObject * LinTable_bipolarGain(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * LinTable_lowpass(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * LinTable_fadein(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * LinTable_fadeout(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * LinTable_pow(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * LinTable_copy(LinTable *self, PyObject *arg) { COPY }; static PyObject * LinTable_setTable(LinTable *self, PyObject *arg) { SET_TABLE }; static PyObject * LinTable_getTable(LinTable *self) { GET_TABLE }; static PyObject * LinTable_getViewTable(LinTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * LinTable_put(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * LinTable_get(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * LinTable_add(LinTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * LinTable_sub(LinTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * LinTable_mul(LinTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * LinTable_setSize(LinTable *self, PyObject *value) { Py_ssize_t i; PyObject *tup, *x2; int old_size, x1; MYFLT factor; if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer."); return PyInt_FromLong(-1); } old_size = self->size; self->size = PyInt_AsLong(value); factor = (MYFLT)(self->size) / old_size; self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); Py_ssize_t listsize = PyList_Size(self->pointslist); PyObject *listtemp = PyList_New(0); for(i=0; i<(listsize); i++) { tup = PyList_GET_ITEM(self->pointslist, i); x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0))); x2 = PyNumber_Float(PyTuple_GET_ITEM(tup, 1)); PyList_Append(listtemp, PyTuple_Pack(2, PyInt_FromLong((int)(x1*factor)), x2)); } Py_INCREF(listtemp); Py_DECREF(self->pointslist); self->pointslist = listtemp; LinTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * LinTable_getSize(LinTable *self) { return PyInt_FromLong(self->size); }; static PyObject * LinTable_getPoints(LinTable *self) { Py_INCREF(self->pointslist); return self->pointslist; }; static PyObject * LinTable_replace(LinTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute."); return PyInt_FromLong(-1); } if (! PyList_Check(value)) { PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list of tuples."); return PyInt_FromLong(-1); } Py_INCREF(value); Py_DECREF(self->pointslist); self->pointslist = value; LinTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef LinTable_members[] = { {"server", T_OBJECT_EX, offsetof(LinTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(LinTable, tablestream), 0, "Table stream object."}, {"pointslist", T_OBJECT_EX, offsetof(LinTable, pointslist), 0, "Harmonics amplitude values."}, {NULL} /* Sentinel */ }; static PyMethodDef LinTable_methods[] = { {"getServer", (PyCFunction)LinTable_getServer, METH_NOARGS, "Returns server object."}, {"copy", (PyCFunction)LinTable_copy, METH_O, "Copy data from table given in argument."}, {"setTable", (PyCFunction)LinTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)LinTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)LinTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)LinTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"setData", (PyCFunction)LinTable_setData, METH_O, "Sets the table from samples in a text file."}, {"normalize", (PyCFunction)LinTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"reset", (PyCFunction)LinTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)LinTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)LinTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)LinTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)LinTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)LinTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)LinTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)LinTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)LinTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)LinTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"setSize", (PyCFunction)LinTable_setSize, METH_O, "Sets the size of the table in samples"}, {"getSize", (PyCFunction)LinTable_getSize, METH_NOARGS, "Return the size of the table in samples"}, {"put", (PyCFunction)LinTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)LinTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"getPoints", (PyCFunction)LinTable_getPoints, METH_NOARGS, "Return the list of points."}, {"replace", (PyCFunction)LinTable_replace, METH_O, "Sets the harmonics amplitude list and generates a new waveform table."}, {"add", (PyCFunction)LinTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)LinTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)LinTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject LinTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.LinTable_base", /*tp_name*/ sizeof(LinTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)LinTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "LinTable objects. Generates a table filled with one or more straight lines.", /* tp_doc */ (traverseproc)LinTable_traverse, /* tp_traverse */ (inquiry)LinTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ LinTable_methods, /* tp_methods */ LinTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ LinTable_new, /* tp_new */ }; /***********************/ /* LogTable structure */ /***********************/ typedef struct { pyo_table_HEAD PyObject *pointslist; } LogTable; static void LogTable_generate(LogTable *self) { Py_ssize_t i, j, steps; Py_ssize_t listsize; PyObject *tup, *tup2; int x1, y1; MYFLT x2, y2, diff, range, logrange, logmin, ratio, low, high; y1 = 0; y2 = 0.0; listsize = PyList_Size(self->pointslist); for(i=0; i<(listsize-1); i++) { tup = PyList_GET_ITEM(self->pointslist, i); x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0))); x2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1)); tup2 = PyList_GET_ITEM(self->pointslist, i+1); y1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup2, 0))); y2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup2, 1)); if (x2 <= 0) x2 = 0.000001; if (y2 <= 0) y2 = 0.000001; if (x2 > y2) { low = y2; high = x2; } else { low = x2; high = y2; } steps = y1 - x1; range = high - low; logrange = MYLOG10(high) - MYLOG10(low); logmin = MYLOG10(low); if (steps <= 0) continue; if (range == 0) { for(j=0; jdata[x1+j] = x2; } } else { diff = (y2 - x2) / steps; for(j=0; jdata[x1+j] = MYPOW(10, ratio * logrange + logmin); } } } if (y1 < (self->size-1)) { self->data[y1] = y2; for (i=y1; isize; i++) { self->data[i+1] = 0.0; } self->data[self->size] = 0.0; } else { self->data[self->size-1] = y2; self->data[self->size] = y2; } } static int LogTable_traverse(LogTable *self, visitproc visit, void *arg) { pyo_table_VISIT Py_VISIT(self->pointslist); return 0; } static int LogTable_clear(LogTable *self) { pyo_table_CLEAR Py_CLEAR(self->pointslist); return 0; } static void LogTable_dealloc(LogTable* self) { free(self->data); LogTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * LogTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *pointslist=NULL; LogTable *self; self = (LogTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->pointslist = PyList_New(0); self->size = 8192; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"list", "size", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &pointslist, &self->size)) Py_RETURN_NONE; if (pointslist) { Py_INCREF(pointslist); Py_DECREF(self->pointslist); self->pointslist = pointslist; } else { PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(0), PyFloat_FromDouble(0.))); PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(self->size), PyFloat_FromDouble(1.))); } self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); LogTable_generate(self); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * LogTable_getServer(LogTable* self) { GET_SERVER }; static PyObject * LogTable_getTableStream(LogTable* self) { GET_TABLE_STREAM }; static PyObject * LogTable_setData(LogTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * LogTable_normalize(LogTable *self) { NORMALIZE }; static PyObject * LogTable_reset(LogTable *self) { TABLE_RESET }; static PyObject * LogTable_removeDC(LogTable *self) { REMOVE_DC }; static PyObject * LogTable_reverse(LogTable *self) { REVERSE }; static PyObject * LogTable_invert(LogTable *self) { INVERT }; static PyObject * LogTable_rectify(LogTable *self) { RECTIFY }; static PyObject * LogTable_bipolarGain(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * LogTable_lowpass(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * LogTable_fadein(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * LogTable_fadeout(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * LogTable_pow(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * LogTable_copy(LogTable *self, PyObject *arg) { COPY }; static PyObject * LogTable_setTable(LogTable *self, PyObject *arg) { SET_TABLE }; static PyObject * LogTable_getTable(LogTable *self) { GET_TABLE }; static PyObject * LogTable_getViewTable(LogTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * LogTable_put(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * LogTable_get(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * LogTable_add(LogTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * LogTable_sub(LogTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * LogTable_mul(LogTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * LogTable_setSize(LogTable *self, PyObject *value) { Py_ssize_t i; PyObject *tup, *x2; int old_size, x1; MYFLT factor; if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer."); return PyInt_FromLong(-1); } old_size = self->size; self->size = PyInt_AsLong(value); factor = (MYFLT)(self->size) / old_size; self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); Py_ssize_t listsize = PyList_Size(self->pointslist); PyObject *listtemp = PyList_New(0); for(i=0; i<(listsize); i++) { tup = PyList_GET_ITEM(self->pointslist, i); x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0))); x2 = PyNumber_Float(PyTuple_GET_ITEM(tup, 1)); PyList_Append(listtemp, PyTuple_Pack(2, PyInt_FromLong((int)(x1*factor)), x2)); } Py_INCREF(listtemp); Py_DECREF(self->pointslist); self->pointslist = listtemp; LogTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * LogTable_getSize(LogTable *self) { return PyInt_FromLong(self->size); }; static PyObject * LogTable_getPoints(LogTable *self) { Py_INCREF(self->pointslist); return self->pointslist; }; static PyObject * LogTable_replace(LogTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute."); return PyInt_FromLong(-1); } if (! PyList_Check(value)) { PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list of tuples."); return PyInt_FromLong(-1); } Py_INCREF(value); Py_DECREF(self->pointslist); self->pointslist = value; LogTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef LogTable_members[] = { {"server", T_OBJECT_EX, offsetof(LogTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(LogTable, tablestream), 0, "Table stream object."}, {"pointslist", T_OBJECT_EX, offsetof(LogTable, pointslist), 0, "Harmonics amplitude values."}, {NULL} /* Sentinel */ }; static PyMethodDef LogTable_methods[] = { {"getServer", (PyCFunction)LogTable_getServer, METH_NOARGS, "Returns server object."}, {"copy", (PyCFunction)LogTable_copy, METH_O, "Copy data from table given in argument."}, {"setTable", (PyCFunction)LogTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)LogTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)LogTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)LogTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"setData", (PyCFunction)LogTable_setData, METH_O, "Sets the table from samples in a text file."}, {"normalize", (PyCFunction)LogTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"reset", (PyCFunction)LogTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)LogTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)LogTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)LogTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)LogTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)LogTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)LogTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)LogTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)LogTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)LogTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"setSize", (PyCFunction)LogTable_setSize, METH_O, "Sets the size of the table in samples"}, {"getSize", (PyCFunction)LogTable_getSize, METH_NOARGS, "Return the size of the table in samples"}, {"put", (PyCFunction)LogTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)LogTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"getPoints", (PyCFunction)LogTable_getPoints, METH_NOARGS, "Return the list of points."}, {"replace", (PyCFunction)LogTable_replace, METH_O, "Sets the harmonics amplitude list and generates a new waveform table."}, {"add", (PyCFunction)LogTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)LogTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)LogTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject LogTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.LogTable_base", /*tp_name*/ sizeof(LogTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)LogTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "LogTable objects. Generates a table filled with one or more logarothmic lines.", /* tp_doc */ (traverseproc)LogTable_traverse, /* tp_traverse */ (inquiry)LogTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ LogTable_methods, /* tp_methods */ LogTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ LogTable_new, /* tp_new */ }; /***********************/ /* CosTable structure */ /***********************/ typedef struct { pyo_table_HEAD PyObject *pointslist; } CosTable; static void CosTable_generate(CosTable *self) { Py_ssize_t i, j, steps; Py_ssize_t listsize; PyObject *tup, *tup2; int x1, y1; MYFLT x2, y2, mu, mu2; y1 = 0; y2 = 0.0; listsize = PyList_Size(self->pointslist); for(i=0; i<(listsize-1); i++) { tup = PyList_GET_ITEM(self->pointslist, i); x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0))); x2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1)); tup2 = PyList_GET_ITEM(self->pointslist, i+1); y1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup2, 0))); y2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup2, 1)); steps = y1 - x1; if (steps <= 0) continue; for(j=0; jdata[x1+j] = x2 *(1.0-mu2) + y2*mu2; } } if (y1 < (self->size-1)) { self->data[y1] = y2; for (i=y1; isize; i++) { self->data[i+1] = 0.0; } self->data[self->size] = 0.0; } else { self->data[self->size-1] = y2; self->data[self->size] = y2; } } static int CosTable_traverse(CosTable *self, visitproc visit, void *arg) { pyo_table_VISIT Py_VISIT(self->pointslist); return 0; } static int CosTable_clear(CosTable *self) { pyo_table_CLEAR Py_CLEAR(self->pointslist); return 0; } static void CosTable_dealloc(CosTable* self) { free(self->data); CosTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * CosTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *pointslist=NULL; CosTable *self; self = (CosTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->pointslist = PyList_New(0); self->size = 8192; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"list", "size", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &pointslist, &self->size)) Py_RETURN_NONE; if (pointslist) { Py_INCREF(pointslist); Py_DECREF(self->pointslist); self->pointslist = pointslist; } else { PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(0), PyFloat_FromDouble(0.))); PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(self->size), PyFloat_FromDouble(1.))); } self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); CosTable_generate(self); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * CosTable_getServer(CosTable* self) { GET_SERVER }; static PyObject * CosTable_getTableStream(CosTable* self) { GET_TABLE_STREAM }; static PyObject * CosTable_setData(CosTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * CosTable_normalize(CosTable *self) { NORMALIZE }; static PyObject * CosTable_reset(CosTable *self) { TABLE_RESET }; static PyObject * CosTable_removeDC(CosTable *self) { REMOVE_DC }; static PyObject * CosTable_reverse(CosTable *self) { REVERSE }; static PyObject * CosTable_invert(CosTable *self) { INVERT }; static PyObject * CosTable_rectify(CosTable *self) { RECTIFY }; static PyObject * CosTable_bipolarGain(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * CosTable_lowpass(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * CosTable_fadein(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * CosTable_fadeout(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * CosTable_pow(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * CosTable_copy(CosTable *self, PyObject *arg) { COPY }; static PyObject * CosTable_setTable(CosTable *self, PyObject *arg) { SET_TABLE }; static PyObject * CosTable_getTable(CosTable *self) { GET_TABLE }; static PyObject * CosTable_getViewTable(CosTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * CosTable_put(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * CosTable_get(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * CosTable_add(CosTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * CosTable_sub(CosTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * CosTable_mul(CosTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * CosTable_setSize(CosTable *self, PyObject *value) { Py_ssize_t i; PyObject *tup, *x2; int old_size, x1; MYFLT factor; if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer."); return PyInt_FromLong(-1); } old_size = self->size; self->size = PyInt_AsLong(value); factor = (MYFLT)(self->size) / old_size; self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); Py_ssize_t listsize = PyList_Size(self->pointslist); PyObject *listtemp = PyList_New(0); for(i=0; i<(listsize); i++) { tup = PyList_GET_ITEM(self->pointslist, i); x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0))); x2 = PyNumber_Float(PyTuple_GET_ITEM(tup, 1)); PyList_Append(listtemp, PyTuple_Pack(2, PyInt_FromLong((int)(x1*factor)), x2)); } Py_INCREF(listtemp); Py_DECREF(self->pointslist); self->pointslist = listtemp; CosTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * CosTable_getSize(CosTable *self) { return PyInt_FromLong(self->size); }; static PyObject * CosTable_getPoints(CosTable *self) { Py_INCREF(self->pointslist); return self->pointslist; }; static PyObject * CosTable_replace(CosTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute."); return PyInt_FromLong(-1); } if (! PyList_Check(value)) { PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list of tuples."); return PyInt_FromLong(-1); } Py_INCREF(value); Py_DECREF(self->pointslist); self->pointslist = value; CosTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef CosTable_members[] = { {"server", T_OBJECT_EX, offsetof(CosTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(CosTable, tablestream), 0, "Table stream object."}, {"pointslist", T_OBJECT_EX, offsetof(CosTable, pointslist), 0, "Harmonics amplitude values."}, {NULL} /* Sentinel */ }; static PyMethodDef CosTable_methods[] = { {"getServer", (PyCFunction)CosTable_getServer, METH_NOARGS, "Returns server object."}, {"copy", (PyCFunction)CosTable_copy, METH_O, "Copy data from table given in argument."}, {"setTable", (PyCFunction)CosTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)CosTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)CosTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)CosTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"setData", (PyCFunction)CosTable_setData, METH_O, "Sets the table from samples in a text file."}, {"normalize", (PyCFunction)CosTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"reset", (PyCFunction)CosTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)CosTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)CosTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)CosTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)CosTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)CosTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)CosTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)CosTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)CosTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)CosTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"setSize", (PyCFunction)CosTable_setSize, METH_O, "Sets the size of the table in samples"}, {"getSize", (PyCFunction)CosTable_getSize, METH_NOARGS, "Return the size of the table in samples"}, {"put", (PyCFunction)CosTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)CosTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"getPoints", (PyCFunction)CosTable_getPoints, METH_NOARGS, "Return the list of points."}, {"replace", (PyCFunction)CosTable_replace, METH_O, "Sets the harmonics amplitude list and generates a new waveform table."}, {"add", (PyCFunction)CosTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)CosTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)CosTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject CosTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.CosTable_base", /*tp_name*/ sizeof(CosTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)CosTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "CosTable objects. Generates a table filled with one or more straight lines.", /* tp_doc */ (traverseproc)CosTable_traverse, /* tp_traverse */ (inquiry)CosTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ CosTable_methods, /* tp_methods */ CosTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ CosTable_new, /* tp_new */ }; /***********************/ /* CosLogTable structure */ /***********************/ typedef struct { pyo_table_HEAD PyObject *pointslist; } CosLogTable; static void CosLogTable_generate(CosLogTable *self) { Py_ssize_t i, j, steps; Py_ssize_t listsize; PyObject *tup, *tup2; int x1, y1; MYFLT x2, y2, range, logrange, logmin, ratio, low, high, mu; y1 = 0; y2 = 0.0; listsize = PyList_Size(self->pointslist); for(i=0; i<(listsize-1); i++) { tup = PyList_GET_ITEM(self->pointslist, i); x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0))); x2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1)); tup2 = PyList_GET_ITEM(self->pointslist, i+1); y1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup2, 0))); y2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup2, 1)); if (x2 <= 0) x2 = 0.000001; if (y2 <= 0) y2 = 0.000001; if (x2 > y2) { low = y2; high = x2; } else { low = x2; high = y2; } steps = y1 - x1; range = high - low; logrange = MYLOG10(high) - MYLOG10(low); logmin = MYLOG10(low); if (steps <= 0) continue; if (range == 0) { for(j=0; jdata[x1+j] = x2; } } else { for(j=0; jdata[x1+j] = MYPOW(10, ratio * logrange + logmin); } } } if (y1 < (self->size-1)) { self->data[y1] = y2; for (i=y1; isize; i++) { self->data[i+1] = 0.0; } self->data[self->size] = 0.0; } else { self->data[self->size-1] = y2; self->data[self->size] = y2; } } static int CosLogTable_traverse(CosLogTable *self, visitproc visit, void *arg) { pyo_table_VISIT Py_VISIT(self->pointslist); return 0; } static int CosLogTable_clear(CosLogTable *self) { pyo_table_CLEAR Py_CLEAR(self->pointslist); return 0; } static void CosLogTable_dealloc(CosLogTable* self) { free(self->data); CosLogTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * CosLogTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *pointslist=NULL; CosLogTable *self; self = (CosLogTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->pointslist = PyList_New(0); self->size = 8192; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"list", "size", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &pointslist, &self->size)) Py_RETURN_NONE; if (pointslist) { Py_INCREF(pointslist); Py_DECREF(self->pointslist); self->pointslist = pointslist; } else { PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(0), PyFloat_FromDouble(0.))); PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(self->size), PyFloat_FromDouble(1.))); } self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); CosLogTable_generate(self); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * CosLogTable_getServer(CosLogTable* self) { GET_SERVER }; static PyObject * CosLogTable_getTableStream(CosLogTable* self) { GET_TABLE_STREAM }; static PyObject * CosLogTable_setData(CosLogTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * CosLogTable_normalize(CosLogTable *self) { NORMALIZE }; static PyObject * CosLogTable_reset(CosLogTable *self) { TABLE_RESET }; static PyObject * CosLogTable_removeDC(CosLogTable *self) { REMOVE_DC }; static PyObject * CosLogTable_reverse(CosLogTable *self) { REVERSE }; static PyObject * CosLogTable_invert(CosLogTable *self) { INVERT }; static PyObject * CosLogTable_rectify(CosLogTable *self) { RECTIFY }; static PyObject * CosLogTable_bipolarGain(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * CosLogTable_lowpass(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * CosLogTable_fadein(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * CosLogTable_fadeout(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * CosLogTable_pow(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * CosLogTable_copy(CosLogTable *self, PyObject *arg) { COPY }; static PyObject * CosLogTable_setTable(CosLogTable *self, PyObject *arg) { SET_TABLE }; static PyObject * CosLogTable_getTable(CosLogTable *self) { GET_TABLE }; static PyObject * CosLogTable_getViewTable(CosLogTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * CosLogTable_put(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * CosLogTable_get(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * CosLogTable_add(CosLogTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * CosLogTable_sub(CosLogTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * CosLogTable_mul(CosLogTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * CosLogTable_setSize(CosLogTable *self, PyObject *value) { Py_ssize_t i; PyObject *tup, *x2; int old_size, x1; MYFLT factor; if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer."); return PyInt_FromLong(-1); } old_size = self->size; self->size = PyInt_AsLong(value); factor = (MYFLT)(self->size) / old_size; self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); Py_ssize_t listsize = PyList_Size(self->pointslist); PyObject *listtemp = PyList_New(0); for(i=0; i<(listsize); i++) { tup = PyList_GET_ITEM(self->pointslist, i); x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0))); x2 = PyNumber_Float(PyTuple_GET_ITEM(tup, 1)); PyList_Append(listtemp, PyTuple_Pack(2, PyInt_FromLong((int)(x1*factor)), x2)); } Py_INCREF(listtemp); Py_DECREF(self->pointslist); self->pointslist = listtemp; CosLogTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * CosLogTable_getSize(CosLogTable *self) { return PyInt_FromLong(self->size); }; static PyObject * CosLogTable_getPoints(CosLogTable *self) { Py_INCREF(self->pointslist); return self->pointslist; }; static PyObject * CosLogTable_replace(CosLogTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute."); return PyInt_FromLong(-1); } if (! PyList_Check(value)) { PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list of tuples."); return PyInt_FromLong(-1); } Py_INCREF(value); Py_DECREF(self->pointslist); self->pointslist = value; CosLogTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef CosLogTable_members[] = { {"server", T_OBJECT_EX, offsetof(CosLogTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(CosLogTable, tablestream), 0, "Table stream object."}, {"pointslist", T_OBJECT_EX, offsetof(CosLogTable, pointslist), 0, "Harmonics amplitude values."}, {NULL} /* Sentinel */ }; static PyMethodDef CosLogTable_methods[] = { {"getServer", (PyCFunction)CosLogTable_getServer, METH_NOARGS, "Returns server object."}, {"copy", (PyCFunction)CosLogTable_copy, METH_O, "Copy data from table given in argument."}, {"setTable", (PyCFunction)CosLogTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)CosLogTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)CosLogTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)CosLogTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"setData", (PyCFunction)CosLogTable_setData, METH_O, "Sets the table from samples in a text file."}, {"normalize", (PyCFunction)CosLogTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"reset", (PyCFunction)CosLogTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)CosLogTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)CosLogTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)CosLogTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)CosLogTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)CosLogTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)CosLogTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)CosLogTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)CosLogTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)CosLogTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"setSize", (PyCFunction)CosLogTable_setSize, METH_O, "Sets the size of the table in samples"}, {"getSize", (PyCFunction)CosLogTable_getSize, METH_NOARGS, "Return the size of the table in samples"}, {"put", (PyCFunction)CosLogTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)CosLogTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"getPoints", (PyCFunction)CosLogTable_getPoints, METH_NOARGS, "Return the list of points."}, {"replace", (PyCFunction)CosLogTable_replace, METH_O, "Sets the harmonics amplitude list and generates a new waveform table."}, {"add", (PyCFunction)CosLogTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)CosLogTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)CosLogTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject CosLogTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.CosLogTable_base", /*tp_name*/ sizeof(CosLogTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)CosLogTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "CosLogTable objects. Generates a table filled with one or more Cosine-logarithmic lines.", /* tp_doc */ (traverseproc)CosLogTable_traverse, /* tp_traverse */ (inquiry)CosLogTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ CosLogTable_methods, /* tp_methods */ CosLogTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ CosLogTable_new, /* tp_new */ }; /***********************/ /* CurveTable structure */ /***********************/ typedef struct { pyo_table_HEAD PyObject *pointslist; MYFLT tension; MYFLT bias; } CurveTable; static void CurveTable_generate(CurveTable *self) { Py_ssize_t i, j, steps; Py_ssize_t listsize; PyObject *tup; int x1, x2; MYFLT y0, y1, y2, y3; MYFLT m0, m1, mu, mu2, mu3; MYFLT a0, a1, a2, a3; for (i=0; isize; i++) { self->data[i] = 0.0; } listsize = PyList_Size(self->pointslist); int times[listsize+2]; MYFLT values[listsize+2]; for (i=0; ipointslist, i); times[i+1] = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0))); values[i+1] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1)); } // sets imaginary points times[0] = times[1] - times[2]; if (values[1] < values[2]) values[0] = values[1] - values[2]; else values[0] = values[1] + values[2]; int endP = listsize+1; times[endP] = times[endP-2] - times[endP-1]; if (values[endP-2] < values[endP-1]) values[endP] = values[endP-1] + values[endP-2]; else values[endP] = values[endP-1] - values[endP-2]; for(i=1; ibias)*(1.0-self->tension)/2.0; m0 += (y2-y1)*(1.0-self->bias)*(1.0-self->tension)/2.0; m1 = (y2-y1)*(1.0+self->bias)*(1.0-self->tension)/2.0; m1 += (y3-y2)*(1.0-self->bias)*(1.0-self->tension)/2.0; a0 = 2.0*mu3 - 3.0*mu2 + 1.0; a1 = mu3 - 2.0*mu2 + mu; a2 = mu3 - mu2; a3 = -2.0*mu3 + 3.0*mu2; self->data[x1+j] = (a0*y1 + a1*m0 + a2*m1 + a3*y2); } } self->data[self->size] = self->data[self->size-1]; } static int CurveTable_traverse(CurveTable *self, visitproc visit, void *arg) { pyo_table_VISIT Py_VISIT(self->pointslist); return 0; } static int CurveTable_clear(CurveTable *self) { pyo_table_CLEAR Py_CLEAR(self->pointslist); return 0; } static void CurveTable_dealloc(CurveTable* self) { free(self->data); CurveTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * CurveTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *pointslist=NULL; CurveTable *self; self = (CurveTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->pointslist = PyList_New(0); self->size = 8192; self->tension = 0.0; self->bias = 0.0; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"list", "tension", "bias", "size", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__OFFI, kwlist, &pointslist, &self->tension, &self->bias, &self->size)) Py_RETURN_NONE; if (pointslist) { Py_INCREF(pointslist); Py_DECREF(self->pointslist); self->pointslist = pointslist; } else { PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(0), PyFloat_FromDouble(0.))); PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(self->size), PyFloat_FromDouble(1.))); } self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); CurveTable_generate(self); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * CurveTable_getServer(CurveTable* self) { GET_SERVER }; static PyObject * CurveTable_getTableStream(CurveTable* self) { GET_TABLE_STREAM }; static PyObject * CurveTable_setData(CurveTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * CurveTable_normalize(CurveTable * self) { NORMALIZE }; static PyObject * CurveTable_reset(CurveTable * self) { TABLE_RESET }; static PyObject * CurveTable_removeDC(CurveTable *self) { REMOVE_DC }; static PyObject * CurveTable_reverse(CurveTable *self) { REVERSE }; static PyObject * CurveTable_invert(CurveTable *self) { INVERT }; static PyObject * CurveTable_rectify(CurveTable *self) { RECTIFY }; static PyObject * CurveTable_bipolarGain(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * CurveTable_lowpass(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * CurveTable_fadein(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * CurveTable_fadeout(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * CurveTable_pow(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * CurveTable_copy(CurveTable *self, PyObject *arg) { COPY }; static PyObject * CurveTable_setTable(CurveTable *self, PyObject *arg) { SET_TABLE }; static PyObject * CurveTable_getTable(CurveTable *self) { GET_TABLE }; static PyObject * CurveTable_getViewTable(CurveTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * CurveTable_put(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * CurveTable_get(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * CurveTable_add(CurveTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * CurveTable_sub(CurveTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * CurveTable_mul(CurveTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * CurveTable_setTension(CurveTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the tension attribute."); return PyInt_FromLong(-1); } if (! PyNumber_Check(value)) { PyErr_SetString(PyExc_TypeError, "The tension attribute value must be a float."); return PyInt_FromLong(-1); } self->tension = PyFloat_AsDouble(value); CurveTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * CurveTable_setBias(CurveTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the bias attribute."); return PyInt_FromLong(-1); } if (! PyNumber_Check(value)) { PyErr_SetString(PyExc_TypeError, "The bias attribute value must be a float."); return PyInt_FromLong(-1); } self->bias = PyFloat_AsDouble(value); CurveTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * CurveTable_setSize(CurveTable *self, PyObject *value) { Py_ssize_t i; PyObject *tup, *x2; int old_size, x1; MYFLT factor; if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer."); return PyInt_FromLong(-1); } old_size = self->size; self->size = PyInt_AsLong(value); factor = (MYFLT)(self->size) / old_size; self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); Py_ssize_t listsize = PyList_Size(self->pointslist); PyObject *listtemp = PyList_New(0); for(i=0; i<(listsize); i++) { tup = PyList_GET_ITEM(self->pointslist, i); x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0))); x2 = PyNumber_Float(PyTuple_GET_ITEM(tup, 1)); PyList_Append(listtemp, PyTuple_Pack(2, PyInt_FromLong((int)(x1*factor)), x2)); } Py_INCREF(listtemp); Py_DECREF(self->pointslist); self->pointslist = listtemp; CurveTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * CurveTable_getSize(CurveTable *self) { return PyInt_FromLong(self->size); }; static PyObject * CurveTable_getPoints(CurveTable *self) { Py_INCREF(self->pointslist); return self->pointslist; }; static PyObject * CurveTable_replace(CurveTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute."); return PyInt_FromLong(-1); } if (! PyList_Check(value)) { PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list of tuples."); return PyInt_FromLong(-1); } Py_INCREF(value); Py_DECREF(self->pointslist); self->pointslist = value; CurveTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef CurveTable_members[] = { {"server", T_OBJECT_EX, offsetof(CurveTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(CurveTable, tablestream), 0, "Table stream object."}, {"pointslist", T_OBJECT_EX, offsetof(CurveTable, pointslist), 0, "Harmonics amplitude values."}, {NULL} /* Sentinel */ }; static PyMethodDef CurveTable_methods[] = { {"getServer", (PyCFunction)CurveTable_getServer, METH_NOARGS, "Returns server object."}, {"copy", (PyCFunction)CurveTable_copy, METH_O, "Copy data from table given in argument."}, {"setTable", (PyCFunction)CurveTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)CurveTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)CurveTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)CurveTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"setData", (PyCFunction)CurveTable_setData, METH_O, "Sets the table from samples in a text file."}, {"setSize", (PyCFunction)CurveTable_setSize, METH_O, "Sets the size of the table in samples"}, {"getSize", (PyCFunction)CurveTable_getSize, METH_NOARGS, "Return the size of the table in samples"}, {"put", (PyCFunction)CurveTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)CurveTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"getPoints", (PyCFunction)CurveTable_getPoints, METH_NOARGS, "Return the list of points."}, {"setTension", (PyCFunction)CurveTable_setTension, METH_O, "Sets the curvature tension."}, {"setBias", (PyCFunction)CurveTable_setBias, METH_O, "Sets the curve bias."}, {"replace", (PyCFunction)CurveTable_replace, METH_O, "Sets the harmonics amplitude list and generates a new waveform table."}, {"normalize", (PyCFunction)CurveTable_normalize, METH_NOARGS, "Normalize table between -1 and 1."}, {"reset", (PyCFunction)CurveTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)CurveTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)CurveTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)CurveTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)CurveTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)CurveTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)CurveTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)CurveTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)CurveTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)CurveTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"add", (PyCFunction)CurveTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)CurveTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)CurveTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject CurveTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.CurveTable_base", /*tp_name*/ sizeof(CurveTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)CurveTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "CurveTable objects. Generates a table filled with one or more straight lines.", /* tp_doc */ (traverseproc)CurveTable_traverse, /* tp_traverse */ (inquiry)CurveTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ CurveTable_methods, /* tp_methods */ CurveTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ CurveTable_new, /* tp_new */ }; /***********************/ /* ExpTable structure */ /***********************/ typedef struct { pyo_table_HEAD PyObject *pointslist; MYFLT exp; int inverse; } ExpTable; static void ExpTable_generate(ExpTable *self) { Py_ssize_t i, j, steps; Py_ssize_t listsize; PyObject *tup; int x1, x2; MYFLT y1, y2, range, inc, pointer, scl; for (i=0; isize; i++) { self->data[i] = 0.0; } listsize = PyList_Size(self->pointslist); int times[listsize]; MYFLT values[listsize]; for (i=0; ipointslist, i); times[i] = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0))); values[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1)); } y1 = y2 = 0.0; for(i=0; i<(listsize-1); i++) { x1 = times[i]; x2 = times[i+1]; y1 = values[i]; y2 = values[i+1]; range = y2 - y1; steps = x2 - x1; if (steps <= 0) continue; inc = 1.0 / steps; pointer = 0.0; if (self->inverse == 1) { if (range >= 0) { for(j=0; jexp); self->data[x1+j] = scl * range + y1; pointer += inc; } } else { for(j=0; jexp); self->data[x1+j] = scl * range + y1; pointer += inc; } } } else { for(j=0; jexp); self->data[x1+j] = scl * range + y1; pointer += inc; } } } self->data[self->size] = y2; } static int ExpTable_traverse(ExpTable *self, visitproc visit, void *arg) { pyo_table_VISIT Py_VISIT(self->pointslist); return 0; } static int ExpTable_clear(ExpTable *self) { pyo_table_CLEAR Py_CLEAR(self->pointslist); return 0; } static void ExpTable_dealloc(ExpTable* self) { free(self->data); ExpTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * ExpTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *pointslist=NULL; ExpTable *self; self = (ExpTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->pointslist = PyList_New(0); self->size = 8192; self->exp = 10.0; self->inverse = 1; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"list", "exp", "inverse", "size", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__OFII, kwlist, &pointslist, &self->exp, &self->inverse, &self->size)) Py_RETURN_NONE; if (pointslist) { Py_INCREF(pointslist); Py_DECREF(self->pointslist); self->pointslist = pointslist; } else { PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(0), PyFloat_FromDouble(0.))); PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(self->size), PyFloat_FromDouble(1.))); } self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); ExpTable_generate(self); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * ExpTable_getServer(ExpTable* self) { GET_SERVER }; static PyObject * ExpTable_getTableStream(ExpTable* self) { GET_TABLE_STREAM }; static PyObject * ExpTable_setData(ExpTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * ExpTable_normalize(ExpTable * self) { NORMALIZE }; static PyObject * ExpTable_reset(ExpTable * self) { TABLE_RESET }; static PyObject * ExpTable_removeDC(ExpTable *self) { REMOVE_DC }; static PyObject * ExpTable_reverse(ExpTable *self) { REVERSE }; static PyObject * ExpTable_invert(ExpTable *self) { INVERT }; static PyObject * ExpTable_rectify(ExpTable *self) { RECTIFY }; static PyObject * ExpTable_bipolarGain(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * ExpTable_lowpass(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * ExpTable_fadein(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * ExpTable_fadeout(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * ExpTable_pow(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * ExpTable_copy(ExpTable *self, PyObject *arg) { COPY }; static PyObject * ExpTable_setTable(ExpTable *self, PyObject *arg) { SET_TABLE }; static PyObject * ExpTable_getTable(ExpTable *self) { GET_TABLE }; static PyObject * ExpTable_getViewTable(ExpTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * ExpTable_put(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * ExpTable_get(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * ExpTable_add(ExpTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * ExpTable_sub(ExpTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * ExpTable_mul(ExpTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * ExpTable_setExp(ExpTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the exp attribute."); return PyInt_FromLong(-1); } if (! PyNumber_Check(value)) { PyErr_SetString(PyExc_TypeError, "The exp attribute value must be a float."); return PyInt_FromLong(-1); } self->exp = PyFloat_AsDouble(value); ExpTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * ExpTable_setInverse(ExpTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the inverse attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The inverse attribute value must be a boolean (True or False or 0 or 1)."); return PyInt_FromLong(-1); } self->inverse = PyInt_AsLong(value); ExpTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * ExpTable_setSize(ExpTable *self, PyObject *value) { Py_ssize_t i; PyObject *tup, *x2; int old_size, x1; MYFLT factor; if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer."); return PyInt_FromLong(-1); } old_size = self->size; self->size = PyInt_AsLong(value); factor = (MYFLT)(self->size) / old_size; self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); Py_ssize_t listsize = PyList_Size(self->pointslist); PyObject *listtemp = PyList_New(0); for(i=0; i<(listsize); i++) { tup = PyList_GET_ITEM(self->pointslist, i); x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0))); x2 = PyNumber_Float(PyTuple_GET_ITEM(tup, 1)); PyList_Append(listtemp, PyTuple_Pack(2, PyInt_FromLong((int)(x1*factor)), x2)); } Py_INCREF(listtemp); Py_DECREF(self->pointslist); self->pointslist = listtemp; ExpTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * ExpTable_getSize(ExpTable *self) { return PyInt_FromLong(self->size); }; static PyObject * ExpTable_getPoints(ExpTable *self) { Py_INCREF(self->pointslist); return self->pointslist; }; static PyObject * ExpTable_replace(ExpTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute."); return PyInt_FromLong(-1); } if (! PyList_Check(value)) { PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list of tuples."); return PyInt_FromLong(-1); } Py_INCREF(value); Py_DECREF(self->pointslist); self->pointslist = value; ExpTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef ExpTable_members[] = { {"server", T_OBJECT_EX, offsetof(ExpTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(ExpTable, tablestream), 0, "Table stream object."}, {"pointslist", T_OBJECT_EX, offsetof(ExpTable, pointslist), 0, "Harmonics amplitude values."}, {NULL} /* Sentinel */ }; static PyMethodDef ExpTable_methods[] = { {"getServer", (PyCFunction)ExpTable_getServer, METH_NOARGS, "Returns server object."}, {"copy", (PyCFunction)ExpTable_copy, METH_O, "Copy data from table given in argument."}, {"setTable", (PyCFunction)ExpTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)ExpTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)ExpTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)ExpTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"setData", (PyCFunction)ExpTable_setData, METH_O, "Sets the table from samples in a text file."}, {"setSize", (PyCFunction)ExpTable_setSize, METH_O, "Sets the size of the table in samples"}, {"getSize", (PyCFunction)ExpTable_getSize, METH_NOARGS, "Return the size of the table in samples"}, {"put", (PyCFunction)ExpTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)ExpTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"getPoints", (PyCFunction)ExpTable_getPoints, METH_NOARGS, "Return the list of points."}, {"setExp", (PyCFunction)ExpTable_setExp, METH_O, "Sets the exponent factor."}, {"setInverse", (PyCFunction)ExpTable_setInverse, METH_O, "Sets the inverse factor."}, {"replace", (PyCFunction)ExpTable_replace, METH_O, "Sets the harmonics amplitude list and generates a new waveform table."}, {"normalize", (PyCFunction)ExpTable_normalize, METH_NOARGS, "Normalize table between -1 and 1."}, {"reset", (PyCFunction)ExpTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)ExpTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)ExpTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)ExpTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)ExpTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)ExpTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)ExpTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)ExpTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)ExpTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)ExpTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"add", (PyCFunction)ExpTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)ExpTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)ExpTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject ExpTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.ExpTable_base", /*tp_name*/ sizeof(ExpTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)ExpTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "ExpTable objects. Generates a table filled with one or more straight lines.", /* tp_doc */ (traverseproc)ExpTable_traverse, /* tp_traverse */ (inquiry)ExpTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ ExpTable_methods, /* tp_methods */ ExpTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ ExpTable_new, /* tp_new */ }; /***********************/ /* SndTable structure */ /***********************/ typedef struct { pyo_table_HEAD char *path; int sndSr; int chnl; MYFLT sr; MYFLT start; MYFLT stop; MYFLT crossfade; MYFLT insertPos; } SndTable; static void SndTable_loadSound(SndTable *self) { SNDFILE *sf; SF_INFO info; unsigned int i, num, num_items, num_chnls, snd_size, start, stop; unsigned int num_count = 0; MYFLT *tmp; info.format = 0; sf = sf_open(self->path, SFM_READ, &info); if (sf == NULL) { printf("SndTable failed to open the file.\n"); return; } snd_size = info.frames; self->sndSr = info.samplerate; num_chnls = info.channels; if (self->stop <= 0 || self->stop <= self->start || (self->stop*self->sndSr) > snd_size) stop = snd_size; else stop = (unsigned int)(self->stop * self->sndSr); if (self->start < 0 || (self->start*self->sndSr) > snd_size) start = 0; else start = (unsigned int)(self->start * self->sndSr); self->size = stop - start; num_items = self->size * num_chnls; /* Allocate space for the data to be read, then read it. */ self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT)); /* For sound longer than 1 minute, load 30 sec chunks. */ if (self->size > (self->sndSr * 60 * num_chnls)) { tmp = (MYFLT *)malloc(self->sndSr * 30 * num_chnls * sizeof(MYFLT)); sf_seek(sf, start, SEEK_SET); num_items = self->sndSr * 30 * num_chnls; do { num = SF_READ(sf, tmp, num_items); for (i=0; ichnl) { self->data[(int)(num_count++)] = tmp[i]; } } } while (num == num_items); sf_close(sf); } /* For sound shorter than 1 minute, load sound in one pass. */ else { tmp = (MYFLT *)malloc(num_items * sizeof(MYFLT)); sf_seek(sf, start, SEEK_SET); num = SF_READ(sf, tmp, num_items); sf_close(sf); for (i=0; ichnl) { self->data[(int)(i/num_chnls)] = tmp[i]; } } } self->data[self->size] = self->data[0]; self->start = 0.0; self->stop = -1.0; free(tmp); TableStream_setSize(self->tablestream, self->size); TableStream_setSamplingRate(self->tablestream, self->sndSr); TableStream_setData(self->tablestream, self->data); } static void SndTable_appendSound(SndTable *self) { SNDFILE *sf; SF_INFO info; unsigned int i, num_items, num_chnls, snd_size, start, stop, to_load_size, cross_in_samps, cross_point, index, real_index; MYFLT *tmp, *tmp_data; MYFLT cross_amp; info.format = 0; sf = sf_open(self->path, SFM_READ, &info); if (sf == NULL) { printf("SndTable failed to open the file.\n"); return; } snd_size = info.frames; self->sndSr = info.samplerate; num_chnls = info.channels; if (self->stop <= 0 || self->stop <= self->start || (self->stop*self->sndSr) > snd_size) stop = snd_size; else stop = (unsigned int)(self->stop * self->sndSr); if (self->start < 0 || (self->start*self->sndSr) > snd_size) start = 0; else start = (unsigned int)(self->start * self->sndSr); to_load_size = stop - start; num_items = to_load_size * num_chnls; cross_in_samps = (unsigned int)(self->crossfade * self->sr); if (cross_in_samps >= to_load_size) cross_in_samps = to_load_size - 1; if (cross_in_samps >= self->size) cross_in_samps = self->size - 1; /* Allocate space for the data to be read, then read it. */ tmp = (MYFLT *)malloc(num_items * sizeof(MYFLT)); tmp_data = (MYFLT *)malloc(self->size * sizeof(MYFLT)); sf_seek(sf, start, SEEK_SET); SF_READ(sf, tmp, num_items); sf_close(sf); if (cross_in_samps != 0) { for (i=0; isize; i++) { tmp_data[i] = self->data[i]; } } cross_point = self->size - cross_in_samps; self->size = self->size + to_load_size - cross_in_samps; self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT)); if (cross_in_samps != 0) { for (i=0; idata[i] = tmp_data[i]; } } if (self->crossfade == 0.0) { for (i=0; ichnl) { index = (int)(i/num_chnls); real_index = cross_point + index; self->data[real_index] = tmp[i]; } } } else { for (i=0; ichnl) { index = (int)(i/num_chnls); real_index = cross_point + index; if (index < cross_in_samps) { cross_amp = MYSQRT(index / (MYFLT)cross_in_samps); self->data[real_index] = tmp[i] * cross_amp + tmp_data[real_index] * (1. - cross_amp); } else self->data[real_index] = tmp[i]; } } } self->data[self->size] = self->data[0]; self->start = 0.0; self->stop = -1.0; free(tmp); free(tmp_data); TableStream_setSize(self->tablestream, self->size); TableStream_setSamplingRate(self->tablestream, self->sndSr); TableStream_setData(self->tablestream, self->data); } static void SndTable_prependSound(SndTable *self) { SNDFILE *sf; SF_INFO info; unsigned int i, num_items, num_chnls, snd_size, start, stop, to_load_size, cross_in_samps, cross_point; unsigned int index = 0; MYFLT *tmp, *tmp_data; MYFLT cross_amp; info.format = 0; sf = sf_open(self->path, SFM_READ, &info); if (sf == NULL) { printf("SndTable failed to open the file.\n"); return; } snd_size = info.frames; self->sndSr = info.samplerate; num_chnls = info.channels; if (self->stop <= 0 || self->stop <= self->start || (self->stop*self->sndSr) > snd_size) stop = snd_size; else stop = (unsigned int)(self->stop * self->sndSr); if (self->start < 0 || (self->start*self->sndSr) > snd_size) start = 0; else start = (unsigned int)(self->start * self->sndSr); to_load_size = stop - start; num_items = to_load_size * num_chnls; cross_in_samps = (unsigned int)(self->crossfade * self->sr); if (cross_in_samps >= to_load_size) cross_in_samps = to_load_size - 1; if (cross_in_samps >= self->size) cross_in_samps = self->size - 1; /* Allocate space for the data to be read, then read it. */ tmp = (MYFLT *)malloc(num_items * sizeof(MYFLT)); tmp_data = (MYFLT *)malloc(self->size * sizeof(MYFLT)); sf_seek(sf, start, SEEK_SET); SF_READ(sf, tmp, num_items); sf_close(sf); for (i=0; isize; i++) { tmp_data[i] = self->data[i]; } cross_point = to_load_size - cross_in_samps; self->size = self->size + to_load_size - cross_in_samps; self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT)); if (self->crossfade == 0.0) { for (i=0; ichnl) { index = (int)(i/num_chnls); self->data[index] = tmp[i]; } } } else { for (i=0; ichnl) { index = (int)(i/num_chnls); if (index >= cross_point) { cross_amp = MYSQRT((index-cross_point) / (MYFLT)cross_in_samps); self->data[index] = tmp[i] * (1. - cross_amp) + tmp_data[index - cross_point] * cross_amp; } else self->data[index] = tmp[i]; } } } for (i=(index+1); isize; i++) { self->data[i] = tmp_data[i - cross_point]; } self->data[self->size] = self->data[0]; self->start = 0.0; self->stop = -1.0; free(tmp); free(tmp_data); TableStream_setSize(self->tablestream, self->size); TableStream_setSamplingRate(self->tablestream, self->sndSr); TableStream_setData(self->tablestream, self->data); } static void SndTable_insertSound(SndTable *self) { SNDFILE *sf; SF_INFO info; unsigned int i, num_items, num_chnls, snd_size, start, stop, to_load_size; unsigned int cross_in_samps, cross_point, insert_point, index; unsigned int read_point = 0; unsigned int real_index = 0; MYFLT *tmp, *tmp_data; MYFLT cross_amp; info.format = 0; sf = sf_open(self->path, SFM_READ, &info); if (sf == NULL) { printf("SndTable failed to open the file.\n"); return; } snd_size = info.frames; self->sndSr = info.samplerate; num_chnls = info.channels; if (self->stop <= 0 || self->stop <= self->start || (self->stop*self->sndSr) > snd_size) stop = snd_size; else stop = (unsigned int)(self->stop * self->sndSr); if (self->start < 0 || (self->start*self->sndSr) > snd_size) start = 0; else start = (unsigned int)(self->start * self->sndSr); to_load_size = stop - start; num_items = to_load_size * num_chnls; insert_point = (unsigned int)(self->insertPos * self->sr); if (insert_point >= self->size) insert_point = self->size - 1; cross_in_samps = (unsigned int)(self->crossfade * self->sr); if (cross_in_samps >= (to_load_size/2)) cross_in_samps = (to_load_size/2) - 5; if (cross_in_samps >= insert_point) cross_in_samps = insert_point - 5; if (cross_in_samps >= (self->size - insert_point)) cross_in_samps = (self->size - insert_point) - 5; /* Allocate space for the data to be read, then read it. */ tmp = (MYFLT *)malloc(num_items * sizeof(MYFLT)); tmp_data = (MYFLT *)malloc(self->size * sizeof(MYFLT)); sf_seek(sf, start, SEEK_SET); SF_READ(sf, tmp, num_items); sf_close(sf); for (i=0; isize; i++) { tmp_data[i] = self->data[i]; } self->size = self->size + to_load_size - (cross_in_samps * 2); self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT)); cross_point = insert_point - cross_in_samps; for (i=0; idata[i] = tmp_data[i]; } if (self->crossfade == 0.0) { for (i=0; ichnl) { index = (int)(i/num_chnls); self->data[index+cross_point] = tmp[i]; } } } else { for (i=0; ichnl) { index = (int)(i/num_chnls); real_index = index + cross_point; if (index <= cross_in_samps) { cross_amp = MYSQRT(index / (MYFLT)cross_in_samps); self->data[real_index] = tmp[i] * cross_amp + tmp_data[cross_point + index] * (1.0 - cross_amp); } else if (index >= (to_load_size - cross_in_samps)) { cross_amp = MYSQRT((to_load_size - index) / (MYFLT)cross_in_samps); read_point = cross_in_samps - (to_load_size - index) +insert_point; self->data[real_index] = tmp[i] * cross_amp + tmp_data[read_point] * (1.0 - cross_amp); } else self->data[real_index] = tmp[i]; } } } read_point++; for (i=(real_index+1); isize; i++) { self->data[i] = tmp_data[read_point]; read_point++; } self->data[self->size] = self->data[0]; self->start = 0.0; self->stop = -1.0; free(tmp); free(tmp_data); TableStream_setSize(self->tablestream, self->size); TableStream_setSamplingRate(self->tablestream, self->sndSr); TableStream_setData(self->tablestream, self->data); } static int SndTable_traverse(SndTable *self, visitproc visit, void *arg) { pyo_table_VISIT return 0; } static int SndTable_clear(SndTable *self) { pyo_table_CLEAR return 0; } static void SndTable_dealloc(SndTable* self) { free(self->data); SndTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SndTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; SndTable *self; self = (SndTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->sr = (MYFLT)PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); self->chnl = 0; self->stop = -1.0; self->crossfade = 0.0; self->insertPos = 0.0; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"path", "chnl", "start", "stop", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_S_IFF, kwlist, &self->path, &self->chnl, &self->start, &self->stop)) return PyInt_FromLong(-1); if (strcmp(self->path, "") == 0) { self->size = (int)self->sr; self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT)); for (i=0; isize; i++) { self->data[i] = 0.0; } self->data[self->size] = self->data[0]; self->start = 0.0; self->stop = -1.0; self->sndSr = (int)self->sr; TableStream_setSize(self->tablestream, self->size); TableStream_setSamplingRate(self->tablestream, (int)self->sr); TableStream_setData(self->tablestream, self->data); } else { SndTable_loadSound(self); } return (PyObject *)self; } static PyObject * SndTable_getServer(SndTable* self) { GET_SERVER }; static PyObject * SndTable_getTableStream(SndTable* self) { GET_TABLE_STREAM }; static PyObject * SndTable_setData(SndTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * SndTable_normalize(SndTable *self) { NORMALIZE }; static PyObject * SndTable_reset(SndTable *self) { TABLE_RESET }; static PyObject * SndTable_removeDC(SndTable *self) { REMOVE_DC }; static PyObject * SndTable_reverse(SndTable *self) { REVERSE }; static PyObject * SndTable_invert(SndTable *self) { INVERT }; static PyObject * SndTable_rectify(SndTable *self) { RECTIFY }; static PyObject * SndTable_bipolarGain(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * SndTable_lowpass(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * SndTable_fadein(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * SndTable_fadeout(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * SndTable_pow(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * SndTable_copy(SndTable *self, PyObject *arg) { COPY }; static PyObject * SndTable_setTable(SndTable *self, PyObject *arg) { SET_TABLE }; static PyObject * SndTable_getTable(SndTable *self) { GET_TABLE }; static PyObject * SndTable_put(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * SndTable_get(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * SndTable_add(SndTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * SndTable_sub(SndTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * SndTable_mul(SndTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * SndTable_getViewTable(SndTable *self, PyObject *args, PyObject *kwds) { int i, j, y, w, h, h2, step, size; int count = 0; int yOffset = 0; MYFLT absin, fstep; MYFLT begin = 0.0; MYFLT end = -1.0; PyObject *samples, *tuple; PyObject *sizetmp = NULL; static char *kwlist[] = {"size", "begin", "end", "yOffset", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__OFFI, kwlist, &sizetmp, &begin, &end, &yOffset)) return PyInt_FromLong(-1); if (end <= 0.0) end = self->size; else { end = end * self->sr; if (end > self->size) end = self->size; } if (begin < 0.0) begin = 0; else { begin = begin * self->sr; if (begin >= end) begin = 0; } size = (int)(end - begin); if (sizetmp) { if (PyTuple_Check(sizetmp)) { w = PyInt_AsLong(PyTuple_GET_ITEM(sizetmp, 0)); h = PyInt_AsLong(PyTuple_GET_ITEM(sizetmp, 1)); } else if (PyList_Check(sizetmp)) { w = PyInt_AsLong(PyList_GET_ITEM(sizetmp, 0)); h = PyInt_AsLong(PyList_GET_ITEM(sizetmp, 1)); } else { w = 500; h = 200; } } else { w = 500; h = 200; } h2 = h/2; step = (int)(size / (MYFLT)(w)); fstep = (MYFLT)(w) / (size-1); if (step == 0) { samples = PyList_New(size); for (i=0; idata[i+(int)(begin)]*h2+h2+yOffset)); PyList_SetItem(samples, i, tuple); } } else if (step < 32) { samples = PyList_New(w); for(i=0; idata[(int)(begin)+count]; count++; } y = (int)(absin / step * h2); tuple = PyTuple_New(2); PyTuple_SetItem(tuple, 0, PyInt_FromLong(i)); PyTuple_SetItem(tuple, 1, PyInt_FromLong(h2+y+yOffset)); PyList_SetItem(samples, i, tuple); } } else { samples = PyList_New(w*2); for(i=0; idata[(int)(begin)+count]) > absin) absin = -self->data[(int)(begin)+count]; count++; } y = (int)(absin * h2); tuple = PyTuple_New(2); PyTuple_SetItem(tuple, 0, PyInt_FromLong(i)); PyTuple_SetItem(tuple, 1, PyInt_FromLong(h2-y+yOffset)); PyList_SetItem(samples, i*2, tuple); tuple = PyTuple_New(2); PyTuple_SetItem(tuple, 0, PyInt_FromLong(i)); PyTuple_SetItem(tuple, 1, PyInt_FromLong(h2+y+yOffset)); PyList_SetItem(samples, i*2+1, tuple); } } return samples; }; static PyObject * SndTable_getEnvelope(SndTable *self, PyObject *arg) { int i, j, step, points; long count; MYFLT absin, last; PyObject *samples; ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt) { count = 0; points = PyInt_AsLong(arg); step = self->size / points; samples = PyList_New(points); for(i=0; idata[count++]) > absin) absin = self->data[count]; } last = (absin + last) * 0.5; PyList_SetItem(samples, i, PyFloat_FromDouble(last)); } return samples; } else { Py_INCREF(Py_None); return Py_None; } }; static PyObject * SndTable_setSound(SndTable *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"path", "chnl", "start", "stop", NULL}; MYFLT stoptmp = -1.0; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_S_IFF, kwlist, &self->path, &self->chnl, &self->start, &stoptmp)) { Py_INCREF(Py_None); return Py_None; } self->stop = stoptmp; SndTable_loadSound(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SndTable_append(SndTable *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"path", "crossfade", "chnl", "start", "stop", NULL}; MYFLT stoptmp = -1.0; MYFLT crosstmp = 0.0; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_S_FIFF, kwlist, &self->path, &crosstmp, &self->chnl, &self->start, &stoptmp)) { Py_INCREF(Py_None); return Py_None; } self->stop = stoptmp; if (crosstmp < 0.0) self->crossfade = 0.0; else self->crossfade = crosstmp; SndTable_appendSound(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SndTable_insert(SndTable *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"path", "pos", "crossfade", "chnl", "start", "stop", NULL}; MYFLT stoptmp = -1.0; MYFLT crosstmp = 0.0; MYFLT postmp = 0.0; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_S_FFIFF, kwlist, &self->path, &postmp, &crosstmp, &self->chnl, &self->start, &stoptmp)) { Py_INCREF(Py_None); return Py_None; } self->stop = stoptmp; if (crosstmp < 0.0) self->crossfade = 0.0; else self->crossfade = crosstmp; if (postmp <= 0.0) SndTable_prependSound(self); else if (postmp >= ((self->size-1) / self->sndSr)) SndTable_appendSound(self); else { self->insertPos = postmp; SndTable_insertSound(self); } Py_INCREF(Py_None); return Py_None; } static PyObject * SndTable_setSize(SndTable *self, PyObject *value) { Py_ssize_t i; self->size = PyInt_AsLong(value); self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); for(i=0; isize; i++) { self->data[i] = 0.0; } self->data[self->size] = 0.0; self->start = 0.0; self->stop = -1.0; TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); Py_INCREF(Py_None); return Py_None; } static PyObject * SndTable_getSize(SndTable *self) { return PyInt_FromLong(self->size); }; static PyObject * SndTable_getRate(SndTable *self) { MYFLT sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); \ return PyFloat_FromDouble(sr * (self->sndSr/sr) / self->size); }; static PyMemberDef SndTable_members[] = { {"server", T_OBJECT_EX, offsetof(SndTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(SndTable, tablestream), 0, "Table stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef SndTable_methods[] = { {"getServer", (PyCFunction)SndTable_getServer, METH_NOARGS, "Returns server object."}, {"copy", (PyCFunction)SndTable_copy, METH_O, "Copy data from table given in argument."}, {"setTable", (PyCFunction)SndTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)SndTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)SndTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)SndTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"getEnvelope", (PyCFunction)SndTable_getEnvelope, METH_O, "Returns X points envelope follower of the table."}, {"setData", (PyCFunction)SndTable_setData, METH_O, "Sets the table from samples in a text file."}, {"normalize", (PyCFunction)SndTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"reset", (PyCFunction)SndTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)SndTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)SndTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)SndTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)SndTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)SndTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)SndTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)SndTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)SndTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)SndTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"put", (PyCFunction)SndTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)SndTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"setSound", (PyCFunction)SndTable_setSound, METH_VARARGS|METH_KEYWORDS, "Load a new sound in the table."}, {"append", (PyCFunction)SndTable_append, METH_VARARGS|METH_KEYWORDS, "Append a sound in the table."}, {"insert", (PyCFunction)SndTable_insert, METH_VARARGS|METH_KEYWORDS, "Insert a sound in the table."}, {"setSize", (PyCFunction)SndTable_setSize, METH_O, "Sets the size of the table in samples"}, {"getSize", (PyCFunction)SndTable_getSize, METH_NOARGS, "Return the size of the table in samples."}, {"getRate", (PyCFunction)SndTable_getRate, METH_NOARGS, "Return the frequency (in cps) that reads the sound without pitch transposition."}, {"add", (PyCFunction)SndTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)SndTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)SndTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject SndTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SndTable_base", /*tp_name*/ sizeof(SndTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SndTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "SndTable objects. Generates a table filled with a soundfile.", /* tp_doc */ (traverseproc)SndTable_traverse, /* tp_traverse */ (inquiry)SndTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SndTable_methods, /* tp_methods */ SndTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SndTable_new, /* tp_new */ 0, /* tp_free */ 0, /* tp_is_gc */ 0, /* tp_bases */ 0, /* tp_mro */ 0, /* tp_cache */ 0, /* tp_subclasses */ 0, /* tp_weaklist */ 0, /* tp_del */ }; /***********************/ /* NewTable structure */ /***********************/ typedef struct { pyo_table_HEAD MYFLT length; MYFLT feedback; MYFLT sr; int pointer; } NewTable; static PyObject * NewTable_recordChunk(NewTable *self, MYFLT *data, int datasize) { int i; if (self->feedback == 0.0) { for (i=0; idata[self->pointer++] = data[i]; if (self->pointer == self->size) { self->pointer = 0; self->data[self->size] = self->data[0]; } } } else { for (i=0; idata[self->pointer] = data[i] + self->data[self->pointer] * self->feedback; self->pointer++; if (self->pointer == self->size) { self->pointer = 0; self->data[self->size] = self->data[0]; } } } Py_INCREF(Py_None); return Py_None; } static int NewTable_traverse(NewTable *self, visitproc visit, void *arg) { pyo_table_VISIT return 0; } static int NewTable_clear(NewTable *self) { pyo_table_CLEAR return 0; } static void NewTable_dealloc(NewTable* self) { free(self->data); NewTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * NewTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inittmp=NULL; NewTable *self; self = (NewTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->pointer = 0; self->feedback = 0.0; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"length", "init", "feedback", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F_OF, kwlist, &self->length, &inittmp, &self->feedback)) Py_RETURN_NONE; self->sr = (MYFLT)PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); self->size = (int)(self->length * self->sr + 0.5); self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT)); for (i=0; i<(self->size+1); i++) { self->data[i] = 0.; } TableStream_setSize(self->tablestream, self->size); if (inittmp && inittmp != Py_None) { PyObject_CallMethod((PyObject *)self, "setTable", "O", inittmp); } TableStream_setData(self->tablestream, self->data); TableStream_setSamplingRate(self->tablestream, self->sr); return (PyObject *)self; } static PyObject * NewTable_getServer(NewTable* self) { GET_SERVER }; static PyObject * NewTable_getTableStream(NewTable* self) { GET_TABLE_STREAM }; static PyObject * NewTable_setData(NewTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * NewTable_normalize(NewTable *self) { NORMALIZE }; static PyObject * NewTable_reset(NewTable *self) { TABLE_RESET }; static PyObject * NewTable_removeDC(NewTable *self) { REMOVE_DC }; static PyObject * NewTable_reverse(NewTable *self) { REVERSE }; static PyObject * NewTable_invert(NewTable *self) { INVERT }; static PyObject * NewTable_rectify(NewTable *self) { RECTIFY }; static PyObject * NewTable_bipolarGain(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * NewTable_lowpass(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * NewTable_fadein(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * NewTable_fadeout(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * NewTable_pow(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * NewTable_copy(NewTable *self, PyObject *arg) { COPY }; static PyObject * NewTable_setTable(NewTable *self, PyObject *arg) { SET_TABLE }; static PyObject * NewTable_getTable(NewTable *self) { GET_TABLE }; static PyObject * NewTable_put(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * NewTable_get(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * NewTable_add(NewTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * NewTable_sub(NewTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * NewTable_mul(NewTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * NewTable_getViewTable(NewTable *self, PyObject *args, PyObject *kwds) { int i, j, y, w, h, h2, step, size; int count = 0; int yOffset = 0; MYFLT absin, fstep; MYFLT begin = 0.0; MYFLT end = -1.0; PyObject *samples, *tuple; PyObject *sizetmp = NULL; static char *kwlist[] = {"size", "begin", "end", "yOffset", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__OFFI, kwlist, &sizetmp, &begin, &end, &yOffset)) return PyInt_FromLong(-1); if (end <= 0.0) end = self->size; else { end = end * self->sr; if (end > self->size) end = self->size; } if (begin < 0.0) begin = 0; else { begin = begin * self->sr; if (begin >= end) begin = 0; } size = (int)(end - begin); if (sizetmp) { if (PyTuple_Check(sizetmp)) { w = PyInt_AsLong(PyTuple_GET_ITEM(sizetmp, 0)); h = PyInt_AsLong(PyTuple_GET_ITEM(sizetmp, 1)); } else if (PyList_Check(sizetmp)) { w = PyInt_AsLong(PyList_GET_ITEM(sizetmp, 0)); h = PyInt_AsLong(PyList_GET_ITEM(sizetmp, 1)); } else { w = 500; h = 200; } } else { w = 500; h = 200; } h2 = h/2; step = (int)(size / (MYFLT)(w)); fstep = (MYFLT)(w) / (size-1); if (step == 0) { samples = PyList_New(size); for (i=0; idata[i+(int)(begin)]*h2+h2+yOffset)); PyList_SetItem(samples, i, tuple); } } else if (step < 32) { samples = PyList_New(w); for(i=0; idata[(int)(begin)+count]; count++; } y = (int)(absin / step * h2); tuple = PyTuple_New(2); PyTuple_SetItem(tuple, 0, PyInt_FromLong(i)); PyTuple_SetItem(tuple, 1, PyInt_FromLong(h2+y+yOffset)); PyList_SetItem(samples, i, tuple); } } else { samples = PyList_New(w*2); for(i=0; idata[(int)(begin)+count]) > absin) absin = -self->data[(int)(begin)+count]; count++; } y = (int)(absin * h2); tuple = PyTuple_New(2); PyTuple_SetItem(tuple, 0, PyInt_FromLong(i)); PyTuple_SetItem(tuple, 1, PyInt_FromLong(h2-y+yOffset)); PyList_SetItem(samples, i*2, tuple); tuple = PyTuple_New(2); PyTuple_SetItem(tuple, 0, PyInt_FromLong(i)); PyTuple_SetItem(tuple, 1, PyInt_FromLong(h2+y+yOffset)); PyList_SetItem(samples, i*2+1, tuple); } } return samples; }; static PyObject * NewTable_getSize(NewTable *self) { return PyInt_FromLong(self->size); }; static PyObject * NewTable_getLength(NewTable *self) { return PyFloat_FromDouble(self->length); }; static PyObject * NewTable_getRate(NewTable *self) { MYFLT sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); \ return PyFloat_FromDouble(sr / self->size); }; static PyObject * NewTable_setFeedback(NewTable *self, PyObject *value) { MYFLT feed; if (PyNumber_Check(value)) { feed = PyFloat_AsDouble(value); if (feed < -1.0) feed = -1.0; else if (feed > 1.0) feed = 1.0; self->feedback = feed; } Py_RETURN_NONE; } static PyMemberDef NewTable_members[] = { {"server", T_OBJECT_EX, offsetof(NewTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(NewTable, tablestream), 0, "Table stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef NewTable_methods[] = { {"getServer", (PyCFunction)NewTable_getServer, METH_NOARGS, "Returns server object."}, {"setTable", (PyCFunction)NewTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)NewTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)NewTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)NewTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"setFeedback", (PyCFunction)NewTable_setFeedback, METH_O, "Feedback sets the amount of old data to mix with a new recording."}, {"setData", (PyCFunction)NewTable_setData, METH_O, "Sets the table from samples in a text file."}, {"copy", (PyCFunction)NewTable_copy, METH_O, "Copy data from table given in argument."}, {"normalize", (PyCFunction)NewTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"reset", (PyCFunction)NewTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)NewTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)NewTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)NewTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)NewTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)NewTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)NewTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)NewTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)NewTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)NewTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"put", (PyCFunction)NewTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)NewTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"getSize", (PyCFunction)NewTable_getSize, METH_NOARGS, "Return the size of the table in samples."}, {"getLength", (PyCFunction)NewTable_getLength, METH_NOARGS, "Return the length of the table in seconds."}, {"getRate", (PyCFunction)NewTable_getRate, METH_NOARGS, "Return the frequency (in cps) that reads the sound without pitch transposition."}, {"add", (PyCFunction)NewTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)NewTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)NewTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject NewTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.NewTable_base", /*tp_name*/ sizeof(NewTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)NewTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "NewTable objects. Generates an empty table.", /* tp_doc */ (traverseproc)NewTable_traverse, /* tp_traverse */ (inquiry)NewTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ NewTable_methods, /* tp_methods */ NewTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ NewTable_new, /* tp_new */ }; /***********************/ /* DataTable structure */ /***********************/ typedef struct { pyo_table_HEAD int pointer; } DataTable; static void DataTable_record(DataTable *self, int pos, MYFLT value) { self->data[pos] = value; } static int DataTable_traverse(DataTable *self, visitproc visit, void *arg) { pyo_table_VISIT return 0; } static int DataTable_clear(DataTable *self) { pyo_table_CLEAR return 0; } static void DataTable_dealloc(DataTable* self) { free(self->data); DataTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * DataTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inittmp=NULL; DataTable *self; self = (DataTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->pointer = 0; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"size", "init", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "i|O", kwlist, &self->size, &inittmp)) Py_RETURN_NONE; self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT)); for (i=0; i<(self->size+1); i++) { self->data[i] = 0.; } TableStream_setSize(self->tablestream, self->size); if (inittmp) { PyObject_CallMethod((PyObject *)self, "setTable", "O", inittmp); } TableStream_setData(self->tablestream, self->data); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * DataTable_getServer(DataTable* self) { GET_SERVER }; static PyObject * DataTable_getTableStream(DataTable* self) { GET_TABLE_STREAM }; static PyObject * DataTable_setData(DataTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * DataTable_normalize(DataTable *self) { NORMALIZE }; static PyObject * DataTable_reset(DataTable *self) { TABLE_RESET }; static PyObject * DataTable_removeDC(DataTable *self) { REMOVE_DC }; static PyObject * DataTable_reverse(DataTable *self) { REVERSE }; static PyObject * DataTable_invert(DataTable *self) { INVERT }; static PyObject * DataTable_rectify(DataTable *self) { RECTIFY }; static PyObject * DataTable_bipolarGain(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * DataTable_lowpass(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * DataTable_fadein(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * DataTable_fadeout(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * DataTable_pow(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * DataTable_copy(DataTable *self, PyObject *arg) { COPY }; static PyObject * DataTable_setTable(DataTable *self, PyObject *arg) { SET_TABLE }; static PyObject * DataTable_getTable(DataTable *self) { GET_TABLE }; static PyObject * DataTable_getViewTable(DataTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * DataTable_put(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * DataTable_get(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * DataTable_add(DataTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * DataTable_sub(DataTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * DataTable_mul(DataTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * DataTable_getSize(DataTable *self) { return PyInt_FromLong(self->size); }; static PyObject * DataTable_getRate(DataTable *self) { MYFLT sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); \ return PyFloat_FromDouble(sr / self->size); }; static PyMemberDef DataTable_members[] = { {"server", T_OBJECT_EX, offsetof(DataTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(DataTable, tablestream), 0, "Table stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef DataTable_methods[] = { {"getServer", (PyCFunction)DataTable_getServer, METH_NOARGS, "Returns server object."}, {"copy", (PyCFunction)DataTable_copy, METH_O, "Copy data from table given in argument."}, {"setTable", (PyCFunction)DataTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)DataTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)DataTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)DataTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"setData", (PyCFunction)DataTable_setData, METH_O, "Sets the table from samples in a text file."}, {"normalize", (PyCFunction)DataTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"reset", (PyCFunction)DataTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)DataTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)DataTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)DataTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)DataTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)DataTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)DataTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)DataTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)DataTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)DataTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"put", (PyCFunction)DataTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)DataTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"getSize", (PyCFunction)DataTable_getSize, METH_NOARGS, "Return the size of the table in samples."}, {"getRate", (PyCFunction)DataTable_getRate, METH_NOARGS, "Return the frequency (in cps) that reads the sound without pitch transposition."}, {"add", (PyCFunction)DataTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)DataTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)DataTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject DataTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.DataTable_base", /*tp_name*/ sizeof(DataTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)DataTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "DataTable objects. Generates an empty table.", /* tp_doc */ (traverseproc)DataTable_traverse, /* tp_traverse */ (inquiry)DataTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ DataTable_methods, /* tp_methods */ DataTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ DataTable_new, /* tp_new */ }; /***********************/ /* AtanTable structure */ /***********************/ typedef struct { pyo_table_HEAD MYFLT slope; } AtanTable; static void AtanTable_generate(AtanTable *self) { int i, hsize; MYFLT drv, invhsize, val, t, fac = 0; hsize = self->size / 2; invhsize = 1.0 / hsize; drv = 1 - self->slope; drv = drv * drv * drv * PI; for(i=0; i<=hsize; i++) { t = i * invhsize - 1; val = MYATAN2(t, drv); if (i == 0) fac = 1.0 / -val; val = val * fac; self->data[i] = val; self->data[self->size - i] = -val; } } static int AtanTable_traverse(AtanTable *self, visitproc visit, void *arg) { pyo_table_VISIT return 0; } static int AtanTable_clear(AtanTable *self) { pyo_table_CLEAR return 0; } static void AtanTable_dealloc(AtanTable* self) { free(self->data); AtanTable_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * AtanTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { AtanTable *self; self = (AtanTable *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->size = 8192; self->slope = 0.5; MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL); static char *kwlist[] = {"slope", "size", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F_I, kwlist, &self->slope, &self->size)) Py_RETURN_NONE; self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); TableStream_setData(self->tablestream, self->data); AtanTable_generate(self); double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); TableStream_setSamplingRate(self->tablestream, sr); return (PyObject *)self; } static PyObject * AtanTable_getServer(AtanTable* self) { GET_SERVER }; static PyObject * AtanTable_getTableStream(AtanTable* self) { GET_TABLE_STREAM }; static PyObject * AtanTable_setData(AtanTable *self, PyObject *arg) { SET_TABLE_DATA }; static PyObject * AtanTable_normalize(AtanTable *self) { NORMALIZE }; static PyObject * AtanTable_reset(AtanTable *self) { TABLE_RESET }; static PyObject * AtanTable_removeDC(AtanTable *self) { REMOVE_DC }; static PyObject * AtanTable_reverse(AtanTable *self) { REVERSE }; static PyObject * AtanTable_invert(AtanTable *self) { INVERT }; static PyObject * AtanTable_rectify(AtanTable *self) { RECTIFY }; static PyObject * AtanTable_bipolarGain(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN }; static PyObject * AtanTable_lowpass(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS }; static PyObject * AtanTable_fadein(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN }; static PyObject * AtanTable_fadeout(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT }; static PyObject * AtanTable_pow(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER }; static PyObject * AtanTable_copy(AtanTable *self, PyObject *arg) { COPY }; static PyObject * AtanTable_setTable(AtanTable *self, PyObject *arg) { SET_TABLE }; static PyObject * AtanTable_getTable(AtanTable *self) { GET_TABLE }; static PyObject * AtanTable_getViewTable(AtanTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE }; static PyObject * AtanTable_put(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT }; static PyObject * AtanTable_get(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_GET }; static PyObject * AtanTable_add(AtanTable *self, PyObject *arg) { TABLE_ADD }; static PyObject * AtanTable_sub(AtanTable *self, PyObject *arg) { TABLE_SUB }; static PyObject * AtanTable_mul(AtanTable *self, PyObject *arg) { TABLE_MUL }; static PyObject * AtanTable_setSlope(AtanTable *self, PyObject *value) { if (! PyNumber_Check(value)) { PyErr_SetString(PyExc_TypeError, "The slope attribute value must be a number."); return PyInt_FromLong(-1); } self->slope = PyFloat_AsDouble(value); if (self->slope < 0.0) self->slope = 0.0; else if (self->slope > 1.0) self->slope = 1.0; AtanTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * AtanTable_setSize(AtanTable *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute."); return PyInt_FromLong(-1); } if (! PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer."); return PyInt_FromLong(-1); } self->size = PyInt_AsLong(value); self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); TableStream_setSize(self->tablestream, self->size); AtanTable_generate(self); Py_INCREF(Py_None); return Py_None; } static PyObject * AtanTable_getSize(AtanTable *self) { return PyInt_FromLong(self->size); }; static PyMemberDef AtanTable_members[] = { {"server", T_OBJECT_EX, offsetof(AtanTable, server), 0, "Pyo server."}, {"tablestream", T_OBJECT_EX, offsetof(AtanTable, tablestream), 0, "Table stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef AtanTable_methods[] = { {"getServer", (PyCFunction)AtanTable_getServer, METH_NOARGS, "Returns server object."}, {"copy", (PyCFunction)AtanTable_copy, METH_O, "Copy data from table given in argument."}, {"setTable", (PyCFunction)AtanTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."}, {"getTable", (PyCFunction)AtanTable_getTable, METH_NOARGS, "Returns a list of table samples."}, {"getViewTable", (PyCFunction)AtanTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."}, {"getTableStream", (PyCFunction)AtanTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."}, {"setData", (PyCFunction)AtanTable_setData, METH_O, "Sets the table from samples in a text file."}, {"normalize", (PyCFunction)AtanTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"reset", (PyCFunction)AtanTable_reset, METH_NOARGS, "Resets table samples to 0.0"}, {"removeDC", (PyCFunction)AtanTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."}, {"reverse", (PyCFunction)AtanTable_reverse, METH_NOARGS, "Reverse the table's data."}, {"invert", (PyCFunction)AtanTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."}, {"rectify", (PyCFunction)AtanTable_rectify, METH_NOARGS, "Positive rectification of the table's data."}, {"bipolarGain", (PyCFunction)AtanTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."}, {"lowpass", (PyCFunction)AtanTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."}, {"fadein", (PyCFunction)AtanTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."}, {"fadeout", (PyCFunction)AtanTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."}, {"pow", (PyCFunction)AtanTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."}, {"setSize", (PyCFunction)AtanTable_setSize, METH_O, "Sets the size of the table in samples"}, {"getSize", (PyCFunction)AtanTable_getSize, METH_NOARGS, "Return the size of the table in samples"}, {"setSlope", (PyCFunction)AtanTable_setSlope, METH_O, "Sets the slope of the atan function."}, {"put", (PyCFunction)AtanTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."}, {"get", (PyCFunction)AtanTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."}, {"add", (PyCFunction)AtanTable_add, METH_O, "Performs table addition."}, {"sub", (PyCFunction)AtanTable_sub, METH_O, "Performs table substraction."}, {"mul", (PyCFunction)AtanTable_mul, METH_O, "Performs table multiplication."}, {NULL} /* Sentinel */ }; PyTypeObject AtanTableType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.AtanTable_base", /*tp_name*/ sizeof(AtanTable), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)AtanTable_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "AtanTable objects. Generates a table filled with a sinc function.", /* tp_doc */ (traverseproc)AtanTable_traverse, /* tp_traverse */ (inquiry)AtanTable_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ AtanTable_methods, /* tp_methods */ AtanTable_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ AtanTable_new, /* tp_new */ }; /******************************/ /* TableRec object definition */ /******************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; NewTable *table; int pointer; int active; MYFLT fadetime; MYFLT fadeInSample; MYFLT *trigsBuffer; TriggerStream *trig_stream; MYFLT *time_buffer_streams; MYFLT *buffer; } TableRec; static void TableRec_compute_next_data_frame(TableRec *self) { int i, num, upBound; MYFLT val; int size = PyInt_AsLong(NewTable_getSize((NewTable *)self->table)); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } if (!self->active) { for (i=0; ibufsize; i++) { self->time_buffer_streams[i] = self->pointer; } } if ((size - self->pointer) >= self->bufsize) num = self->bufsize; else { num = size - self->pointer; if (self->active == 1) { if (num <= 0) self->trigsBuffer[0] = 1.0; else self->trigsBuffer[num-1] = 1.0; self->active = 0; } } if (self->pointer < size) { upBound = (int)(size - self->fadeInSample); //MYFLT buffer[num]; //memset(&buffer, 0, sizeof(buffer)); for (i=0; ibufsize; i++) { self->buffer[i] = 0.0; } MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ipointer < self->fadeInSample) val = self->pointer / self->fadeInSample; else if (self->pointer >= upBound) val = (size - (self->pointer+1)) / self->fadeInSample; else val = 1.; self->buffer[i] = in[i] * val; self->time_buffer_streams[i] = self->pointer++; } NewTable_recordChunk((NewTable *)self->table, self->buffer, num); if (num < self->bufsize) { for (i=num; ibufsize; i++) { self->time_buffer_streams[i] = self->pointer; } } } } static MYFLT * TableRec_getTimeBuffer(TableRec *self) { return self->time_buffer_streams; } static int TableRec_traverse(TableRec *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->table); Py_VISIT(self->trig_stream); return 0; } static int TableRec_clear(TableRec *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->table); Py_CLEAR(self->trig_stream); return 0; } static void TableRec_dealloc(TableRec* self) { pyo_DEALLOC free(self->buffer); free(self->trigsBuffer); free(self->time_buffer_streams); TableRec_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TableRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *tabletmp; TableRec *self; self = (TableRec *)type->tp_alloc(type, 0); self->pointer = 0; self->active = 1; self->fadetime = 0.; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TableRec_compute_next_data_frame); Stream_setStreamActive(self->stream, 0); static char *kwlist[] = {"input", "table", "fadetime", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_F, kwlist, &inputtmp, &tabletmp, &self->fadetime)) Py_RETURN_NONE; INIT_INPUT_STREAM if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableRec must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); Py_INCREF(tabletmp); self->table = (NewTable *)tabletmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->buffer = (MYFLT *)realloc(self->buffer, self->bufsize * sizeof(MYFLT)); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); self->time_buffer_streams = (MYFLT *)realloc(self->time_buffer_streams, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->buffer[i] = self->trigsBuffer[i] = self->time_buffer_streams[i] = 0.0; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); int size = PyInt_AsLong(NewTable_getSize((NewTable *)self->table)); if ((self->fadetime * self->sr) >= (size * 0.5)) self->fadetime = size * 0.499 / self->sr; if (self->fadetime == 0.0) self->fadeInSample = 0.0; else self->fadeInSample = MYFLOOR(self->fadetime * self->sr); return (PyObject *)self; } static PyObject * TableRec_getServer(TableRec* self) { GET_SERVER }; static PyObject * TableRec_getStream(TableRec* self) { GET_STREAM }; static PyObject * TableRec_getTriggerStream(TableRec* self) { GET_TRIGGER_STREAM }; static PyObject * TableRec_play(TableRec *self, PyObject *args, PyObject *kwds) { self->pointer = 0; self->active = 1; PLAY }; static PyObject * TableRec_stop(TableRec *self) { STOP }; static PyObject * TableRec_setTable(TableRec *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_INCREF(tmp); Py_DECREF(self->table); self->table = (NewTable *)tmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef TableRec_members[] = { {"server", T_OBJECT_EX, offsetof(TableRec, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TableRec, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(TableRec, trig_stream), 0, "Trigger Stream object."}, {"input", T_OBJECT_EX, offsetof(TableRec, input), 0, "Input sound object."}, {"table", T_OBJECT_EX, offsetof(TableRec, table), 0, "Table to record in."}, {NULL} /* Sentinel */ }; static PyMethodDef TableRec_methods[] = { {"getServer", (PyCFunction)TableRec_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TableRec_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)TableRec_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"setTable", (PyCFunction)TableRec_setTable, METH_O, "Sets a new table."}, {"play", (PyCFunction)TableRec_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)TableRec_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject TableRecType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TableRec_base", /*tp_name*/ sizeof(TableRec), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TableRec_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TableRec objects. Record audio input in a table object.", /* tp_doc */ (traverseproc)TableRec_traverse, /* tp_traverse */ (inquiry)TableRec_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TableRec_methods, /* tp_methods */ TableRec_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TableRec_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD TableRec *mainPlayer; int modebuffer[2]; } TableRecTimeStream; static void TableRecTimeStream_postprocessing_ii(TableRecTimeStream *self) { POST_PROCESSING_II }; static void TableRecTimeStream_postprocessing_ai(TableRecTimeStream *self) { POST_PROCESSING_AI }; static void TableRecTimeStream_postprocessing_ia(TableRecTimeStream *self) { POST_PROCESSING_IA }; static void TableRecTimeStream_postprocessing_aa(TableRecTimeStream *self) { POST_PROCESSING_AA }; static void TableRecTimeStream_postprocessing_ireva(TableRecTimeStream *self) { POST_PROCESSING_IREVA }; static void TableRecTimeStream_postprocessing_areva(TableRecTimeStream *self) { POST_PROCESSING_AREVA }; static void TableRecTimeStream_postprocessing_revai(TableRecTimeStream *self) { POST_PROCESSING_REVAI }; static void TableRecTimeStream_postprocessing_revaa(TableRecTimeStream *self) { POST_PROCESSING_REVAA }; static void TableRecTimeStream_postprocessing_revareva(TableRecTimeStream *self) { POST_PROCESSING_REVAREVA }; static void TableRecTimeStream_setProcMode(TableRecTimeStream *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = TableRecTimeStream_postprocessing_ii; break; case 1: self->muladd_func_ptr = TableRecTimeStream_postprocessing_ai; break; case 2: self->muladd_func_ptr = TableRecTimeStream_postprocessing_revai; break; case 10: self->muladd_func_ptr = TableRecTimeStream_postprocessing_ia; break; case 11: self->muladd_func_ptr = TableRecTimeStream_postprocessing_aa; break; case 12: self->muladd_func_ptr = TableRecTimeStream_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TableRecTimeStream_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TableRecTimeStream_postprocessing_areva; break; case 22: self->muladd_func_ptr = TableRecTimeStream_postprocessing_revareva; break; } } static void TableRecTimeStream_compute_next_data_frame(TableRecTimeStream *self) { int i; MYFLT *tmp; tmp = TableRec_getTimeBuffer((TableRec *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i]; } (*self->muladd_func_ptr)(self); } static int TableRecTimeStream_traverse(TableRecTimeStream *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int TableRecTimeStream_clear(TableRecTimeStream *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void TableRecTimeStream_dealloc(TableRecTimeStream* self) { pyo_DEALLOC TableRecTimeStream_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TableRecTimeStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; TableRecTimeStream *self; self = (TableRecTimeStream *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TableRecTimeStream_compute_next_data_frame); self->mode_func_ptr = TableRecTimeStream_setProcMode; static char *kwlist[] = {"mainPlayer", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &maintmp)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (TableRec *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TableRecTimeStream_getServer(TableRecTimeStream* self) { GET_SERVER }; static PyObject * TableRecTimeStream_getStream(TableRecTimeStream* self) { GET_STREAM }; static PyObject * TableRecTimeStream_setMul(TableRecTimeStream *self, PyObject *arg) { SET_MUL }; static PyObject * TableRecTimeStream_setAdd(TableRecTimeStream *self, PyObject *arg) { SET_ADD }; static PyObject * TableRecTimeStream_setSub(TableRecTimeStream *self, PyObject *arg) { SET_SUB }; static PyObject * TableRecTimeStream_setDiv(TableRecTimeStream *self, PyObject *arg) { SET_DIV }; static PyObject * TableRecTimeStream_play(TableRecTimeStream *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TableRecTimeStream_out(TableRecTimeStream *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TableRecTimeStream_stop(TableRecTimeStream *self) { STOP }; static PyObject * TableRecTimeStream_multiply(TableRecTimeStream *self, PyObject *arg) { MULTIPLY }; static PyObject * TableRecTimeStream_inplace_multiply(TableRecTimeStream *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TableRecTimeStream_add(TableRecTimeStream *self, PyObject *arg) { ADD }; static PyObject * TableRecTimeStream_inplace_add(TableRecTimeStream *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TableRecTimeStream_sub(TableRecTimeStream *self, PyObject *arg) { SUB }; static PyObject * TableRecTimeStream_inplace_sub(TableRecTimeStream *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TableRecTimeStream_div(TableRecTimeStream *self, PyObject *arg) { DIV }; static PyObject * TableRecTimeStream_inplace_div(TableRecTimeStream *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef TableRecTimeStream_members[] = { {"server", T_OBJECT_EX, offsetof(TableRecTimeStream, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TableRecTimeStream, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(TableRecTimeStream, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TableRecTimeStream, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TableRecTimeStream_methods[] = { {"getServer", (PyCFunction)TableRecTimeStream_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TableRecTimeStream_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TableRecTimeStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TableRecTimeStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TableRecTimeStream_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)TableRecTimeStream_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TableRecTimeStream_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TableRecTimeStream_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TableRecTimeStream_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TableRecTimeStream_as_number = { (binaryfunc)TableRecTimeStream_add, /*nb_add*/ (binaryfunc)TableRecTimeStream_sub, /*nb_subtract*/ (binaryfunc)TableRecTimeStream_multiply, /*nb_multiply*/ (binaryfunc)TableRecTimeStream_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TableRecTimeStream_inplace_add, /*inplace_add*/ (binaryfunc)TableRecTimeStream_inplace_sub, /*inplace_subtract*/ (binaryfunc)TableRecTimeStream_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TableRecTimeStream_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TableRecTimeStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TableRecTimeStream_base", /*tp_name*/ sizeof(TableRecTimeStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TableRecTimeStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TableRecTimeStream_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TableRecTimeStream objects. Returns the current recording time, in samples, of a TableRec object.", /* tp_doc */ (traverseproc)TableRecTimeStream_traverse, /* tp_traverse */ (inquiry)TableRecTimeStream_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TableRecTimeStream_methods, /* tp_methods */ TableRecTimeStream_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TableRecTimeStream_new, /* tp_new */ }; /******************************/ /* TableMorph object definition */ /******************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *table; PyObject *sources; MYFLT *buffer; int last_size; } TableMorph; static MYFLT TableMorph_clip(MYFLT x) { if (x < 0.0) return 0.0; else if (x >= 0.999999) return 0.999999; else return x; } static void TableMorph_alloc_memories(TableMorph *self) { int i, size; size = PyInt_AsLong(NewTable_getSize((NewTable *)self->table)); self->last_size = size; self->buffer = (MYFLT *)realloc(self->buffer, size * sizeof(MYFLT)); for (i=0; ibuffer[i] = 0.0; } } static void TableMorph_compute_next_data_frame(TableMorph *self) { int i, x, y; MYFLT input, interp, interp1, interp2; MYFLT *in = Stream_getData((Stream *)self->input_stream); int size = PyInt_AsLong(NewTable_getSize((NewTable *)self->table)); int len = PyList_Size(self->sources); if (size != self->last_size) TableMorph_alloc_memories(self); input = TableMorph_clip(in[0]); interp = input * (len - 1); x = (int)(interp); y = x + 1; MYFLT *tab1 = TableStream_getData((TableStream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->sources, x), "getTableStream", "")); MYFLT *tab2 = TableStream_getData((TableStream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->sources, y), "getTableStream", "")); interp = MYFMOD(interp, 1.0); interp1 = 1. - interp; interp2 = interp; //MYFLT buffer[size]; for (i=0; ibuffer[i] = tab1[i] * interp1 + tab2[i] * interp2; } NewTable_recordChunk((NewTable *)self->table, self->buffer, size); } static int TableMorph_traverse(TableMorph *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->table); Py_VISIT(self->sources); return 0; } static int TableMorph_clear(TableMorph *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->table); Py_CLEAR(self->sources); return 0; } static void TableMorph_dealloc(TableMorph* self) { pyo_DEALLOC free(self->buffer); TableMorph_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TableMorph_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *tabletmp, *sourcestmp; TableMorph *self; self = (TableMorph *)type->tp_alloc(type, 0); INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TableMorph_compute_next_data_frame); static char *kwlist[] = {"input", "table", "sources", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOO", kwlist, &inputtmp, &tabletmp, &sourcestmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableMorph must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); Py_INCREF(tabletmp); self->table = (PyObject *)tabletmp; Py_XDECREF(self->sources); Py_INCREF(sourcestmp); self->sources = (PyObject *)sourcestmp; TableMorph_alloc_memories(self); PyObject_CallMethod(self->server, "addStream", "O", self->stream); return (PyObject *)self; } static PyObject * TableMorph_getServer(TableMorph* self) { GET_SERVER }; static PyObject * TableMorph_getStream(TableMorph* self) { GET_STREAM }; static PyObject * TableMorph_play(TableMorph *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TableMorph_stop(TableMorph *self) { STOP }; static PyObject * TableMorph_setTable(TableMorph *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_INCREF(tmp); Py_DECREF(self->table); self->table = (PyObject *)tmp; Py_INCREF(Py_None); return Py_None; } static PyObject * TableMorph_setSources(TableMorph *self, PyObject *arg) { ASSERT_ARG_NOT_NULL if (! PyList_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list."); return PyInt_FromLong(-1); } Py_INCREF(arg); Py_DECREF(self->sources); self->sources = arg; Py_INCREF(Py_None); return Py_None; } static PyMemberDef TableMorph_members[] = { {"server", T_OBJECT_EX, offsetof(TableMorph, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TableMorph, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(TableMorph, input), 0, "Input sound object."}, {"table", T_OBJECT_EX, offsetof(TableMorph, table), 0, "Table to record in."}, {"sources", T_OBJECT_EX, offsetof(TableMorph, sources), 0, "list of tables to interpolate from."}, {NULL} /* Sentinel */ }; static PyMethodDef TableMorph_methods[] = { {"getServer", (PyCFunction)TableMorph_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TableMorph_getStream, METH_NOARGS, "Returns stream object."}, {"setTable", (PyCFunction)TableMorph_setTable, METH_O, "Sets a new table."}, {"setSources", (PyCFunction)TableMorph_setSources, METH_O, "Changes the sources tables."}, {"play", (PyCFunction)TableMorph_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)TableMorph_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject TableMorphType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TableMorph_base", /*tp_name*/ sizeof(TableMorph), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TableMorph_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TableMorph objects. Interpolation contents of different table objects.", /* tp_doc */ (traverseproc)TableMorph_traverse, /* tp_traverse */ (inquiry)TableMorph_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TableMorph_methods, /* tp_methods */ TableMorph_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TableMorph_new, /* tp_new */ }; /******************************/ /* TrigTableRec object definition */ /******************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *trigger; Stream *trigger_stream; NewTable *table; int pointer; int active; MYFLT fadetime; MYFLT fadeInSample; MYFLT *trigsBuffer; TriggerStream *trig_stream; MYFLT *time_buffer_streams; } TrigTableRec; static void TrigTableRec_compute_next_data_frame(TrigTableRec *self) { int i, j, num, upBound; MYFLT val; int size = PyInt_AsLong(NewTable_getSize((NewTable *)self->table)); MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *trig = Stream_getData((Stream *)self->trigger_stream); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } if (self->active == 1) { if ((size - self->pointer) >= self->bufsize) num = self->bufsize; else { num = size - self->pointer; if (self->active == 1) { if (num <= 0) self->trigsBuffer[0] = 1.0; else self->trigsBuffer[num-1] = 1.0; self->active = 0; } } if (self->pointer < size) { upBound = size - self->fadeInSample; MYFLT buffer[num]; memset(&buffer, 0, sizeof(buffer)); for (i=0; ipointer < self->fadeInSample) val = self->pointer / self->fadeInSample; else if (self->pointer > upBound) val = (size - self->pointer) / self->fadeInSample; else val = 1.; buffer[i] = in[i] * val; self->time_buffer_streams[i] = self->pointer++; } NewTable_recordChunk((NewTable *)self->table, buffer, num); if (num < self->bufsize) { for (i=num; ibufsize; i++) { self->time_buffer_streams[i] = self->pointer; } } } } else { for (j=0; jbufsize; j++) { self->time_buffer_streams[j] = self->pointer; if (trig[j] == 1.0) { self->active = 1; self->pointer = 0; if (size >= self->bufsize) num = self->bufsize - j; else { num = size < (self->bufsize - j) ? size : (self->bufsize - j); if (self->active == 1) { if (num <= 0) self->trigsBuffer[0] = 1.0; else self->trigsBuffer[num-1] = 1.0; self->active = 0; } } upBound = size - self->fadeInSample; MYFLT buffer[num]; memset(&buffer, 0, sizeof(buffer)); for (i=0; ipointer < self->fadeInSample) { val = self->pointer / self->fadeInSample; } else if (self->pointer > upBound) val = (size - self->pointer) / self->fadeInSample; else val = 1.; buffer[i] = in[i+j] * val; self->time_buffer_streams[i+j] = self->pointer++; } NewTable_recordChunk((NewTable *)self->table, buffer, num); if (num < (self->bufsize-j)) { for (i=num; i<(self->bufsize-j); i++) { self->time_buffer_streams[i+j] = self->pointer; } } break; } } } } static MYFLT * TrigTableRec_getTimeBuffer(TrigTableRec *self) { return self->time_buffer_streams; } static int TrigTableRec_traverse(TrigTableRec *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->trigger); Py_VISIT(self->trigger_stream); Py_VISIT(self->table); Py_VISIT(self->trig_stream); return 0; } static int TrigTableRec_clear(TrigTableRec *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->trigger); Py_CLEAR(self->trigger_stream); Py_CLEAR(self->table); Py_CLEAR(self->trig_stream); return 0; } static void TrigTableRec_dealloc(TrigTableRec* self) { pyo_DEALLOC free(self->trigsBuffer); TrigTableRec_clear(self); free(self->time_buffer_streams); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigTableRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *trigtmp, *trig_streamtmp, *tabletmp; TrigTableRec *self; self = (TrigTableRec *)type->tp_alloc(type, 0); self->pointer = 0; self->active = 0; self->fadetime = 0.; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigTableRec_compute_next_data_frame); static char *kwlist[] = {"input", "trig", "table", "fadetime", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OOO_F, kwlist, &inputtmp, &trigtmp, &tabletmp, &self->fadetime)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_XDECREF(self->trigger); Py_INCREF(trigtmp); self->trigger = trigtmp; trig_streamtmp = PyObject_CallMethod((PyObject *)self->trigger, "_getStream", NULL); Py_INCREF(trig_streamtmp); Py_XDECREF(self->trigger_stream); self->trigger_stream = (Stream *)trig_streamtmp; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of TrigTableRec must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); Py_INCREF(tabletmp); self->table = (NewTable *)tabletmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); self->time_buffer_streams = (MYFLT *)realloc(self->time_buffer_streams, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = self->time_buffer_streams[i] = 0.0; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); int size = PyInt_AsLong(NewTable_getSize((NewTable *)self->table)); if ((self->fadetime * self->sr) >= (size * 0.5)) self->fadetime = size * 0.499 / self->sr; if (self->fadetime == 0.0) self->fadeInSample = 0.0; else self->fadeInSample = MYROUND(self->fadetime * self->sr + 0.5); return (PyObject *)self; } static PyObject * TrigTableRec_getServer(TrigTableRec* self) { GET_SERVER }; static PyObject * TrigTableRec_getStream(TrigTableRec* self) { GET_STREAM }; static PyObject * TrigTableRec_getTriggerStream(TrigTableRec* self) { GET_TRIGGER_STREAM }; static PyObject * TrigTableRec_play(TrigTableRec *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigTableRec_stop(TrigTableRec *self) { STOP }; static PyObject * TrigTableRec_setTable(TrigTableRec *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_INCREF(tmp); Py_DECREF(self->table); self->table = (NewTable *)tmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef TrigTableRec_members[] = { {"server", T_OBJECT_EX, offsetof(TrigTableRec, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigTableRec, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(TrigTableRec, trig_stream), 0, "Trigger Stream object."}, {"input", T_OBJECT_EX, offsetof(TrigTableRec, input), 0, "Input sound object."}, {"trigger", T_OBJECT_EX, offsetof(TrigTableRec, trigger), 0, "Trigger object."}, {"table", T_OBJECT_EX, offsetof(TrigTableRec, table), 0, "Table to record in."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigTableRec_methods[] = { {"getServer", (PyCFunction)TrigTableRec_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigTableRec_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)TrigTableRec_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"setTable", (PyCFunction)TrigTableRec_setTable, METH_O, "Sets a new table."}, {"play", (PyCFunction)TrigTableRec_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)TrigTableRec_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject TrigTableRecType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigTableRec_base", /*tp_name*/ sizeof(TrigTableRec), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigTableRec_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigTableRec objects. Record audio input in a table object.", /* tp_doc */ (traverseproc)TrigTableRec_traverse, /* tp_traverse */ (inquiry)TrigTableRec_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigTableRec_methods, /* tp_methods */ TrigTableRec_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigTableRec_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD TrigTableRec *mainPlayer; int modebuffer[2]; } TrigTableRecTimeStream; static void TrigTableRecTimeStream_postprocessing_ii(TrigTableRecTimeStream *self) { POST_PROCESSING_II }; static void TrigTableRecTimeStream_postprocessing_ai(TrigTableRecTimeStream *self) { POST_PROCESSING_AI }; static void TrigTableRecTimeStream_postprocessing_ia(TrigTableRecTimeStream *self) { POST_PROCESSING_IA }; static void TrigTableRecTimeStream_postprocessing_aa(TrigTableRecTimeStream *self) { POST_PROCESSING_AA }; static void TrigTableRecTimeStream_postprocessing_ireva(TrigTableRecTimeStream *self) { POST_PROCESSING_IREVA }; static void TrigTableRecTimeStream_postprocessing_areva(TrigTableRecTimeStream *self) { POST_PROCESSING_AREVA }; static void TrigTableRecTimeStream_postprocessing_revai(TrigTableRecTimeStream *self) { POST_PROCESSING_REVAI }; static void TrigTableRecTimeStream_postprocessing_revaa(TrigTableRecTimeStream *self) { POST_PROCESSING_REVAA }; static void TrigTableRecTimeStream_postprocessing_revareva(TrigTableRecTimeStream *self) { POST_PROCESSING_REVAREVA }; static void TrigTableRecTimeStream_setProcMode(TrigTableRecTimeStream *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_revareva; break; } } static void TrigTableRecTimeStream_compute_next_data_frame(TrigTableRecTimeStream *self) { int i; MYFLT *tmp; tmp = TrigTableRec_getTimeBuffer((TrigTableRec *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i]; } (*self->muladd_func_ptr)(self); } static int TrigTableRecTimeStream_traverse(TrigTableRecTimeStream *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int TrigTableRecTimeStream_clear(TrigTableRecTimeStream *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void TrigTableRecTimeStream_dealloc(TrigTableRecTimeStream* self) { pyo_DEALLOC TrigTableRecTimeStream_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigTableRecTimeStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; TrigTableRecTimeStream *self; self = (TrigTableRecTimeStream *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigTableRecTimeStream_compute_next_data_frame); self->mode_func_ptr = TrigTableRecTimeStream_setProcMode; static char *kwlist[] = {"mainPlayer", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &maintmp)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (TrigTableRec *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigTableRecTimeStream_getServer(TrigTableRecTimeStream* self) { GET_SERVER }; static PyObject * TrigTableRecTimeStream_getStream(TrigTableRecTimeStream* self) { GET_STREAM }; static PyObject * TrigTableRecTimeStream_setMul(TrigTableRecTimeStream *self, PyObject *arg) { SET_MUL }; static PyObject * TrigTableRecTimeStream_setAdd(TrigTableRecTimeStream *self, PyObject *arg) { SET_ADD }; static PyObject * TrigTableRecTimeStream_setSub(TrigTableRecTimeStream *self, PyObject *arg) { SET_SUB }; static PyObject * TrigTableRecTimeStream_setDiv(TrigTableRecTimeStream *self, PyObject *arg) { SET_DIV }; static PyObject * TrigTableRecTimeStream_play(TrigTableRecTimeStream *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigTableRecTimeStream_out(TrigTableRecTimeStream *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrigTableRecTimeStream_stop(TrigTableRecTimeStream *self) { STOP }; static PyObject * TrigTableRecTimeStream_multiply(TrigTableRecTimeStream *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigTableRecTimeStream_inplace_multiply(TrigTableRecTimeStream *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigTableRecTimeStream_add(TrigTableRecTimeStream *self, PyObject *arg) { ADD }; static PyObject * TrigTableRecTimeStream_inplace_add(TrigTableRecTimeStream *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigTableRecTimeStream_sub(TrigTableRecTimeStream *self, PyObject *arg) { SUB }; static PyObject * TrigTableRecTimeStream_inplace_sub(TrigTableRecTimeStream *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigTableRecTimeStream_div(TrigTableRecTimeStream *self, PyObject *arg) { DIV }; static PyObject * TrigTableRecTimeStream_inplace_div(TrigTableRecTimeStream *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef TrigTableRecTimeStream_members[] = { {"server", T_OBJECT_EX, offsetof(TrigTableRecTimeStream, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigTableRecTimeStream, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(TrigTableRecTimeStream, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigTableRecTimeStream, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigTableRecTimeStream_methods[] = { {"getServer", (PyCFunction)TrigTableRecTimeStream_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigTableRecTimeStream_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigTableRecTimeStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrigTableRecTimeStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrigTableRecTimeStream_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)TrigTableRecTimeStream_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TrigTableRecTimeStream_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TrigTableRecTimeStream_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigTableRecTimeStream_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigTableRecTimeStream_as_number = { (binaryfunc)TrigTableRecTimeStream_add, /*nb_add*/ (binaryfunc)TrigTableRecTimeStream_sub, /*nb_subtract*/ (binaryfunc)TrigTableRecTimeStream_multiply, /*nb_multiply*/ (binaryfunc)TrigTableRecTimeStream_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigTableRecTimeStream_inplace_add, /*inplace_add*/ (binaryfunc)TrigTableRecTimeStream_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigTableRecTimeStream_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigTableRecTimeStream_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigTableRecTimeStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigTableRecTimeStream_base", /*tp_name*/ sizeof(TrigTableRecTimeStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigTableRecTimeStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigTableRecTimeStream_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigTableRecTimeStream objects. Returns the current recording time, in samples, of a TableRec object.", /* tp_doc */ (traverseproc)TrigTableRecTimeStream_traverse, /* tp_traverse */ (inquiry)TrigTableRecTimeStream_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigTableRecTimeStream_methods, /* tp_methods */ TrigTableRecTimeStream_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigTableRecTimeStream_new, /* tp_new */ }; /******************************/ /* TablePut object definition */ /******************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; DataTable *table; int pointer; int active; MYFLT last_value; MYFLT *trigsBuffer; TriggerStream *trig_stream; } TablePut; static void TablePut_compute_next_data_frame(TablePut *self) { int i; int size = PyInt_AsLong(DataTable_getSize((DataTable *)self->table)); MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } if (self->active == 1) { for (i=0; ibufsize; i++) { if (in[i] != self->last_value) { self->last_value = in[i]; DataTable_record((DataTable *)self->table, self->pointer++, self->last_value); if (self->pointer >= size) { self->active = 0; self->trigsBuffer[i] = 1.0; break; } } } } } static int TablePut_traverse(TablePut *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->table); Py_VISIT(self->trig_stream); return 0; } static int TablePut_clear(TablePut *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->table); Py_CLEAR(self->trig_stream); return 0; } static void TablePut_dealloc(TablePut* self) { pyo_DEALLOC free(self->trigsBuffer); TablePut_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TablePut_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *tabletmp; TablePut *self; self = (TablePut *)type->tp_alloc(type, 0); self->pointer = 0; self->active = 1; self->last_value = 0.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TablePut_compute_next_data_frame); Stream_setStreamActive(self->stream, 0); static char *kwlist[] = {"input", "table", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &inputtmp, &tabletmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of TablePut must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); Py_INCREF(tabletmp); self->table = (DataTable *)tabletmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); return (PyObject *)self; } static PyObject * TablePut_getServer(TablePut* self) { GET_SERVER }; static PyObject * TablePut_getStream(TablePut* self) { GET_STREAM }; static PyObject * TablePut_getTriggerStream(TablePut* self) { GET_TRIGGER_STREAM }; static PyObject * TablePut_play(TablePut *self, PyObject *args, PyObject *kwds) { self->pointer = 0; self->active = 1; PLAY }; static PyObject * TablePut_stop(TablePut *self) { STOP }; static PyObject * TablePut_setTable(TablePut *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_INCREF(tmp); Py_DECREF(self->table); self->table = (DataTable *)tmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef TablePut_members[] = { {"server", T_OBJECT_EX, offsetof(TablePut, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TablePut, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(TablePut, trig_stream), 0, "Trigger Stream object."}, {"input", T_OBJECT_EX, offsetof(TablePut, input), 0, "Input sound object."}, {"table", T_OBJECT_EX, offsetof(TablePut, table), 0, "Table to record in."}, {NULL} /* Sentinel */ }; static PyMethodDef TablePut_methods[] = { {"getServer", (PyCFunction)TablePut_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TablePut_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)TablePut_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"setTable", (PyCFunction)TablePut_setTable, METH_O, "Sets a new data table."}, {"play", (PyCFunction)TablePut_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)TablePut_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject TablePutType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TablePut_base", /*tp_name*/ sizeof(TablePut), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TablePut_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TablePut objects. Record new value in input in a data table object.", /* tp_doc */ (traverseproc)TablePut_traverse, /* tp_traverse */ (inquiry)TablePut_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TablePut_methods, /* tp_methods */ TablePut_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TablePut_new, /* tp_new */ }; /******************************/ /* TableWrite object definition */ /******************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *pos; Stream *pos_stream; NewTable *table; } TableWrite; static void TableWrite_compute_next_data_frame(TableWrite *self) { int i, ipos; PyObject *table; table = PyObject_CallMethod((PyObject *)self->table, "getTableStream", ""); MYFLT *tablelist = TableStream_getData((TableStream *)table); int size = TableStream_getSize((TableStream *)table); MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *pos = Stream_getData((Stream *)self->pos_stream); for (i=0; ibufsize; i++) { ipos = (int)(pos[i] * size); if (ipos < 0) ipos = 0; else if (ipos >= size) ipos = size - 1; tablelist[ipos] = in[i]; } } static int TableWrite_traverse(TableWrite *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->table); Py_VISIT(self->pos); Py_VISIT(self->pos_stream); return 0; } static int TableWrite_clear(TableWrite *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->table); Py_CLEAR(self->pos); Py_CLEAR(self->pos_stream); return 0; } static void TableWrite_dealloc(TableWrite* self) { pyo_DEALLOC TableWrite_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TableWrite_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *postmp, *tabletmp; TableWrite *self; self = (TableWrite *)type->tp_alloc(type, 0); INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TableWrite_compute_next_data_frame); Stream_setStreamActive(self->stream, 1); static char *kwlist[] = {"input", "pos", "table", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOO", kwlist, &inputtmp, &postmp, &tabletmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (postmp) { PyObject_CallMethod((PyObject *)self, "setPos", "O", postmp); } if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableWrite must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); Py_INCREF(tabletmp); self->table = (NewTable *)tabletmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); return (PyObject *)self; } static PyObject * TableWrite_getServer(TableWrite* self) { GET_SERVER }; static PyObject * TableWrite_getStream(TableWrite* self) { GET_STREAM }; static PyObject * TableWrite_play(TableWrite *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TableWrite_stop(TableWrite *self) { STOP }; static PyObject * TableWrite_setPos(TableWrite *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL tmp = arg; if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) { PyErr_SetString(PyExc_TypeError, "\"pos\" argument of TableWrite must be a PyoObject.\n"); Py_RETURN_NONE; } Py_INCREF(tmp); Py_XDECREF(self->pos); self->pos = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pos, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pos_stream); self->pos_stream = (Stream *)streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * TableWrite_setTable(TableWrite *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_INCREF(tmp); Py_DECREF(self->table); self->table = (NewTable *)tmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef TableWrite_members[] = { {"server", T_OBJECT_EX, offsetof(TableWrite, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TableWrite, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(TableWrite, input), 0, "Input sound object."}, {"table", T_OBJECT_EX, offsetof(TableWrite, table), 0, "Table to record in."}, {"pos", T_OBJECT_EX, offsetof(TableWrite, pos), 0, "Position in the Table to record in."}, {NULL} /* Sentinel */ }; static PyMethodDef TableWrite_methods[] = { {"getServer", (PyCFunction)TableWrite_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TableWrite_getStream, METH_NOARGS, "Returns stream object."}, {"setTable", (PyCFunction)TableWrite_setTable, METH_O, "Sets a new table."}, {"setPos", (PyCFunction)TableWrite_setPos, METH_O, "Sets position in the sound table."}, {"play", (PyCFunction)TableWrite_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)TableWrite_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject TableWriteType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TableWrite_base", /*tp_name*/ sizeof(TableWrite), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TableWrite_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TableWrite objects. Record audio input in a table object.", /* tp_doc */ (traverseproc)TableWrite_traverse, /* tp_traverse */ (inquiry)TableWrite_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TableWrite_methods, /* tp_methods */ TableWrite_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TableWrite_new, /* tp_new */ }; pyo/src/objects/matrixmodule.c0000644000175000017500000010663212652732202015764 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #include "servermodule.h" #include "streammodule.h" #include "dummymodule.h" #define __MATRIX_MODULE #include "matrixmodule.h" #undef __MATRIX_MODULE /*************************/ /* MatrixStream structure */ /*************************/ static void MatrixStream_dealloc(MatrixStream* self) { self->ob_type->tp_free((PyObject*)self); } static PyObject * MatrixStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { MatrixStream *self; MAKE_NEW_MATRIXSTREAM(self, type, NULL); return (PyObject *)self; } int MatrixStream_getWidth(MatrixStream *self) { return self->width; } int MatrixStream_getHeight(MatrixStream *self) { return self->height; } /* width and height position normalized between 0 and 1 */ MYFLT MatrixStream_getInterpPointFromPos(MatrixStream *self, MYFLT x, MYFLT y) { MYFLT xpos, ypos, xfpart, yfpart, x1, x2, x3, x4; int xipart, yipart; xpos = x * self->width; if (xpos < 0) xpos += self->width; else if (xpos >= self->width) { while (xpos >= self->width) { xpos -= self->width; } } ypos = y * self->height; if (ypos < 0) ypos += self->height; else if (ypos >= self->height) { while (ypos >= self->height) { ypos -= self->height; } } xipart = (int)xpos; xfpart = xpos - xipart; yipart = (int)ypos; yfpart = ypos - yipart; x1 = self->data[yipart][xipart]; // (0, 0) x2 = self->data[yipart+1][xipart]; // (0, 1) x3 = self->data[yipart][xipart+1]; // (1, 0) x4 = self->data[yipart+1][xipart+1]; // (1, 1) return (x1*(1-yfpart)*(1-xfpart) + x2*yfpart*(1-xfpart) + x3*(1-yfpart)*xfpart + x4*yfpart*xfpart); } MYFLT MatrixStream_getPointFromPos(MatrixStream *self, long x, long y) { return self->data[y][x]; } void MatrixStream_setData(MatrixStream *self, MYFLT **data) { self->data = data; } void MatrixStream_setWidth(MatrixStream *self, int size) { self->width = size; } void MatrixStream_setHeight(MatrixStream *self, int size) { self->height = size; } PyTypeObject MatrixStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.MatrixStream", /*tp_name*/ sizeof(MatrixStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)MatrixStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ "MatrixStream objects. For internal use only. Must never be instantiated by the user.", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MatrixStream_new, /* tp_new */ }; /***********************/ /* NewMatrix structure */ /***********************/ typedef struct { pyo_matrix_HEAD int x_pointer; int y_pointer; } NewMatrix; MYFLT NewMatrix_clip(MYFLT val, MYFLT min, MYFLT max) { if (val < min) return min; else if (val > max) return max; else return val; } static PyObject * NewMatrix_recordChunkAllRow(NewMatrix *self, MYFLT *data, long datasize) { long i; for (i=0; idata[self->y_pointer][self->x_pointer++] = data[i]; if (self->x_pointer >= self->width) { self->x_pointer = 0; self->y_pointer++; if (self->y_pointer >= self->height) self->y_pointer = 0; } } Py_INCREF(Py_None); return Py_None; } static int NewMatrix_traverse(NewMatrix *self, visitproc visit, void *arg) { pyo_matrix_VISIT return 0; } static int NewMatrix_clear(NewMatrix *self) { pyo_matrix_CLEAR return 0; } static void NewMatrix_dealloc(NewMatrix* self) { int i; for (i=0; i<(self->height+1); i++) { free(self->data[i]); } free(self->data); NewMatrix_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * NewMatrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, j; PyObject *inittmp=NULL; NewMatrix *self; self = (NewMatrix *)type->tp_alloc(type, 0); self->server = PyServer_get_server(); self->x_pointer = self->y_pointer = 0; MAKE_NEW_MATRIXSTREAM(self->matrixstream, &MatrixStreamType, NULL); static char *kwlist[] = {"width", "height", "init", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "ii|O", kwlist, &self->width, &self->height, &inittmp)) Py_RETURN_NONE; self->data = (MYFLT **)realloc(self->data, (self->height + 1) * sizeof(MYFLT *)); for (i=0; i<(self->height+1); i++) { self->data[i] = (MYFLT *)malloc((self->width + 1) * sizeof(MYFLT)); } for(i=0; i<(self->height+1); i++) { for (j=0; j<(self->width+1); j++) { self->data[i][j] = 0.0; } } MatrixStream_setWidth(self->matrixstream, self->width); MatrixStream_setHeight(self->matrixstream, self->height); if (inittmp) { PyObject_CallMethod((PyObject *)self, "setMatrix", "O", inittmp); } MatrixStream_setData(self->matrixstream, self->data); return (PyObject *)self; } static PyObject * NewMatrix_getServer(NewMatrix* self) { GET_SERVER }; static PyObject * NewMatrix_getMatrixStream(NewMatrix* self) { GET_MATRIX_STREAM }; static PyObject * NewMatrix_normalize(NewMatrix *self) { NORMALIZE_MATRIX }; static PyObject * NewMatrix_setData(NewMatrix *self, PyObject *arg) { SET_MATRIX_DATA }; static PyObject * NewMatrix_blur(NewMatrix *self) { MATRIX_BLUR }; static PyObject * NewMatrix_boost(NewMatrix *self, PyObject *args, PyObject *kwds) { MATRIX_BOOST }; static PyObject * NewMatrix_put(NewMatrix *self, PyObject *args, PyObject *kwds) { MATRIX_PUT }; static PyObject * NewMatrix_get(NewMatrix *self, PyObject *args, PyObject *kwds) { MATRIX_GET }; static PyObject * NewMatrix_getSize(NewMatrix *self) { return Py_BuildValue("(ii)", self->width, self->height); }; static int NewMatrix_getWidth(NewMatrix *self) { return self->width; }; static int NewMatrix_getHeight(NewMatrix *self) { return self->height; }; static PyObject * NewMatrix_getRate(NewMatrix *self) { MYFLT sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); \ return PyFloat_FromDouble(sr / self->width); }; static PyObject * NewMatrix_getData(NewMatrix *self) { int i, j; PyObject *matrix, *samples; matrix = PyList_New(self->height); for(i=0; iheight; i++) { samples = PyList_New(self->width); for (j=0; jwidth; j++) { PyList_SetItem(samples, j, PyFloat_FromDouble(self->data[i][j])); } PyList_SetItem(matrix, i, samples); } return matrix; }; static PyObject * NewMatrix_getViewData(NewMatrix *self) { int i, j; PyObject *matrix; matrix = PyList_New(self->width*self->height); for(i=0; iheight; i++) { for (j=0; jwidth; j++) { PyList_SET_ITEM(matrix, i*self->width+j, PyFloat_FromDouble(self->data[i][j]*128+128)); } } return matrix; }; static PyObject * NewMatrix_setMatrix(NewMatrix *self, PyObject *value) { int i, j; PyObject *innerlist; if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute."); return PyInt_FromLong(-1); } if (! PyList_Check(value)) { PyErr_SetString(PyExc_TypeError, "The matrix value value must be a list."); return PyInt_FromLong(-1); } int height = PyList_Size(value); int width = PyList_Size(PyList_GetItem(value, 0)); if (height != self->height || width != self->width) { PyErr_SetString(PyExc_TypeError, "New matrix must be of the same size as actual matrix."); return PyInt_FromLong(-1); } for(i=0; iheight; i++) { innerlist = PyList_GetItem(value, i); for (j=0; jwidth; j++) { self->data[i][j] = PyFloat_AsDouble(PyList_GET_ITEM(innerlist, j)); } } Py_INCREF(Py_None); return Py_None; } static PyObject * NewMatrix_genSineTerrain(NewMatrix *self, PyObject *args, PyObject *kwds) { int i, j; MYFLT xfreq, xphase, xsize; MYFLT freq = 1; MYFLT phase = 0.0625; static char *kwlist[] = {"freq", "phase", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FF, kwlist, &freq, &phase)) return PyInt_FromLong(-1); xfreq = TWOPI * freq; xsize = 1.0 / self->width; for (i=0; iheight; i++) { xphase = MYSIN(i * phase); for (j=0; jwidth; j++) { self->data[i][j] = MYSIN(xfreq * j * xsize + xphase); } } Py_INCREF(Py_None); return Py_None; } static PyMemberDef NewMatrix_members[] = { {"server", T_OBJECT_EX, offsetof(NewMatrix, server), 0, "Pyo server."}, {"matrixstream", T_OBJECT_EX, offsetof(NewMatrix, matrixstream), 0, "Matrix stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef NewMatrix_methods[] = { {"getServer", (PyCFunction)NewMatrix_getServer, METH_NOARGS, "Returns server object."}, {"getData", (PyCFunction)NewMatrix_getData, METH_NOARGS, "Returns a list of matrix samples."}, {"getViewData", (PyCFunction)NewMatrix_getViewData, METH_NOARGS, "Returns a list of matrix samples normalized between 0 and 256 ."}, {"getMatrixStream", (PyCFunction)NewMatrix_getMatrixStream, METH_NOARGS, "Returns matrixstream object created by this matrix."}, {"setMatrix", (PyCFunction)NewMatrix_setMatrix, METH_O, "Sets the matrix from a list of list of floats (must be the same size as the object size)."}, {"setData", (PyCFunction)NewMatrix_setData, METH_O, "Sets the matrix from a list of list of floats (resizes the matrix)."}, {"normalize", (PyCFunction)NewMatrix_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"}, {"blur", (PyCFunction)NewMatrix_blur, METH_NOARGS, "Blur the matrix."}, {"genSineTerrain", (PyCFunction)NewMatrix_genSineTerrain, METH_VARARGS|METH_KEYWORDS, "Generate a modulated sinusoidal terrain."}, {"boost", (PyCFunction)NewMatrix_boost, METH_VARARGS|METH_KEYWORDS, "Boost the contrast of the matrix."}, {"put", (PyCFunction)NewMatrix_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the matrix."}, {"get", (PyCFunction)NewMatrix_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the matrix."}, {"getSize", (PyCFunction)NewMatrix_getSize, METH_NOARGS, "Return the size of the matrix in samples."}, {"getRate", (PyCFunction)NewMatrix_getRate, METH_NOARGS, "Return the frequency (in cps) that reads the sound without pitch transposition."}, {NULL} /* Sentinel */ }; PyTypeObject NewMatrixType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.NewMatrix_base", /*tp_name*/ sizeof(NewMatrix), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)NewMatrix_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "NewMatrix objects. Generates an empty matrix.", /* tp_doc */ (traverseproc)NewMatrix_traverse, /* tp_traverse */ (inquiry)NewMatrix_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ NewMatrix_methods, /* tp_methods */ NewMatrix_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ NewMatrix_new, /* tp_new */ }; /******************************/ /* MatrixRec object definition */ /******************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; NewMatrix *matrix; int pointer; int active; int delay; int delayCount; MYFLT fadetime; MYFLT fadeInSample; MYFLT *trigsBuffer; TriggerStream *trig_stream; } MatrixRec; static void MatrixRec_compute_next_data_frame(MatrixRec *self) { int i, num, num2, upBound; MYFLT val; int width = NewMatrix_getWidth((NewMatrix *)self->matrix); int height = NewMatrix_getHeight((NewMatrix *)self->matrix); int size = width * height; int off = self->delay - self->delayCount; for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } if ((size - self->pointer) >= self->bufsize) num = self->bufsize; else { num = size - self->pointer; if (self->active == 1) { if (num <= 0) self->trigsBuffer[0] = 1.0; else self->trigsBuffer[num-1] = 1.0; self->active = 0; } } if (self->pointer < size) { upBound = size - self->fadeInSample; if (off == 0) num2 = num; else if ((num-off) <= 0) num2 = 0; else num2 = num-off; MYFLT buffer[num2]; memset(&buffer, 0, sizeof(buffer)); MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; idelayCount < self->delay) { self->delayCount++; } else { if (self->pointer < self->fadeInSample) val = self->pointer / self->fadeInSample; else if (self->pointer > upBound) val = (size - self->pointer) / self->fadeInSample; else val = 1.; buffer[i-off] = in[i] * val; self->pointer++; } } NewMatrix_recordChunkAllRow((NewMatrix *)self->matrix, buffer, num2); } } static int MatrixRec_traverse(MatrixRec *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->matrix); Py_VISIT(self->trig_stream); return 0; } static int MatrixRec_clear(MatrixRec *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->matrix); Py_CLEAR(self->trig_stream); return 0; } static void MatrixRec_dealloc(MatrixRec* self) { pyo_DEALLOC free(self->trigsBuffer); MatrixRec_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * MatrixRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *matrixtmp; MatrixRec *self; self = (MatrixRec *)type->tp_alloc(type, 0); self->pointer = 0; self->active = 1; self->fadetime = 0.; self->delay = self->delayCount = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, MatrixRec_compute_next_data_frame); Stream_setStreamActive(self->stream, 0); static char *kwlist[] = {"input", "matrix", "fadetime", "delay", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_FI, kwlist, &inputtmp, &matrixtmp, &self->fadetime, &self->delay)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_XDECREF(self->matrix); Py_INCREF(matrixtmp); self->matrix = (NewMatrix *)matrixtmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); int width = NewMatrix_getWidth((NewMatrix *)self->matrix); int height = NewMatrix_getHeight((NewMatrix *)self->matrix); int size = width * height; if ((self->fadetime * self->sr) > (size * 0.5)) self->fadetime = size * 0.5 / self->sr; self->fadeInSample = roundf(self->fadetime * self->sr + 0.5); return (PyObject *)self; } static PyObject * MatrixRec_getServer(MatrixRec* self) { GET_SERVER }; static PyObject * MatrixRec_getStream(MatrixRec* self) { GET_STREAM }; static PyObject * MatrixRec_getTriggerStream(MatrixRec* self) { GET_TRIGGER_STREAM }; static PyObject * MatrixRec_play(MatrixRec *self, PyObject *args, PyObject *kwds) { self->pointer = 0; self->active = 1; self->delayCount = 0; PLAY }; static PyObject * MatrixRec_stop(MatrixRec *self) { STOP }; static PyObject * MatrixRec_setMatrix(MatrixRec *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_INCREF(tmp); Py_DECREF(self->matrix); self->matrix = (NewMatrix *)tmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef MatrixRec_members[] = { {"server", T_OBJECT_EX, offsetof(MatrixRec, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(MatrixRec, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(MatrixRec, trig_stream), 0, "Trigger Stream object."}, {"input", T_OBJECT_EX, offsetof(MatrixRec, input), 0, "Input sound object."}, {"matrix", T_OBJECT_EX, offsetof(MatrixRec, matrix), 0, "matrix to record in."}, {NULL} /* Sentinel */ }; static PyMethodDef MatrixRec_methods[] = { {"getServer", (PyCFunction)MatrixRec_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)MatrixRec_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)MatrixRec_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"setMatrix", (PyCFunction)MatrixRec_setMatrix, METH_O, "Sets a new Matrix."}, {"play", (PyCFunction)MatrixRec_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)MatrixRec_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject MatrixRecType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.MatrixRec_base", /*tp_name*/ sizeof(MatrixRec), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)MatrixRec_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "MatrixRec objects. Record audio input in a Matrix object.", /* tp_doc */ (traverseproc)MatrixRec_traverse, /* tp_traverse */ (inquiry)MatrixRec_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ MatrixRec_methods, /* tp_methods */ MatrixRec_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MatrixRec_new, /* tp_new */ }; /******************************/ /* MatrixRecLoop object definition */ /******************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; NewMatrix *matrix; int pointer; MYFLT *trigsBuffer; TriggerStream *trig_stream; } MatrixRecLoop; static void MatrixRecLoop_compute_next_data_frame(MatrixRecLoop *self) { int i; int width = NewMatrix_getWidth((NewMatrix *)self->matrix); int height = NewMatrix_getHeight((NewMatrix *)self->matrix); int size = width * height; MYFLT buffer[self->bufsize]; memset(&buffer, 0, sizeof(buffer)); MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; buffer[i] = in[i]; if (self->pointer++ >= size) { self->pointer = 0; self->trigsBuffer[i] = 1.0; } } NewMatrix_recordChunkAllRow((NewMatrix *)self->matrix, buffer, self->bufsize); } static int MatrixRecLoop_traverse(MatrixRecLoop *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->matrix); Py_VISIT(self->trig_stream); return 0; } static int MatrixRecLoop_clear(MatrixRecLoop *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->matrix); Py_CLEAR(self->trig_stream); return 0; } static void MatrixRecLoop_dealloc(MatrixRecLoop* self) { pyo_DEALLOC free(self->trigsBuffer); MatrixRecLoop_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * MatrixRecLoop_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *matrixtmp; MatrixRecLoop *self; self = (MatrixRecLoop *)type->tp_alloc(type, 0); self->pointer = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, MatrixRecLoop_compute_next_data_frame); static char *kwlist[] = {"input", "matrix", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &inputtmp, &matrixtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_XDECREF(self->matrix); Py_INCREF(matrixtmp); self->matrix = (NewMatrix *)matrixtmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); return (PyObject *)self; } static PyObject * MatrixRecLoop_getServer(MatrixRecLoop* self) { GET_SERVER }; static PyObject * MatrixRecLoop_getStream(MatrixRecLoop* self) { GET_STREAM }; static PyObject * MatrixRecLoop_getTriggerStream(MatrixRecLoop* self) { GET_TRIGGER_STREAM }; static PyObject * MatrixRecLoop_play(MatrixRecLoop *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * MatrixRecLoop_stop(MatrixRecLoop *self) { STOP }; static PyObject * MatrixRecLoop_setMatrix(MatrixRecLoop *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_INCREF(tmp); Py_DECREF(self->matrix); self->matrix = (NewMatrix *)tmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef MatrixRecLoop_members[] = { {"server", T_OBJECT_EX, offsetof(MatrixRecLoop, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(MatrixRecLoop, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(MatrixRecLoop, trig_stream), 0, "Trigger Stream object."}, {"input", T_OBJECT_EX, offsetof(MatrixRecLoop, input), 0, "Input sound object."}, {"matrix", T_OBJECT_EX, offsetof(MatrixRecLoop, matrix), 0, "matrix to record in."}, {NULL} /* Sentinel */ }; static PyMethodDef MatrixRecLoop_methods[] = { {"getServer", (PyCFunction)MatrixRecLoop_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)MatrixRecLoop_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)MatrixRecLoop_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"setMatrix", (PyCFunction)MatrixRecLoop_setMatrix, METH_O, "Sets a new Matrix."}, {"play", (PyCFunction)MatrixRecLoop_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)MatrixRecLoop_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject MatrixRecLoopType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.MatrixRecLoop_base", /*tp_name*/ sizeof(MatrixRecLoop), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)MatrixRecLoop_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "MatrixRecLoop objects. Record circular audio input in a Matrix object.", /* tp_doc */ (traverseproc)MatrixRecLoop_traverse, /* tp_traverse */ (inquiry)MatrixRecLoop_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ MatrixRecLoop_methods, /* tp_methods */ MatrixRecLoop_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MatrixRecLoop_new, /* tp_new */ }; /******************************/ /* MatrixMorph object definition */ /******************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *matrix; PyObject *sources; MYFLT *buffer; } MatrixMorph; static MYFLT MatrixMorph_clip(MYFLT x) { if (x < 0.0) return 0.0; else if (x >= 0.999999) return 0.999999; else return x; } static void MatrixMorph_compute_next_data_frame(MatrixMorph *self) { int x, y; long i, j, width, height, numsamps, index; MYFLT input, interp, interp1; MYFLT *in = Stream_getData((Stream *)self->input_stream); width = NewMatrix_getWidth((NewMatrix *)self->matrix); height = NewMatrix_getHeight((NewMatrix *)self->matrix); numsamps = width * height; int len = PyList_Size(self->sources); input = MatrixMorph_clip(in[0]); interp = input * (len - 1); x = (int)(interp); y = x + 1; MatrixStream *tab1 = (MatrixStream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->sources, x), "getMatrixStream", ""); MatrixStream *tab2 = (MatrixStream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->sources, y), "getMatrixStream", ""); interp = MYFMOD(interp, 1.0); interp1 = 1. - interp; for (i=0; ibuffer[index] = MatrixStream_getPointFromPos(tab1, j, i) * interp1 + MatrixStream_getPointFromPos(tab2, j, i) * interp; } } NewMatrix_recordChunkAllRow((NewMatrix *)self->matrix, self->buffer, numsamps); } static int MatrixMorph_traverse(MatrixMorph *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->matrix); Py_VISIT(self->sources); return 0; } static int MatrixMorph_clear(MatrixMorph *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->matrix); Py_CLEAR(self->sources); return 0; } static void MatrixMorph_dealloc(MatrixMorph* self) { pyo_DEALLOC free(self->buffer); MatrixMorph_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * MatrixMorph_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; long width, height, numsamps; PyObject *inputtmp, *input_streamtmp, *matrixtmp, *sourcestmp; MatrixMorph *self; self = (MatrixMorph *)type->tp_alloc(type, 0); INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, MatrixMorph_compute_next_data_frame); static char *kwlist[] = {"input", "matrix", "sources", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOO", kwlist, &inputtmp, &matrixtmp, &sourcestmp)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_XDECREF(self->matrix); Py_INCREF(matrixtmp); self->matrix = (PyObject *)matrixtmp; width = NewMatrix_getWidth((NewMatrix *)self->matrix); height = NewMatrix_getHeight((NewMatrix *)self->matrix); numsamps = width * height; self->buffer = (MYFLT *)realloc(self->buffer, (numsamps) * sizeof(MYFLT)); Py_XDECREF(self->sources); Py_INCREF(sourcestmp); self->sources = (PyObject *)sourcestmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); return (PyObject *)self; } static PyObject * MatrixMorph_getServer(MatrixMorph* self) { GET_SERVER }; static PyObject * MatrixMorph_getStream(MatrixMorph* self) { GET_STREAM }; static PyObject * MatrixMorph_play(MatrixMorph *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * MatrixMorph_stop(MatrixMorph *self) { STOP }; static PyObject * MatrixMorph_setMatrix(MatrixMorph *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_INCREF(tmp); Py_DECREF(self->matrix); self->matrix = (PyObject *)tmp; Py_INCREF(Py_None); return Py_None; } static PyObject * MatrixMorph_setSources(MatrixMorph *self, PyObject *arg) { ASSERT_ARG_NOT_NULL if (! PyList_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list."); return PyInt_FromLong(-1); } Py_INCREF(arg); Py_DECREF(self->sources); self->sources = arg; Py_INCREF(Py_None); return Py_None; } static PyMemberDef MatrixMorph_members[] = { {"server", T_OBJECT_EX, offsetof(MatrixMorph, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(MatrixMorph, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(MatrixMorph, input), 0, "Input sound object."}, {"matrix", T_OBJECT_EX, offsetof(MatrixMorph, matrix), 0, "Matrix to record in."}, {"sources", T_OBJECT_EX, offsetof(MatrixMorph, sources), 0, "list of matrixes to interpolate from."}, {NULL} /* Sentinel */ }; static PyMethodDef MatrixMorph_methods[] = { {"getServer", (PyCFunction)MatrixMorph_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)MatrixMorph_getStream, METH_NOARGS, "Returns stream object."}, {"setMatrix", (PyCFunction)MatrixMorph_setMatrix, METH_O, "Sets a new matrix."}, {"setSources", (PyCFunction)MatrixMorph_setSources, METH_O, "Changes the sources matrixs."}, {"play", (PyCFunction)MatrixMorph_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)MatrixMorph_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject MatrixMorphType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.MatrixMorph_base", /*tp_name*/ sizeof(MatrixMorph), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)MatrixMorph_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "MatrixMorph objects. Interpolation contents of different matrix objects.", /* tp_doc */ (traverseproc)MatrixMorph_traverse, /* tp_traverse */ (inquiry)MatrixMorph_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ MatrixMorph_methods, /* tp_methods */ MatrixMorph_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MatrixMorph_new, /* tp_new */ }; pyo/src/objects/patternmodule.c0000644000175000017500000004431512652732202016134 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD PyObject *callable; PyObject *time; Stream *time_stream; int modebuffer[1]; MYFLT sampleToSec; double currentTime; int init; } Pattern; static void Pattern_generate_i(Pattern *self) { MYFLT tm; int i, flag; PyObject *result; flag = 0; tm = PyFloat_AS_DOUBLE(self->time); for (i=0; ibufsize; i++) { if (self->currentTime >= tm) { flag = 1; self->currentTime = 0.; } self->currentTime += self->sampleToSec; } if (flag == 1 || self->init == 1) { self->init = 0; result = PyObject_Call((PyObject *)self->callable, PyTuple_New(0), NULL); if (result == NULL) PyErr_Print(); } } static void Pattern_generate_a(Pattern *self) { int i, flag; PyObject *result; MYFLT *tm = Stream_getData((Stream *)self->time_stream); flag = 0; for (i=0; ibufsize; i++) { if (self->currentTime >= tm[i]) { flag = 1; self->currentTime = 0.; } self->currentTime += self->sampleToSec; } if (flag == 1 || self->init == 1) { self->init = 0; result = PyObject_Call((PyObject *)self->callable, PyTuple_New(0), NULL); if (result == NULL) PyErr_Print(); } } static void Pattern_setProcMode(Pattern *self) { int procmode = self->modebuffer[0]; switch (procmode) { case 0: self->proc_func_ptr = Pattern_generate_i; break; case 1: self->proc_func_ptr = Pattern_generate_a; break; } } static void Pattern_compute_next_data_frame(Pattern *self) { (*self->proc_func_ptr)(self); } static int Pattern_traverse(Pattern *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->callable); Py_VISIT(self->time); Py_VISIT(self->time_stream); return 0; } static int Pattern_clear(Pattern *self) { pyo_CLEAR Py_CLEAR(self->callable); Py_CLEAR(self->time); Py_CLEAR(self->time_stream); return 0; } static void Pattern_dealloc(Pattern* self) { pyo_DEALLOC Pattern_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Pattern_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *timetmp=NULL, *calltmp=NULL; Pattern *self; self = (Pattern *)type->tp_alloc(type, 0); self->time = PyFloat_FromDouble(1.); self->modebuffer[0] = 0; self->init = 1; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Pattern_compute_next_data_frame); self->mode_func_ptr = Pattern_setProcMode; Stream_setStreamActive(self->stream, 0); self->sampleToSec = 1. / self->sr; self->currentTime = 0.; static char *kwlist[] = {"callable", "time", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &calltmp, &timetmp)) Py_RETURN_NONE; if (calltmp) { PyObject_CallMethod((PyObject *)self, "setFunction", "O", calltmp); } if (timetmp) { PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Pattern_getServer(Pattern* self) { GET_SERVER }; static PyObject * Pattern_getStream(Pattern* self) { GET_STREAM }; static PyObject * Pattern_play(Pattern *self, PyObject *args, PyObject *kwds) { self->init = 1; PLAY }; static PyObject * Pattern_stop(Pattern *self) { STOP }; static PyObject * Pattern_setFunction(Pattern *self, PyObject *arg) { PyObject *tmp; if (! PyCallable_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function."); Py_INCREF(Py_None); return Py_None; } tmp = arg; Py_XDECREF(self->callable); Py_INCREF(tmp); self->callable = tmp; Py_INCREF(Py_None); return Py_None; } static PyObject * Pattern_setTime(Pattern *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->time); if (isNumber == 1) { self->time = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->time = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->time, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->time_stream); self->time_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Pattern_members[] = { {"server", T_OBJECT_EX, offsetof(Pattern, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Pattern, stream), 0, "Stream object."}, {"time", T_OBJECT_EX, offsetof(Pattern, time), 0, "Pattern time factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Pattern_methods[] = { {"getServer", (PyCFunction)Pattern_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Pattern_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Pattern_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Pattern_stop, METH_NOARGS, "Stops computing."}, {"setTime", (PyCFunction)Pattern_setTime, METH_O, "Sets time factor."}, {"setFunction", (PyCFunction)Pattern_setFunction, METH_O, "Sets the function to be called."}, {NULL} /* Sentinel */ }; PyTypeObject PatternType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Pattern_base", /*tp_name*/ sizeof(Pattern), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Pattern_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Pattern objects. Create a metronome.", /* tp_doc */ (traverseproc)Pattern_traverse, /* tp_traverse */ (inquiry)Pattern_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Pattern_methods, /* tp_methods */ Pattern_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Pattern_new, /* tp_new */ }; /***************/ /**** Score ****/ /***************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; char *fname; char curfname[100]; int last_value; } Score; static void Score_selector(Score *self) { int i, inval; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { inval = (int)in[i]; if (inval != self->last_value) { sprintf(self->curfname, "%s%i()\n", self->fname, inval); PyRun_SimpleString(self->curfname); self->last_value = inval; } } } static void Score_setProcMode(Score *self) { self->proc_func_ptr = Score_selector; } static void Score_compute_next_data_frame(Score *self) { (*self->proc_func_ptr)(self); } static int Score_traverse(Score *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Score_clear(Score *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Score_dealloc(Score* self) { pyo_DEALLOC Score_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Score_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp; Score *self; self = (Score *)type->tp_alloc(type, 0); self->last_value = -99; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Score_compute_next_data_frame); self->mode_func_ptr = Score_setProcMode; static char *kwlist[] = {"input", "fname", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|s", kwlist, &inputtmp, &self->fname)) Py_RETURN_NONE; INIT_INPUT_STREAM PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Score_getServer(Score* self) { GET_SERVER }; static PyObject * Score_getStream(Score* self) { GET_STREAM }; static PyObject * Score_play(Score *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Score_stop(Score *self) { STOP }; static PyMemberDef Score_members[] = { {"server", T_OBJECT_EX, offsetof(Score, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Score, stream), 0, "Stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef Score_methods[] = { {"getServer", (PyCFunction)Score_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Score_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Score_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Score_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject ScoreType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Score_base", /*tp_name*/ sizeof(Score), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Score_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Score objects. Calls numbered function from an integer count.", /* tp_doc */ (traverseproc)Score_traverse, /* tp_traverse */ (inquiry)Score_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Score_methods, /* tp_methods */ Score_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Score_new, /* tp_new */ }; /*****************/ /*** CallAfter ***/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *callable; PyObject *arg; MYFLT time; MYFLT sampleToSec; double currentTime; } CallAfter; static void CallAfter_generate(CallAfter *self) { int i; PyObject *tuple, *result; for (i=0; ibufsize; i++) { if (self->currentTime >= self->time) { if (self->arg == Py_None) tuple = PyTuple_New(0); else { tuple = PyTuple_New(1); PyTuple_SET_ITEM(tuple, 0, self->arg); } result = PyObject_Call(self->callable, tuple, NULL); if (result == NULL) PyErr_Print(); PyObject_CallMethod((PyObject *)self, "stop", NULL); break; } self->currentTime += self->sampleToSec; } } static void CallAfter_setProcMode(CallAfter *self) { self->proc_func_ptr = CallAfter_generate; } static void CallAfter_compute_next_data_frame(CallAfter *self) { (*self->proc_func_ptr)(self); } static int CallAfter_traverse(CallAfter *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->callable); Py_VISIT(self->arg); return 0; } static int CallAfter_clear(CallAfter *self) { pyo_CLEAR Py_CLEAR(self->callable); Py_CLEAR(self->arg); return 0; } static void CallAfter_dealloc(CallAfter* self) { pyo_DEALLOC CallAfter_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * CallAfter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *calltmp=NULL, *argtmp=NULL; CallAfter *self; self = (CallAfter *)type->tp_alloc(type, 0); self->time = 1.; self->arg = Py_None; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, CallAfter_compute_next_data_frame); self->mode_func_ptr = CallAfter_setProcMode; self->sampleToSec = 1. / self->sr; self->currentTime = 0.; static char *kwlist[] = {"callable", "time", "arg", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FO, kwlist, &calltmp, &self->time, &argtmp)) Py_RETURN_NONE; if (! PyCallable_Check(calltmp)) Py_RETURN_NONE; if (argtmp) { Py_DECREF(self->arg); Py_INCREF(argtmp); self->arg = argtmp; } Py_INCREF(calltmp); Py_XDECREF(self->callable); self->callable = calltmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * CallAfter_getServer(CallAfter* self) { GET_SERVER }; static PyObject * CallAfter_getStream(CallAfter* self) { GET_STREAM }; static PyObject * CallAfter_play(CallAfter *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * CallAfter_stop(CallAfter *self) { STOP }; static PyMemberDef CallAfter_members[] = { {"server", T_OBJECT_EX, offsetof(CallAfter, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(CallAfter, stream), 0, "Stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef CallAfter_methods[] = { {"getServer", (PyCFunction)CallAfter_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)CallAfter_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)CallAfter_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)CallAfter_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject CallAfterType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.CallAfter_base", /*tp_name*/ sizeof(CallAfter), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)CallAfter_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "CallAfter objects. Create a metronome.", /* tp_doc */ (traverseproc)CallAfter_traverse, /* tp_traverse */ (inquiry)CallAfter_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ CallAfter_methods, /* tp_methods */ CallAfter_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ CallAfter_new, /* tp_new */ };pyo/src/objects/arithmeticmodule.c0000644000175000017500000051157712652732202016621 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" /************/ /* M_Sin */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add } M_Sin; static void M_Sin_process(M_Sin *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = MYSIN(in[i]); } } static void M_Sin_postprocessing_ii(M_Sin *self) { POST_PROCESSING_II }; static void M_Sin_postprocessing_ai(M_Sin *self) { POST_PROCESSING_AI }; static void M_Sin_postprocessing_ia(M_Sin *self) { POST_PROCESSING_IA }; static void M_Sin_postprocessing_aa(M_Sin *self) { POST_PROCESSING_AA }; static void M_Sin_postprocessing_ireva(M_Sin *self) { POST_PROCESSING_IREVA }; static void M_Sin_postprocessing_areva(M_Sin *self) { POST_PROCESSING_AREVA }; static void M_Sin_postprocessing_revai(M_Sin *self) { POST_PROCESSING_REVAI }; static void M_Sin_postprocessing_revaa(M_Sin *self) { POST_PROCESSING_REVAA }; static void M_Sin_postprocessing_revareva(M_Sin *self) { POST_PROCESSING_REVAREVA }; static void M_Sin_setProcMode(M_Sin *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = M_Sin_process; switch (muladdmode) { case 0: self->muladd_func_ptr = M_Sin_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Sin_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Sin_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Sin_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Sin_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Sin_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Sin_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Sin_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Sin_postprocessing_revareva; break; } } static void M_Sin_compute_next_data_frame(M_Sin *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Sin_traverse(M_Sin *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int M_Sin_clear(M_Sin *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void M_Sin_dealloc(M_Sin* self) { pyo_DEALLOC M_Sin_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Sin_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; M_Sin *self; self = (M_Sin *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Sin_compute_next_data_frame); self->mode_func_ptr = M_Sin_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Sin_getServer(M_Sin* self) { GET_SERVER }; static PyObject * M_Sin_getStream(M_Sin* self) { GET_STREAM }; static PyObject * M_Sin_setMul(M_Sin *self, PyObject *arg) { SET_MUL }; static PyObject * M_Sin_setAdd(M_Sin *self, PyObject *arg) { SET_ADD }; static PyObject * M_Sin_setSub(M_Sin *self, PyObject *arg) { SET_SUB }; static PyObject * M_Sin_setDiv(M_Sin *self, PyObject *arg) { SET_DIV }; static PyObject * M_Sin_play(M_Sin *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Sin_out(M_Sin *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Sin_stop(M_Sin *self) { STOP }; static PyObject * M_Sin_multiply(M_Sin *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Sin_inplace_multiply(M_Sin *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Sin_add(M_Sin *self, PyObject *arg) { ADD }; static PyObject * M_Sin_inplace_add(M_Sin *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Sin_sub(M_Sin *self, PyObject *arg) { SUB }; static PyObject * M_Sin_inplace_sub(M_Sin *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Sin_div(M_Sin *self, PyObject *arg) { DIV }; static PyObject * M_Sin_inplace_div(M_Sin *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef M_Sin_members[] = { {"server", T_OBJECT_EX, offsetof(M_Sin, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Sin, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(M_Sin, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(M_Sin, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Sin, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Sin_methods[] = { {"getServer", (PyCFunction)M_Sin_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Sin_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Sin_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)M_Sin_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)M_Sin_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)M_Sin_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)M_Sin_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)M_Sin_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Sin_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Sin_as_number = { (binaryfunc)M_Sin_add, /*nb_add*/ (binaryfunc)M_Sin_sub, /*nb_subtract*/ (binaryfunc)M_Sin_multiply, /*nb_multiply*/ (binaryfunc)M_Sin_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Sin_inplace_add, /*inplace_add*/ (binaryfunc)M_Sin_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Sin_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Sin_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_SinType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Sin_base", /*tp_name*/ sizeof(M_Sin), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Sin_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Sin_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Sin objects. Performs sin function on audio samples.", /* tp_doc */ (traverseproc)M_Sin_traverse, /* tp_traverse */ (inquiry)M_Sin_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Sin_methods, /* tp_methods */ M_Sin_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Sin_new, /* tp_new */ }; /************/ /* M_Cos */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add } M_Cos; static void M_Cos_process(M_Cos *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = MYCOS(in[i]); } } static void M_Cos_postprocessing_ii(M_Cos *self) { POST_PROCESSING_II }; static void M_Cos_postprocessing_ai(M_Cos *self) { POST_PROCESSING_AI }; static void M_Cos_postprocessing_ia(M_Cos *self) { POST_PROCESSING_IA }; static void M_Cos_postprocessing_aa(M_Cos *self) { POST_PROCESSING_AA }; static void M_Cos_postprocessing_ireva(M_Cos *self) { POST_PROCESSING_IREVA }; static void M_Cos_postprocessing_areva(M_Cos *self) { POST_PROCESSING_AREVA }; static void M_Cos_postprocessing_revai(M_Cos *self) { POST_PROCESSING_REVAI }; static void M_Cos_postprocessing_revaa(M_Cos *self) { POST_PROCESSING_REVAA }; static void M_Cos_postprocessing_revareva(M_Cos *self) { POST_PROCESSING_REVAREVA }; static void M_Cos_setProcMode(M_Cos *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = M_Cos_process; switch (muladdmode) { case 0: self->muladd_func_ptr = M_Cos_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Cos_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Cos_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Cos_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Cos_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Cos_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Cos_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Cos_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Cos_postprocessing_revareva; break; } } static void M_Cos_compute_next_data_frame(M_Cos *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Cos_traverse(M_Cos *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int M_Cos_clear(M_Cos *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void M_Cos_dealloc(M_Cos* self) { pyo_DEALLOC M_Cos_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Cos_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; M_Cos *self; self = (M_Cos *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Cos_compute_next_data_frame); self->mode_func_ptr = M_Cos_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Cos_getServer(M_Cos* self) { GET_SERVER }; static PyObject * M_Cos_getStream(M_Cos* self) { GET_STREAM }; static PyObject * M_Cos_setMul(M_Cos *self, PyObject *arg) { SET_MUL }; static PyObject * M_Cos_setAdd(M_Cos *self, PyObject *arg) { SET_ADD }; static PyObject * M_Cos_setSub(M_Cos *self, PyObject *arg) { SET_SUB }; static PyObject * M_Cos_setDiv(M_Cos *self, PyObject *arg) { SET_DIV }; static PyObject * M_Cos_play(M_Cos *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Cos_out(M_Cos *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Cos_stop(M_Cos *self) { STOP }; static PyObject * M_Cos_multiply(M_Cos *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Cos_inplace_multiply(M_Cos *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Cos_add(M_Cos *self, PyObject *arg) { ADD }; static PyObject * M_Cos_inplace_add(M_Cos *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Cos_sub(M_Cos *self, PyObject *arg) { SUB }; static PyObject * M_Cos_inplace_sub(M_Cos *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Cos_div(M_Cos *self, PyObject *arg) { DIV }; static PyObject * M_Cos_inplace_div(M_Cos *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef M_Cos_members[] = { {"server", T_OBJECT_EX, offsetof(M_Cos, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Cos, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(M_Cos, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(M_Cos, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Cos, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Cos_methods[] = { {"getServer", (PyCFunction)M_Cos_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Cos_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Cos_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)M_Cos_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)M_Cos_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)M_Cos_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)M_Cos_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)M_Cos_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Cos_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Cos_as_number = { (binaryfunc)M_Cos_add, /*nb_add*/ (binaryfunc)M_Cos_sub, /*nb_subtract*/ (binaryfunc)M_Cos_multiply, /*nb_multiply*/ (binaryfunc)M_Cos_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Cos_inplace_add, /*inplace_add*/ (binaryfunc)M_Cos_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Cos_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Cos_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_CosType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Cos_base", /*tp_name*/ sizeof(M_Cos), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Cos_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Cos_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Cos objects. Performs sin function on audio samples.", /* tp_doc */ (traverseproc)M_Cos_traverse, /* tp_traverse */ (inquiry)M_Cos_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Cos_methods, /* tp_methods */ M_Cos_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Cos_new, /* tp_new */ }; /************/ /* M_Tan */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add } M_Tan; static void M_Tan_process(M_Tan *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = MYTAN(in[i]); } } static void M_Tan_postprocessing_ii(M_Tan *self) { POST_PROCESSING_II }; static void M_Tan_postprocessing_ai(M_Tan *self) { POST_PROCESSING_AI }; static void M_Tan_postprocessing_ia(M_Tan *self) { POST_PROCESSING_IA }; static void M_Tan_postprocessing_aa(M_Tan *self) { POST_PROCESSING_AA }; static void M_Tan_postprocessing_ireva(M_Tan *self) { POST_PROCESSING_IREVA }; static void M_Tan_postprocessing_areva(M_Tan *self) { POST_PROCESSING_AREVA }; static void M_Tan_postprocessing_revai(M_Tan *self) { POST_PROCESSING_REVAI }; static void M_Tan_postprocessing_revaa(M_Tan *self) { POST_PROCESSING_REVAA }; static void M_Tan_postprocessing_revareva(M_Tan *self) { POST_PROCESSING_REVAREVA }; static void M_Tan_setProcMode(M_Tan *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = M_Tan_process; switch (muladdmode) { case 0: self->muladd_func_ptr = M_Tan_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Tan_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Tan_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Tan_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Tan_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Tan_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Tan_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Tan_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Tan_postprocessing_revareva; break; } } static void M_Tan_compute_next_data_frame(M_Tan *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Tan_traverse(M_Tan *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int M_Tan_clear(M_Tan *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void M_Tan_dealloc(M_Tan* self) { pyo_DEALLOC M_Tan_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Tan_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; M_Tan *self; self = (M_Tan *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Tan_compute_next_data_frame); self->mode_func_ptr = M_Tan_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Tan_getServer(M_Tan* self) { GET_SERVER }; static PyObject * M_Tan_getStream(M_Tan* self) { GET_STREAM }; static PyObject * M_Tan_setMul(M_Tan *self, PyObject *arg) { SET_MUL }; static PyObject * M_Tan_setAdd(M_Tan *self, PyObject *arg) { SET_ADD }; static PyObject * M_Tan_setSub(M_Tan *self, PyObject *arg) { SET_SUB }; static PyObject * M_Tan_setDiv(M_Tan *self, PyObject *arg) { SET_DIV }; static PyObject * M_Tan_play(M_Tan *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Tan_out(M_Tan *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Tan_stop(M_Tan *self) { STOP }; static PyObject * M_Tan_multiply(M_Tan *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Tan_inplace_multiply(M_Tan *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Tan_add(M_Tan *self, PyObject *arg) { ADD }; static PyObject * M_Tan_inplace_add(M_Tan *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Tan_sub(M_Tan *self, PyObject *arg) { SUB }; static PyObject * M_Tan_inplace_sub(M_Tan *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Tan_div(M_Tan *self, PyObject *arg) { DIV }; static PyObject * M_Tan_inplace_div(M_Tan *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef M_Tan_members[] = { {"server", T_OBJECT_EX, offsetof(M_Tan, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Tan, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(M_Tan, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(M_Tan, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Tan, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Tan_methods[] = { {"getServer", (PyCFunction)M_Tan_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Tan_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Tan_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)M_Tan_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)M_Tan_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)M_Tan_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)M_Tan_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)M_Tan_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Tan_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Tan_as_number = { (binaryfunc)M_Tan_add, /*nb_add*/ (binaryfunc)M_Tan_sub, /*nb_subtract*/ (binaryfunc)M_Tan_multiply, /*nb_multiply*/ (binaryfunc)M_Tan_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Tan_inplace_add, /*inplace_add*/ (binaryfunc)M_Tan_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Tan_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Tan_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_TanType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Tan_base", /*tp_name*/ sizeof(M_Tan), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Tan_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Tan_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Tan objects. Performs sin function on audio samples.", /* tp_doc */ (traverseproc)M_Tan_traverse, /* tp_traverse */ (inquiry)M_Tan_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Tan_methods, /* tp_methods */ M_Tan_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Tan_new, /* tp_new */ }; /************/ /* M_Abs */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add } M_Abs; static void M_Abs_process(M_Abs *self) { int i; MYFLT inval; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { inval = in[i]; if (inval < 0.0) self->data[i] = -inval; else self->data[i] = inval; } } static void M_Abs_postprocessing_ii(M_Abs *self) { POST_PROCESSING_II }; static void M_Abs_postprocessing_ai(M_Abs *self) { POST_PROCESSING_AI }; static void M_Abs_postprocessing_ia(M_Abs *self) { POST_PROCESSING_IA }; static void M_Abs_postprocessing_aa(M_Abs *self) { POST_PROCESSING_AA }; static void M_Abs_postprocessing_ireva(M_Abs *self) { POST_PROCESSING_IREVA }; static void M_Abs_postprocessing_areva(M_Abs *self) { POST_PROCESSING_AREVA }; static void M_Abs_postprocessing_revai(M_Abs *self) { POST_PROCESSING_REVAI }; static void M_Abs_postprocessing_revaa(M_Abs *self) { POST_PROCESSING_REVAA }; static void M_Abs_postprocessing_revareva(M_Abs *self) { POST_PROCESSING_REVAREVA }; static void M_Abs_setProcMode(M_Abs *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = M_Abs_process; switch (muladdmode) { case 0: self->muladd_func_ptr = M_Abs_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Abs_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Abs_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Abs_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Abs_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Abs_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Abs_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Abs_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Abs_postprocessing_revareva; break; } } static void M_Abs_compute_next_data_frame(M_Abs *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Abs_traverse(M_Abs *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int M_Abs_clear(M_Abs *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void M_Abs_dealloc(M_Abs* self) { pyo_DEALLOC M_Abs_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Abs_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; M_Abs *self; self = (M_Abs *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Abs_compute_next_data_frame); self->mode_func_ptr = M_Abs_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Abs_getServer(M_Abs* self) { GET_SERVER }; static PyObject * M_Abs_getStream(M_Abs* self) { GET_STREAM }; static PyObject * M_Abs_setMul(M_Abs *self, PyObject *arg) { SET_MUL }; static PyObject * M_Abs_setAdd(M_Abs *self, PyObject *arg) { SET_ADD }; static PyObject * M_Abs_setSub(M_Abs *self, PyObject *arg) { SET_SUB }; static PyObject * M_Abs_setDiv(M_Abs *self, PyObject *arg) { SET_DIV }; static PyObject * M_Abs_play(M_Abs *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Abs_out(M_Abs *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Abs_stop(M_Abs *self) { STOP }; static PyObject * M_Abs_multiply(M_Abs *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Abs_inplace_multiply(M_Abs *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Abs_add(M_Abs *self, PyObject *arg) { ADD }; static PyObject * M_Abs_inplace_add(M_Abs *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Abs_sub(M_Abs *self, PyObject *arg) { SUB }; static PyObject * M_Abs_inplace_sub(M_Abs *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Abs_div(M_Abs *self, PyObject *arg) { DIV }; static PyObject * M_Abs_inplace_div(M_Abs *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef M_Abs_members[] = { {"server", T_OBJECT_EX, offsetof(M_Abs, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Abs, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(M_Abs, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(M_Abs, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Abs, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Abs_methods[] = { {"getServer", (PyCFunction)M_Abs_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Abs_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Abs_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)M_Abs_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)M_Abs_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)M_Abs_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)M_Abs_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)M_Abs_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Abs_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Abs_as_number = { (binaryfunc)M_Abs_add, /*nb_add*/ (binaryfunc)M_Abs_sub, /*nb_subtract*/ (binaryfunc)M_Abs_multiply, /*nb_multiply*/ (binaryfunc)M_Abs_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Abs_inplace_add, /*inplace_add*/ (binaryfunc)M_Abs_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Abs_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Abs_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_AbsType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Abs_base", /*tp_name*/ sizeof(M_Abs), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Abs_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Abs_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Abs objects. Performs abs function on audio samples.", /* tp_doc */ (traverseproc)M_Abs_traverse, /* tp_traverse */ (inquiry)M_Abs_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Abs_methods, /* tp_methods */ M_Abs_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Abs_new, /* tp_new */ }; /************/ /* M_Sqrt */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add } M_Sqrt; static void M_Sqrt_process(M_Sqrt *self) { int i; MYFLT inval; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { inval = in[i]; if (inval < 0.0) self->data[i] = 0.0; else self->data[i] = MYSQRT(inval); } } static void M_Sqrt_postprocessing_ii(M_Sqrt *self) { POST_PROCESSING_II }; static void M_Sqrt_postprocessing_ai(M_Sqrt *self) { POST_PROCESSING_AI }; static void M_Sqrt_postprocessing_ia(M_Sqrt *self) { POST_PROCESSING_IA }; static void M_Sqrt_postprocessing_aa(M_Sqrt *self) { POST_PROCESSING_AA }; static void M_Sqrt_postprocessing_ireva(M_Sqrt *self) { POST_PROCESSING_IREVA }; static void M_Sqrt_postprocessing_areva(M_Sqrt *self) { POST_PROCESSING_AREVA }; static void M_Sqrt_postprocessing_revai(M_Sqrt *self) { POST_PROCESSING_REVAI }; static void M_Sqrt_postprocessing_revaa(M_Sqrt *self) { POST_PROCESSING_REVAA }; static void M_Sqrt_postprocessing_revareva(M_Sqrt *self) { POST_PROCESSING_REVAREVA }; static void M_Sqrt_setProcMode(M_Sqrt *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = M_Sqrt_process; switch (muladdmode) { case 0: self->muladd_func_ptr = M_Sqrt_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Sqrt_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Sqrt_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Sqrt_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Sqrt_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Sqrt_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Sqrt_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Sqrt_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Sqrt_postprocessing_revareva; break; } } static void M_Sqrt_compute_next_data_frame(M_Sqrt *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Sqrt_traverse(M_Sqrt *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int M_Sqrt_clear(M_Sqrt *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void M_Sqrt_dealloc(M_Sqrt* self) { pyo_DEALLOC M_Sqrt_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Sqrt_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; M_Sqrt *self; self = (M_Sqrt *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Sqrt_compute_next_data_frame); self->mode_func_ptr = M_Sqrt_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Sqrt_getServer(M_Sqrt* self) { GET_SERVER }; static PyObject * M_Sqrt_getStream(M_Sqrt* self) { GET_STREAM }; static PyObject * M_Sqrt_setMul(M_Sqrt *self, PyObject *arg) { SET_MUL }; static PyObject * M_Sqrt_setAdd(M_Sqrt *self, PyObject *arg) { SET_ADD }; static PyObject * M_Sqrt_setSub(M_Sqrt *self, PyObject *arg) { SET_SUB }; static PyObject * M_Sqrt_setDiv(M_Sqrt *self, PyObject *arg) { SET_DIV }; static PyObject * M_Sqrt_play(M_Sqrt *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Sqrt_out(M_Sqrt *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Sqrt_stop(M_Sqrt *self) { STOP }; static PyObject * M_Sqrt_multiply(M_Sqrt *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Sqrt_inplace_multiply(M_Sqrt *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Sqrt_add(M_Sqrt *self, PyObject *arg) { ADD }; static PyObject * M_Sqrt_inplace_add(M_Sqrt *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Sqrt_sub(M_Sqrt *self, PyObject *arg) { SUB }; static PyObject * M_Sqrt_inplace_sub(M_Sqrt *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Sqrt_div(M_Sqrt *self, PyObject *arg) { DIV }; static PyObject * M_Sqrt_inplace_div(M_Sqrt *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef M_Sqrt_members[] = { {"server", T_OBJECT_EX, offsetof(M_Sqrt, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Sqrt, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(M_Sqrt, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(M_Sqrt, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Sqrt, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Sqrt_methods[] = { {"getServer", (PyCFunction)M_Sqrt_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Sqrt_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Sqrt_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)M_Sqrt_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)M_Sqrt_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)M_Sqrt_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)M_Sqrt_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)M_Sqrt_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Sqrt_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Sqrt_as_number = { (binaryfunc)M_Sqrt_add, /*nb_add*/ (binaryfunc)M_Sqrt_sub, /*nb_subtract*/ (binaryfunc)M_Sqrt_multiply, /*nb_multiply*/ (binaryfunc)M_Sqrt_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Sqrt_inplace_add, /*inplace_add*/ (binaryfunc)M_Sqrt_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Sqrt_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Sqrt_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_SqrtType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Sqrt_base", /*tp_name*/ sizeof(M_Sqrt), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Sqrt_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Sqrt_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Sqrt objects. Performs sqrt function on audio samples.", /* tp_doc */ (traverseproc)M_Sqrt_traverse, /* tp_traverse */ (inquiry)M_Sqrt_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Sqrt_methods, /* tp_methods */ M_Sqrt_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Sqrt_new, /* tp_new */ }; /************/ /* M_Log */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add } M_Log; static void M_Log_process(M_Log *self) { int i; MYFLT inval; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { inval = in[i]; if (inval <= 0.0) self->data[i] = 0.0; else self->data[i] = MYLOG(inval); } } static void M_Log_postprocessing_ii(M_Log *self) { POST_PROCESSING_II }; static void M_Log_postprocessing_ai(M_Log *self) { POST_PROCESSING_AI }; static void M_Log_postprocessing_ia(M_Log *self) { POST_PROCESSING_IA }; static void M_Log_postprocessing_aa(M_Log *self) { POST_PROCESSING_AA }; static void M_Log_postprocessing_ireva(M_Log *self) { POST_PROCESSING_IREVA }; static void M_Log_postprocessing_areva(M_Log *self) { POST_PROCESSING_AREVA }; static void M_Log_postprocessing_revai(M_Log *self) { POST_PROCESSING_REVAI }; static void M_Log_postprocessing_revaa(M_Log *self) { POST_PROCESSING_REVAA }; static void M_Log_postprocessing_revareva(M_Log *self) { POST_PROCESSING_REVAREVA }; static void M_Log_setProcMode(M_Log *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = M_Log_process; switch (muladdmode) { case 0: self->muladd_func_ptr = M_Log_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Log_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Log_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Log_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Log_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Log_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Log_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Log_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Log_postprocessing_revareva; break; } } static void M_Log_compute_next_data_frame(M_Log *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Log_traverse(M_Log *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int M_Log_clear(M_Log *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void M_Log_dealloc(M_Log* self) { pyo_DEALLOC M_Log_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Log_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; M_Log *self; self = (M_Log *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Log_compute_next_data_frame); self->mode_func_ptr = M_Log_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Log_getServer(M_Log* self) { GET_SERVER }; static PyObject * M_Log_getStream(M_Log* self) { GET_STREAM }; static PyObject * M_Log_setMul(M_Log *self, PyObject *arg) { SET_MUL }; static PyObject * M_Log_setAdd(M_Log *self, PyObject *arg) { SET_ADD }; static PyObject * M_Log_setSub(M_Log *self, PyObject *arg) { SET_SUB }; static PyObject * M_Log_setDiv(M_Log *self, PyObject *arg) { SET_DIV }; static PyObject * M_Log_play(M_Log *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Log_out(M_Log *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Log_stop(M_Log *self) { STOP }; static PyObject * M_Log_multiply(M_Log *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Log_inplace_multiply(M_Log *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Log_add(M_Log *self, PyObject *arg) { ADD }; static PyObject * M_Log_inplace_add(M_Log *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Log_sub(M_Log *self, PyObject *arg) { SUB }; static PyObject * M_Log_inplace_sub(M_Log *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Log_div(M_Log *self, PyObject *arg) { DIV }; static PyObject * M_Log_inplace_div(M_Log *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef M_Log_members[] = { {"server", T_OBJECT_EX, offsetof(M_Log, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Log, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(M_Log, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(M_Log, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Log, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Log_methods[] = { {"getServer", (PyCFunction)M_Log_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Log_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Log_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)M_Log_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)M_Log_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)M_Log_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)M_Log_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)M_Log_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Log_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Log_as_number = { (binaryfunc)M_Log_add, /*nb_add*/ (binaryfunc)M_Log_sub, /*nb_subtract*/ (binaryfunc)M_Log_multiply, /*nb_multiply*/ (binaryfunc)M_Log_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Log_inplace_add, /*inplace_add*/ (binaryfunc)M_Log_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Log_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Log_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_LogType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Log_base", /*tp_name*/ sizeof(M_Log), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Log_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Log_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Log objects. Performs natural log function on audio samples.", /* tp_doc */ (traverseproc)M_Log_traverse, /* tp_traverse */ (inquiry)M_Log_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Log_methods, /* tp_methods */ M_Log_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Log_new, /* tp_new */ }; /************/ /* M_Log10 */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add } M_Log10; static void M_Log10_process(M_Log10 *self) { int i; MYFLT inval; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { inval = in[i]; if (inval <= 0.0) self->data[i] = 0.0; else self->data[i] = MYLOG10(inval); } } static void M_Log10_postprocessing_ii(M_Log10 *self) { POST_PROCESSING_II }; static void M_Log10_postprocessing_ai(M_Log10 *self) { POST_PROCESSING_AI }; static void M_Log10_postprocessing_ia(M_Log10 *self) { POST_PROCESSING_IA }; static void M_Log10_postprocessing_aa(M_Log10 *self) { POST_PROCESSING_AA }; static void M_Log10_postprocessing_ireva(M_Log10 *self) { POST_PROCESSING_IREVA }; static void M_Log10_postprocessing_areva(M_Log10 *self) { POST_PROCESSING_AREVA }; static void M_Log10_postprocessing_revai(M_Log10 *self) { POST_PROCESSING_REVAI }; static void M_Log10_postprocessing_revaa(M_Log10 *self) { POST_PROCESSING_REVAA }; static void M_Log10_postprocessing_revareva(M_Log10 *self) { POST_PROCESSING_REVAREVA }; static void M_Log10_setProcMode(M_Log10 *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = M_Log10_process; switch (muladdmode) { case 0: self->muladd_func_ptr = M_Log10_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Log10_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Log10_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Log10_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Log10_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Log10_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Log10_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Log10_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Log10_postprocessing_revareva; break; } } static void M_Log10_compute_next_data_frame(M_Log10 *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Log10_traverse(M_Log10 *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int M_Log10_clear(M_Log10 *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void M_Log10_dealloc(M_Log10* self) { pyo_DEALLOC M_Log10_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Log10_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; M_Log10 *self; self = (M_Log10 *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Log10_compute_next_data_frame); self->mode_func_ptr = M_Log10_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Log10_getServer(M_Log10* self) { GET_SERVER }; static PyObject * M_Log10_getStream(M_Log10* self) { GET_STREAM }; static PyObject * M_Log10_setMul(M_Log10 *self, PyObject *arg) { SET_MUL }; static PyObject * M_Log10_setAdd(M_Log10 *self, PyObject *arg) { SET_ADD }; static PyObject * M_Log10_setSub(M_Log10 *self, PyObject *arg) { SET_SUB }; static PyObject * M_Log10_setDiv(M_Log10 *self, PyObject *arg) { SET_DIV }; static PyObject * M_Log10_play(M_Log10 *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Log10_out(M_Log10 *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Log10_stop(M_Log10 *self) { STOP }; static PyObject * M_Log10_multiply(M_Log10 *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Log10_inplace_multiply(M_Log10 *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Log10_add(M_Log10 *self, PyObject *arg) { ADD }; static PyObject * M_Log10_inplace_add(M_Log10 *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Log10_sub(M_Log10 *self, PyObject *arg) { SUB }; static PyObject * M_Log10_inplace_sub(M_Log10 *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Log10_div(M_Log10 *self, PyObject *arg) { DIV }; static PyObject * M_Log10_inplace_div(M_Log10 *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef M_Log10_members[] = { {"server", T_OBJECT_EX, offsetof(M_Log10, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Log10, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(M_Log10, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(M_Log10, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Log10, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Log10_methods[] = { {"getServer", (PyCFunction)M_Log10_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Log10_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Log10_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)M_Log10_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)M_Log10_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)M_Log10_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)M_Log10_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)M_Log10_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Log10_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Log10_as_number = { (binaryfunc)M_Log10_add, /*nb_add*/ (binaryfunc)M_Log10_sub, /*nb_subtract*/ (binaryfunc)M_Log10_multiply, /*nb_multiply*/ (binaryfunc)M_Log10_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Log10_inplace_add, /*inplace_add*/ (binaryfunc)M_Log10_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Log10_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Log10_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_Log10Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Log10_base", /*tp_name*/ sizeof(M_Log10), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Log10_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Log10_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Log10 objects. Performs base 10 log function on audio samples.", /* tp_doc */ (traverseproc)M_Log10_traverse, /* tp_traverse */ (inquiry)M_Log10_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Log10_methods, /* tp_methods */ M_Log10_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Log10_new, /* tp_new */ }; /************/ /* M_Log2 */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add } M_Log2; static void M_Log2_process(M_Log2 *self) { int i; MYFLT inval; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { inval = in[i]; if (inval <= 0.0) self->data[i] = 0.0; else self->data[i] = MYLOG2(inval); } } static void M_Log2_postprocessing_ii(M_Log2 *self) { POST_PROCESSING_II }; static void M_Log2_postprocessing_ai(M_Log2 *self) { POST_PROCESSING_AI }; static void M_Log2_postprocessing_ia(M_Log2 *self) { POST_PROCESSING_IA }; static void M_Log2_postprocessing_aa(M_Log2 *self) { POST_PROCESSING_AA }; static void M_Log2_postprocessing_ireva(M_Log2 *self) { POST_PROCESSING_IREVA }; static void M_Log2_postprocessing_areva(M_Log2 *self) { POST_PROCESSING_AREVA }; static void M_Log2_postprocessing_revai(M_Log2 *self) { POST_PROCESSING_REVAI }; static void M_Log2_postprocessing_revaa(M_Log2 *self) { POST_PROCESSING_REVAA }; static void M_Log2_postprocessing_revareva(M_Log2 *self) { POST_PROCESSING_REVAREVA }; static void M_Log2_setProcMode(M_Log2 *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = M_Log2_process; switch (muladdmode) { case 0: self->muladd_func_ptr = M_Log2_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Log2_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Log2_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Log2_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Log2_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Log2_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Log2_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Log2_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Log2_postprocessing_revareva; break; } } static void M_Log2_compute_next_data_frame(M_Log2 *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Log2_traverse(M_Log2 *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int M_Log2_clear(M_Log2 *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void M_Log2_dealloc(M_Log2* self) { pyo_DEALLOC M_Log2_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Log2_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; M_Log2 *self; self = (M_Log2 *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Log2_compute_next_data_frame); self->mode_func_ptr = M_Log2_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Log2_getServer(M_Log2* self) { GET_SERVER }; static PyObject * M_Log2_getStream(M_Log2* self) { GET_STREAM }; static PyObject * M_Log2_setMul(M_Log2 *self, PyObject *arg) { SET_MUL }; static PyObject * M_Log2_setAdd(M_Log2 *self, PyObject *arg) { SET_ADD }; static PyObject * M_Log2_setSub(M_Log2 *self, PyObject *arg) { SET_SUB }; static PyObject * M_Log2_setDiv(M_Log2 *self, PyObject *arg) { SET_DIV }; static PyObject * M_Log2_play(M_Log2 *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Log2_out(M_Log2 *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Log2_stop(M_Log2 *self) { STOP }; static PyObject * M_Log2_multiply(M_Log2 *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Log2_inplace_multiply(M_Log2 *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Log2_add(M_Log2 *self, PyObject *arg) { ADD }; static PyObject * M_Log2_inplace_add(M_Log2 *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Log2_sub(M_Log2 *self, PyObject *arg) { SUB }; static PyObject * M_Log2_inplace_sub(M_Log2 *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Log2_div(M_Log2 *self, PyObject *arg) { DIV }; static PyObject * M_Log2_inplace_div(M_Log2 *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef M_Log2_members[] = { {"server", T_OBJECT_EX, offsetof(M_Log2, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Log2, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(M_Log2, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(M_Log2, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Log2, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Log2_methods[] = { {"getServer", (PyCFunction)M_Log2_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Log2_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Log2_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)M_Log2_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)M_Log2_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)M_Log2_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)M_Log2_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)M_Log2_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Log2_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Log2_as_number = { (binaryfunc)M_Log2_add, /*nb_add*/ (binaryfunc)M_Log2_sub, /*nb_subtract*/ (binaryfunc)M_Log2_multiply, /*nb_multiply*/ (binaryfunc)M_Log2_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Log2_inplace_add, /*inplace_add*/ (binaryfunc)M_Log2_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Log2_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Log2_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_Log2Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Log2_base", /*tp_name*/ sizeof(M_Log2), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Log2_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Log2_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Log2 objects. Performs base 2 log function on audio samples.", /* tp_doc */ (traverseproc)M_Log2_traverse, /* tp_traverse */ (inquiry)M_Log2_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Log2_methods, /* tp_methods */ M_Log2_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Log2_new, /* tp_new */ }; /**************/ /* M_Pow object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *base; Stream *base_stream; PyObject *exponent; Stream *exponent_stream; int modebuffer[4]; } M_Pow; static void M_Pow_readframes_ii(M_Pow *self) { int i; MYFLT base = PyFloat_AS_DOUBLE(self->base); MYFLT exp = PyFloat_AS_DOUBLE(self->exponent); for (i=0; ibufsize; i++) { self->data[i] = MYPOW(base, exp); } } static void M_Pow_readframes_ai(M_Pow *self) { int i; MYFLT *base = Stream_getData((Stream *)self->base_stream); MYFLT exp = PyFloat_AS_DOUBLE(self->exponent); for (i=0; ibufsize; i++) { self->data[i] = MYPOW(base[i], exp); } } static void M_Pow_readframes_ia(M_Pow *self) { int i; MYFLT base = PyFloat_AS_DOUBLE(self->base); MYFLT *exp = Stream_getData((Stream *)self->exponent_stream); for (i=0; ibufsize; i++) { self->data[i] = MYPOW(base, exp[i]); } } static void M_Pow_readframes_aa(M_Pow *self) { int i; MYFLT *base = Stream_getData((Stream *)self->base_stream); MYFLT *exp = Stream_getData((Stream *)self->exponent_stream); for (i=0; ibufsize; i++) { self->data[i] = MYPOW(base[i], exp[i]); } } static void M_Pow_postprocessing_ii(M_Pow *self) { POST_PROCESSING_II }; static void M_Pow_postprocessing_ai(M_Pow *self) { POST_PROCESSING_AI }; static void M_Pow_postprocessing_ia(M_Pow *self) { POST_PROCESSING_IA }; static void M_Pow_postprocessing_aa(M_Pow *self) { POST_PROCESSING_AA }; static void M_Pow_postprocessing_ireva(M_Pow *self) { POST_PROCESSING_IREVA }; static void M_Pow_postprocessing_areva(M_Pow *self) { POST_PROCESSING_AREVA }; static void M_Pow_postprocessing_revai(M_Pow *self) { POST_PROCESSING_REVAI }; static void M_Pow_postprocessing_revaa(M_Pow *self) { POST_PROCESSING_REVAA }; static void M_Pow_postprocessing_revareva(M_Pow *self) { POST_PROCESSING_REVAREVA }; static void M_Pow_setProcMode(M_Pow *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = M_Pow_readframes_ii; break; case 1: self->proc_func_ptr = M_Pow_readframes_ai; break; case 10: self->proc_func_ptr = M_Pow_readframes_ia; break; case 11: self->proc_func_ptr = M_Pow_readframes_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = M_Pow_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Pow_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Pow_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Pow_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Pow_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Pow_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Pow_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Pow_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Pow_postprocessing_revareva; break; } } static void M_Pow_compute_next_data_frame(M_Pow *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Pow_traverse(M_Pow *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->exponent); Py_VISIT(self->exponent_stream); Py_VISIT(self->base); Py_VISIT(self->base_stream); return 0; } static int M_Pow_clear(M_Pow *self) { pyo_CLEAR Py_CLEAR(self->exponent); Py_CLEAR(self->exponent_stream); Py_CLEAR(self->base); Py_CLEAR(self->base_stream); return 0; } static void M_Pow_dealloc(M_Pow* self) { pyo_DEALLOC M_Pow_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Pow_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *basetmp=NULL, *exponenttmp=NULL, *multmp=NULL, *addtmp=NULL; M_Pow *self; self = (M_Pow *)type->tp_alloc(type, 0); self->base = PyFloat_FromDouble(10); self->exponent = PyFloat_FromDouble(1); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Pow_compute_next_data_frame); self->mode_func_ptr = M_Pow_setProcMode; static char *kwlist[] = {"base", "exponent", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &basetmp, &exponenttmp, &multmp, &addtmp)) Py_RETURN_NONE; if (basetmp) { PyObject_CallMethod((PyObject *)self, "setBase", "O", basetmp); } if (exponenttmp) { PyObject_CallMethod((PyObject *)self, "setExponent", "O", exponenttmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Pow_getServer(M_Pow* self) { GET_SERVER }; static PyObject * M_Pow_getStream(M_Pow* self) { GET_STREAM }; static PyObject * M_Pow_setMul(M_Pow *self, PyObject *arg) { SET_MUL }; static PyObject * M_Pow_setAdd(M_Pow *self, PyObject *arg) { SET_ADD }; static PyObject * M_Pow_setSub(M_Pow *self, PyObject *arg) { SET_SUB }; static PyObject * M_Pow_setDiv(M_Pow *self, PyObject *arg) { SET_DIV }; static PyObject * M_Pow_play(M_Pow *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Pow_out(M_Pow *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Pow_stop(M_Pow *self) { STOP }; static PyObject * M_Pow_multiply(M_Pow *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Pow_inplace_multiply(M_Pow *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Pow_add(M_Pow *self, PyObject *arg) { ADD }; static PyObject * M_Pow_inplace_add(M_Pow *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Pow_sub(M_Pow *self, PyObject *arg) { SUB }; static PyObject * M_Pow_inplace_sub(M_Pow *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Pow_div(M_Pow *self, PyObject *arg) { DIV }; static PyObject * M_Pow_inplace_div(M_Pow *self, PyObject *arg) { INPLACE_DIV }; static PyObject * M_Pow_setBase(M_Pow *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->base); if (isNumber == 1) { self->base = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->base = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->base, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->base_stream); self->base_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * M_Pow_setExponent(M_Pow *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->exponent); if (isNumber == 1) { self->exponent = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->exponent = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->exponent, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->exponent_stream); self->exponent_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef M_Pow_members[] = { {"server", T_OBJECT_EX, offsetof(M_Pow, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Pow, stream), 0, "Stream object."}, {"base", T_OBJECT_EX, offsetof(M_Pow, base), 0, "base composant."}, {"exponent", T_OBJECT_EX, offsetof(M_Pow, exponent), 0, "exponent composant."}, {"mul", T_OBJECT_EX, offsetof(M_Pow, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Pow, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Pow_methods[] = { {"getServer", (PyCFunction)M_Pow_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Pow_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Pow_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)M_Pow_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)M_Pow_stop, METH_NOARGS, "Stops computing."}, {"setBase", (PyCFunction)M_Pow_setBase, METH_O, "Sets base."}, {"setExponent", (PyCFunction)M_Pow_setExponent, METH_O, "Sets exponent."}, {"setMul", (PyCFunction)M_Pow_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)M_Pow_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)M_Pow_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Pow_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Pow_as_number = { (binaryfunc)M_Pow_add, /*nb_add*/ (binaryfunc)M_Pow_sub, /*nb_subtract*/ (binaryfunc)M_Pow_multiply, /*nb_multiply*/ (binaryfunc)M_Pow_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Pow_inplace_add, /*inplace_add*/ (binaryfunc)M_Pow_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Pow_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Pow_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_PowType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Pow_base", /*tp_name*/ sizeof(M_Pow), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Pow_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Pow_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Pow objects. Power function.", /* tp_doc */ (traverseproc)M_Pow_traverse, /* tp_traverse */ (inquiry)M_Pow_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Pow_methods, /* tp_methods */ M_Pow_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Pow_new, /* tp_new */ }; /**************/ /* M_Atan2 object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *b; Stream *b_stream; PyObject *a; Stream *a_stream; int modebuffer[4]; } M_Atan2; static void M_Atan2_readframes_ii(M_Atan2 *self) { int i; MYFLT b = PyFloat_AS_DOUBLE(self->b); MYFLT a = PyFloat_AS_DOUBLE(self->a); for (i=0; ibufsize; i++) { self->data[i] = MYATAN2(b, a); } } static void M_Atan2_readframes_ai(M_Atan2 *self) { int i; MYFLT *b = Stream_getData((Stream *)self->b_stream); MYFLT a = PyFloat_AS_DOUBLE(self->a); for (i=0; ibufsize; i++) { self->data[i] = MYATAN2(b[i], a); } } static void M_Atan2_readframes_ia(M_Atan2 *self) { int i; MYFLT b = PyFloat_AS_DOUBLE(self->b); MYFLT *a = Stream_getData((Stream *)self->a_stream); for (i=0; ibufsize; i++) { self->data[i] = MYATAN2(b, a[i]); } } static void M_Atan2_readframes_aa(M_Atan2 *self) { int i; MYFLT *b = Stream_getData((Stream *)self->b_stream); MYFLT *a = Stream_getData((Stream *)self->a_stream); for (i=0; ibufsize; i++) { self->data[i] = MYATAN2(b[i], a[i]); } } static void M_Atan2_postprocessing_ii(M_Atan2 *self) { POST_PROCESSING_II }; static void M_Atan2_postprocessing_ai(M_Atan2 *self) { POST_PROCESSING_AI }; static void M_Atan2_postprocessing_ia(M_Atan2 *self) { POST_PROCESSING_IA }; static void M_Atan2_postprocessing_aa(M_Atan2 *self) { POST_PROCESSING_AA }; static void M_Atan2_postprocessing_ireva(M_Atan2 *self) { POST_PROCESSING_IREVA }; static void M_Atan2_postprocessing_areva(M_Atan2 *self) { POST_PROCESSING_AREVA }; static void M_Atan2_postprocessing_revai(M_Atan2 *self) { POST_PROCESSING_REVAI }; static void M_Atan2_postprocessing_revaa(M_Atan2 *self) { POST_PROCESSING_REVAA }; static void M_Atan2_postprocessing_revareva(M_Atan2 *self) { POST_PROCESSING_REVAREVA }; static void M_Atan2_setProcMode(M_Atan2 *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = M_Atan2_readframes_ii; break; case 1: self->proc_func_ptr = M_Atan2_readframes_ai; break; case 10: self->proc_func_ptr = M_Atan2_readframes_ia; break; case 11: self->proc_func_ptr = M_Atan2_readframes_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = M_Atan2_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Atan2_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Atan2_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Atan2_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Atan2_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Atan2_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Atan2_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Atan2_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Atan2_postprocessing_revareva; break; } } static void M_Atan2_compute_next_data_frame(M_Atan2 *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Atan2_traverse(M_Atan2 *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->b); Py_VISIT(self->b_stream); Py_VISIT(self->a); Py_VISIT(self->a_stream); return 0; } static int M_Atan2_clear(M_Atan2 *self) { pyo_CLEAR Py_CLEAR(self->b); Py_CLEAR(self->b_stream); Py_CLEAR(self->a); Py_CLEAR(self->a_stream); return 0; } static void M_Atan2_dealloc(M_Atan2* self) { pyo_DEALLOC M_Atan2_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Atan2_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *btmp=NULL, *atmp=NULL, *multmp=NULL, *addtmp=NULL; M_Atan2 *self; self = (M_Atan2 *)type->tp_alloc(type, 0); self->a = PyFloat_FromDouble(1); self->b = PyFloat_FromDouble(1); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Atan2_compute_next_data_frame); self->mode_func_ptr = M_Atan2_setProcMode; static char *kwlist[] = {"b", "a", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &btmp, &atmp, &multmp, &addtmp)) Py_RETURN_NONE; if (btmp) { PyObject_CallMethod((PyObject *)self, "setB", "O", btmp); } if (atmp) { PyObject_CallMethod((PyObject *)self, "setA", "O", atmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Atan2_getServer(M_Atan2* self) { GET_SERVER }; static PyObject * M_Atan2_getStream(M_Atan2* self) { GET_STREAM }; static PyObject * M_Atan2_setMul(M_Atan2 *self, PyObject *arg) { SET_MUL }; static PyObject * M_Atan2_setAdd(M_Atan2 *self, PyObject *arg) { SET_ADD }; static PyObject * M_Atan2_setSub(M_Atan2 *self, PyObject *arg) { SET_SUB }; static PyObject * M_Atan2_setDiv(M_Atan2 *self, PyObject *arg) { SET_DIV }; static PyObject * M_Atan2_play(M_Atan2 *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Atan2_out(M_Atan2 *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Atan2_stop(M_Atan2 *self) { STOP }; static PyObject * M_Atan2_multiply(M_Atan2 *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Atan2_inplace_multiply(M_Atan2 *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Atan2_add(M_Atan2 *self, PyObject *arg) { ADD }; static PyObject * M_Atan2_inplace_add(M_Atan2 *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Atan2_sub(M_Atan2 *self, PyObject *arg) { SUB }; static PyObject * M_Atan2_inplace_sub(M_Atan2 *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Atan2_div(M_Atan2 *self, PyObject *arg) { DIV }; static PyObject * M_Atan2_inplace_div(M_Atan2 *self, PyObject *arg) { INPLACE_DIV }; static PyObject * M_Atan2_setB(M_Atan2 *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->b); if (isNumber == 1) { self->b = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->b = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->b, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->b_stream); self->b_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * M_Atan2_setA(M_Atan2 *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->a); if (isNumber == 1) { self->a = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->a = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->a, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->a_stream); self->a_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef M_Atan2_members[] = { {"server", T_OBJECT_EX, offsetof(M_Atan2, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Atan2, stream), 0, "Stream object."}, {"b", T_OBJECT_EX, offsetof(M_Atan2, b), 0, "b composant."}, {"a", T_OBJECT_EX, offsetof(M_Atan2, a), 0, "a composant."}, {"mul", T_OBJECT_EX, offsetof(M_Atan2, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Atan2, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Atan2_methods[] = { {"getServer", (PyCFunction)M_Atan2_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Atan2_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Atan2_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)M_Atan2_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)M_Atan2_stop, METH_NOARGS, "Stops computing."}, {"setB", (PyCFunction)M_Atan2_setB, METH_O, "Sets b."}, {"setA", (PyCFunction)M_Atan2_setA, METH_O, "Sets a."}, {"setMul", (PyCFunction)M_Atan2_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)M_Atan2_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)M_Atan2_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Atan2_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Atan2_as_number = { (binaryfunc)M_Atan2_add, /*nb_add*/ (binaryfunc)M_Atan2_sub, /*nb_subtract*/ (binaryfunc)M_Atan2_multiply, /*nb_multiply*/ (binaryfunc)M_Atan2_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Atan2_inplace_add, /*inplace_add*/ (binaryfunc)M_Atan2_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Atan2_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Atan2_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_Atan2Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Atan2_base", /*tp_name*/ sizeof(M_Atan2), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Atan2_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Atan2_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Atan2 objects. Atan2er function.", /* tp_doc */ (traverseproc)M_Atan2_traverse, /* tp_traverse */ (inquiry)M_Atan2_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Atan2_methods, /* tp_methods */ M_Atan2_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Atan2_new, /* tp_new */ }; /************/ /* M_Floor */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add } M_Floor; static void M_Floor_process(M_Floor *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = MYFLOOR(in[i]); } } static void M_Floor_postprocessing_ii(M_Floor *self) { POST_PROCESSING_II }; static void M_Floor_postprocessing_ai(M_Floor *self) { POST_PROCESSING_AI }; static void M_Floor_postprocessing_ia(M_Floor *self) { POST_PROCESSING_IA }; static void M_Floor_postprocessing_aa(M_Floor *self) { POST_PROCESSING_AA }; static void M_Floor_postprocessing_ireva(M_Floor *self) { POST_PROCESSING_IREVA }; static void M_Floor_postprocessing_areva(M_Floor *self) { POST_PROCESSING_AREVA }; static void M_Floor_postprocessing_revai(M_Floor *self) { POST_PROCESSING_REVAI }; static void M_Floor_postprocessing_revaa(M_Floor *self) { POST_PROCESSING_REVAA }; static void M_Floor_postprocessing_revareva(M_Floor *self) { POST_PROCESSING_REVAREVA }; static void M_Floor_setProcMode(M_Floor *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = M_Floor_process; switch (muladdmode) { case 0: self->muladd_func_ptr = M_Floor_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Floor_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Floor_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Floor_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Floor_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Floor_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Floor_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Floor_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Floor_postprocessing_revareva; break; } } static void M_Floor_compute_next_data_frame(M_Floor *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Floor_traverse(M_Floor *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int M_Floor_clear(M_Floor *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void M_Floor_dealloc(M_Floor* self) { pyo_DEALLOC M_Floor_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Floor_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; M_Floor *self; self = (M_Floor *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Floor_compute_next_data_frame); self->mode_func_ptr = M_Floor_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Floor_getServer(M_Floor* self) { GET_SERVER }; static PyObject * M_Floor_getStream(M_Floor* self) { GET_STREAM }; static PyObject * M_Floor_setMul(M_Floor *self, PyObject *arg) { SET_MUL }; static PyObject * M_Floor_setAdd(M_Floor *self, PyObject *arg) { SET_ADD }; static PyObject * M_Floor_setSub(M_Floor *self, PyObject *arg) { SET_SUB }; static PyObject * M_Floor_setDiv(M_Floor *self, PyObject *arg) { SET_DIV }; static PyObject * M_Floor_play(M_Floor *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Floor_out(M_Floor *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Floor_stop(M_Floor *self) { STOP }; static PyObject * M_Floor_multiply(M_Floor *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Floor_inplace_multiply(M_Floor *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Floor_add(M_Floor *self, PyObject *arg) { ADD }; static PyObject * M_Floor_inplace_add(M_Floor *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Floor_sub(M_Floor *self, PyObject *arg) { SUB }; static PyObject * M_Floor_inplace_sub(M_Floor *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Floor_div(M_Floor *self, PyObject *arg) { DIV }; static PyObject * M_Floor_inplace_div(M_Floor *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef M_Floor_members[] = { {"server", T_OBJECT_EX, offsetof(M_Floor, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Floor, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(M_Floor, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(M_Floor, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Floor, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Floor_methods[] = { {"getServer", (PyCFunction)M_Floor_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Floor_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Floor_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)M_Floor_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)M_Floor_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)M_Floor_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)M_Floor_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)M_Floor_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Floor_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Floor_as_number = { (binaryfunc)M_Floor_add, /*nb_add*/ (binaryfunc)M_Floor_sub, /*nb_subtract*/ (binaryfunc)M_Floor_multiply, /*nb_multiply*/ (binaryfunc)M_Floor_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Floor_inplace_add, /*inplace_add*/ (binaryfunc)M_Floor_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Floor_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Floor_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_FloorType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Floor_base", /*tp_name*/ sizeof(M_Floor), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Floor_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Floor_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Floor objects. Performs sqrt function on audio samples.", /* tp_doc */ (traverseproc)M_Floor_traverse, /* tp_traverse */ (inquiry)M_Floor_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Floor_methods, /* tp_methods */ M_Floor_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Floor_new, /* tp_new */ }; /************/ /* M_Ceil */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add } M_Ceil; static void M_Ceil_process(M_Ceil *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = MYCEIL(in[i]); } } static void M_Ceil_postprocessing_ii(M_Ceil *self) { POST_PROCESSING_II }; static void M_Ceil_postprocessing_ai(M_Ceil *self) { POST_PROCESSING_AI }; static void M_Ceil_postprocessing_ia(M_Ceil *self) { POST_PROCESSING_IA }; static void M_Ceil_postprocessing_aa(M_Ceil *self) { POST_PROCESSING_AA }; static void M_Ceil_postprocessing_ireva(M_Ceil *self) { POST_PROCESSING_IREVA }; static void M_Ceil_postprocessing_areva(M_Ceil *self) { POST_PROCESSING_AREVA }; static void M_Ceil_postprocessing_revai(M_Ceil *self) { POST_PROCESSING_REVAI }; static void M_Ceil_postprocessing_revaa(M_Ceil *self) { POST_PROCESSING_REVAA }; static void M_Ceil_postprocessing_revareva(M_Ceil *self) { POST_PROCESSING_REVAREVA }; static void M_Ceil_setProcMode(M_Ceil *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = M_Ceil_process; switch (muladdmode) { case 0: self->muladd_func_ptr = M_Ceil_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Ceil_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Ceil_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Ceil_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Ceil_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Ceil_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Ceil_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Ceil_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Ceil_postprocessing_revareva; break; } } static void M_Ceil_compute_next_data_frame(M_Ceil *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Ceil_traverse(M_Ceil *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int M_Ceil_clear(M_Ceil *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void M_Ceil_dealloc(M_Ceil* self) { pyo_DEALLOC M_Ceil_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Ceil_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; M_Ceil *self; self = (M_Ceil *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Ceil_compute_next_data_frame); self->mode_func_ptr = M_Ceil_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Ceil_getServer(M_Ceil* self) { GET_SERVER }; static PyObject * M_Ceil_getStream(M_Ceil* self) { GET_STREAM }; static PyObject * M_Ceil_setMul(M_Ceil *self, PyObject *arg) { SET_MUL }; static PyObject * M_Ceil_setAdd(M_Ceil *self, PyObject *arg) { SET_ADD }; static PyObject * M_Ceil_setSub(M_Ceil *self, PyObject *arg) { SET_SUB }; static PyObject * M_Ceil_setDiv(M_Ceil *self, PyObject *arg) { SET_DIV }; static PyObject * M_Ceil_play(M_Ceil *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Ceil_out(M_Ceil *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Ceil_stop(M_Ceil *self) { STOP }; static PyObject * M_Ceil_multiply(M_Ceil *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Ceil_inplace_multiply(M_Ceil *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Ceil_add(M_Ceil *self, PyObject *arg) { ADD }; static PyObject * M_Ceil_inplace_add(M_Ceil *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Ceil_sub(M_Ceil *self, PyObject *arg) { SUB }; static PyObject * M_Ceil_inplace_sub(M_Ceil *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Ceil_div(M_Ceil *self, PyObject *arg) { DIV }; static PyObject * M_Ceil_inplace_div(M_Ceil *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef M_Ceil_members[] = { {"server", T_OBJECT_EX, offsetof(M_Ceil, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Ceil, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(M_Ceil, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(M_Ceil, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Ceil, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Ceil_methods[] = { {"getServer", (PyCFunction)M_Ceil_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Ceil_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Ceil_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)M_Ceil_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)M_Ceil_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)M_Ceil_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)M_Ceil_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)M_Ceil_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Ceil_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Ceil_as_number = { (binaryfunc)M_Ceil_add, /*nb_add*/ (binaryfunc)M_Ceil_sub, /*nb_subtract*/ (binaryfunc)M_Ceil_multiply, /*nb_multiply*/ (binaryfunc)M_Ceil_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Ceil_inplace_add, /*inplace_add*/ (binaryfunc)M_Ceil_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Ceil_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Ceil_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_CeilType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Ceil_base", /*tp_name*/ sizeof(M_Ceil), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Ceil_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Ceil_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Ceil objects. Performs ceil function on audio samples.", /* tp_doc */ (traverseproc)M_Ceil_traverse, /* tp_traverse */ (inquiry)M_Ceil_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Ceil_methods, /* tp_methods */ M_Ceil_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Ceil_new, /* tp_new */ }; /************/ /* M_Round */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add } M_Round; static void M_Round_process(M_Round *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = MYROUND(in[i]); } } static void M_Round_postprocessing_ii(M_Round *self) { POST_PROCESSING_II }; static void M_Round_postprocessing_ai(M_Round *self) { POST_PROCESSING_AI }; static void M_Round_postprocessing_ia(M_Round *self) { POST_PROCESSING_IA }; static void M_Round_postprocessing_aa(M_Round *self) { POST_PROCESSING_AA }; static void M_Round_postprocessing_ireva(M_Round *self) { POST_PROCESSING_IREVA }; static void M_Round_postprocessing_areva(M_Round *self) { POST_PROCESSING_AREVA }; static void M_Round_postprocessing_revai(M_Round *self) { POST_PROCESSING_REVAI }; static void M_Round_postprocessing_revaa(M_Round *self) { POST_PROCESSING_REVAA }; static void M_Round_postprocessing_revareva(M_Round *self) { POST_PROCESSING_REVAREVA }; static void M_Round_setProcMode(M_Round *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = M_Round_process; switch (muladdmode) { case 0: self->muladd_func_ptr = M_Round_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Round_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Round_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Round_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Round_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Round_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Round_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Round_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Round_postprocessing_revareva; break; } } static void M_Round_compute_next_data_frame(M_Round *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Round_traverse(M_Round *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int M_Round_clear(M_Round *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void M_Round_dealloc(M_Round* self) { pyo_DEALLOC M_Round_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Round_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; M_Round *self; self = (M_Round *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Round_compute_next_data_frame); self->mode_func_ptr = M_Round_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Round_getServer(M_Round* self) { GET_SERVER }; static PyObject * M_Round_getStream(M_Round* self) { GET_STREAM }; static PyObject * M_Round_setMul(M_Round *self, PyObject *arg) { SET_MUL }; static PyObject * M_Round_setAdd(M_Round *self, PyObject *arg) { SET_ADD }; static PyObject * M_Round_setSub(M_Round *self, PyObject *arg) { SET_SUB }; static PyObject * M_Round_setDiv(M_Round *self, PyObject *arg) { SET_DIV }; static PyObject * M_Round_play(M_Round *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Round_out(M_Round *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Round_stop(M_Round *self) { STOP }; static PyObject * M_Round_multiply(M_Round *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Round_inplace_multiply(M_Round *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Round_add(M_Round *self, PyObject *arg) { ADD }; static PyObject * M_Round_inplace_add(M_Round *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Round_sub(M_Round *self, PyObject *arg) { SUB }; static PyObject * M_Round_inplace_sub(M_Round *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Round_div(M_Round *self, PyObject *arg) { DIV }; static PyObject * M_Round_inplace_div(M_Round *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef M_Round_members[] = { {"server", T_OBJECT_EX, offsetof(M_Round, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Round, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(M_Round, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(M_Round, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Round, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Round_methods[] = { {"getServer", (PyCFunction)M_Round_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Round_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Round_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)M_Round_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)M_Round_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)M_Round_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)M_Round_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)M_Round_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Round_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Round_as_number = { (binaryfunc)M_Round_add, /*nb_add*/ (binaryfunc)M_Round_sub, /*nb_subtract*/ (binaryfunc)M_Round_multiply, /*nb_multiply*/ (binaryfunc)M_Round_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Round_inplace_add, /*inplace_add*/ (binaryfunc)M_Round_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Round_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Round_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_RoundType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Round_base", /*tp_name*/ sizeof(M_Round), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Round_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Round_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Round objects. Performs sqrt function on audio samples.", /* tp_doc */ (traverseproc)M_Round_traverse, /* tp_traverse */ (inquiry)M_Round_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Round_methods, /* tp_methods */ M_Round_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Round_new, /* tp_new */ }; /************/ /* M_Tanh */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add } M_Tanh; static void M_Tanh_process(M_Tanh *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = MYTANH(in[i]); } } static void M_Tanh_postprocessing_ii(M_Tanh *self) { POST_PROCESSING_II }; static void M_Tanh_postprocessing_ai(M_Tanh *self) { POST_PROCESSING_AI }; static void M_Tanh_postprocessing_ia(M_Tanh *self) { POST_PROCESSING_IA }; static void M_Tanh_postprocessing_aa(M_Tanh *self) { POST_PROCESSING_AA }; static void M_Tanh_postprocessing_ireva(M_Tanh *self) { POST_PROCESSING_IREVA }; static void M_Tanh_postprocessing_areva(M_Tanh *self) { POST_PROCESSING_AREVA }; static void M_Tanh_postprocessing_revai(M_Tanh *self) { POST_PROCESSING_REVAI }; static void M_Tanh_postprocessing_revaa(M_Tanh *self) { POST_PROCESSING_REVAA }; static void M_Tanh_postprocessing_revareva(M_Tanh *self) { POST_PROCESSING_REVAREVA }; static void M_Tanh_setProcMode(M_Tanh *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = M_Tanh_process; switch (muladdmode) { case 0: self->muladd_func_ptr = M_Tanh_postprocessing_ii; break; case 1: self->muladd_func_ptr = M_Tanh_postprocessing_ai; break; case 2: self->muladd_func_ptr = M_Tanh_postprocessing_revai; break; case 10: self->muladd_func_ptr = M_Tanh_postprocessing_ia; break; case 11: self->muladd_func_ptr = M_Tanh_postprocessing_aa; break; case 12: self->muladd_func_ptr = M_Tanh_postprocessing_revaa; break; case 20: self->muladd_func_ptr = M_Tanh_postprocessing_ireva; break; case 21: self->muladd_func_ptr = M_Tanh_postprocessing_areva; break; case 22: self->muladd_func_ptr = M_Tanh_postprocessing_revareva; break; } } static void M_Tanh_compute_next_data_frame(M_Tanh *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int M_Tanh_traverse(M_Tanh *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int M_Tanh_clear(M_Tanh *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void M_Tanh_dealloc(M_Tanh* self) { pyo_DEALLOC M_Tanh_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * M_Tanh_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; M_Tanh *self; self = (M_Tanh *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, M_Tanh_compute_next_data_frame); self->mode_func_ptr = M_Tanh_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * M_Tanh_getServer(M_Tanh* self) { GET_SERVER }; static PyObject * M_Tanh_getStream(M_Tanh* self) { GET_STREAM }; static PyObject * M_Tanh_setMul(M_Tanh *self, PyObject *arg) { SET_MUL }; static PyObject * M_Tanh_setAdd(M_Tanh *self, PyObject *arg) { SET_ADD }; static PyObject * M_Tanh_setSub(M_Tanh *self, PyObject *arg) { SET_SUB }; static PyObject * M_Tanh_setDiv(M_Tanh *self, PyObject *arg) { SET_DIV }; static PyObject * M_Tanh_play(M_Tanh *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * M_Tanh_out(M_Tanh *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * M_Tanh_stop(M_Tanh *self) { STOP }; static PyObject * M_Tanh_multiply(M_Tanh *self, PyObject *arg) { MULTIPLY }; static PyObject * M_Tanh_inplace_multiply(M_Tanh *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * M_Tanh_add(M_Tanh *self, PyObject *arg) { ADD }; static PyObject * M_Tanh_inplace_add(M_Tanh *self, PyObject *arg) { INPLACE_ADD }; static PyObject * M_Tanh_sub(M_Tanh *self, PyObject *arg) { SUB }; static PyObject * M_Tanh_inplace_sub(M_Tanh *self, PyObject *arg) { INPLACE_SUB }; static PyObject * M_Tanh_div(M_Tanh *self, PyObject *arg) { DIV }; static PyObject * M_Tanh_inplace_div(M_Tanh *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef M_Tanh_members[] = { {"server", T_OBJECT_EX, offsetof(M_Tanh, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(M_Tanh, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(M_Tanh, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(M_Tanh, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(M_Tanh, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef M_Tanh_methods[] = { {"getServer", (PyCFunction)M_Tanh_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)M_Tanh_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)M_Tanh_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)M_Tanh_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)M_Tanh_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)M_Tanh_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)M_Tanh_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)M_Tanh_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)M_Tanh_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods M_Tanh_as_number = { (binaryfunc)M_Tanh_add, /*nb_add*/ (binaryfunc)M_Tanh_sub, /*nb_subtract*/ (binaryfunc)M_Tanh_multiply, /*nb_multiply*/ (binaryfunc)M_Tanh_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)M_Tanh_inplace_add, /*inplace_add*/ (binaryfunc)M_Tanh_inplace_sub, /*inplace_subtract*/ (binaryfunc)M_Tanh_inplace_multiply, /*inplace_multiply*/ (binaryfunc)M_Tanh_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject M_TanhType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.M_Tanh_base", /*tp_name*/ sizeof(M_Tanh), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)M_Tanh_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &M_Tanh_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "M_Tanh objects. Performs tanh function on audio samples.", /* tp_doc */ (traverseproc)M_Tanh_traverse, /* tp_traverse */ (inquiry)M_Tanh_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ M_Tanh_methods, /* tp_methods */ M_Tanh_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ M_Tanh_new, /* tp_new */ };pyo/src/objects/convolvemodule.c0000644000175000017500000026263712652732202016323 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "tablemodule.h" static MYFLT BLACKMAN2[257] = {0.0, 0.00001355457612407795, 0.00005422714831165853, 0.00012204424012042525, 0.00021705003118953348, 0.00033930631782219667, 0.0004888924578373699, 0.00066590529972627988, 0.00087045909615995898, 0.0011026854019042381, 0.0013627329562085205, 0.0016507675497451635, 0.001966971876186191, 0.0023115453685137038, 0.0026847040201710415, 0.0030866801911709624, 0.0035177223992877149, 0.0039780950964686118, 0.004468078430611172, 0.0049879679928611226, 0.0055380745505964057, 0.0061187237662708727, 0.0067302559023018349, 0.0073730255121936678, 0.0080474011180991928, 0.0087537648750297542, 0.0094925122219332442, 0.010264051519867853, 0.011068803677508544, 0.011907201764231275, 0.012779690611027246, 0.013686726399509554, 0.014628776239280425, 0.015606317733936455, 0.016619838535996113, 0.017669835891040944, 0.018756816171369962, 0.019881294399473233, 0.021043793761637002, 0.022244845112000651, 0.023484986467390646, 0.024764762493264474, 0.026084723981101995, 0.027445427317589366, 0.028847433945943753, 0.030291309819735913, 0.031777624849569003, 0.033306952342980187, 0.034879868437934558, 0.036496951530286398, 0.038158781695585731, 0.039865940105613923, 0.041619008440034494, 0.043418568293550078, 0.045265200578957936, 0.047159484926502321, 0.04910199907992175, 0.051093318289594611, 0.053134014703186641, 0.055224656754207603, 0.05736580854888524, 0.059558029251766974, 0.061801872470459936, 0.064097885639923663, 0.066446609406726198, 0.068848577013680551, 0.071304313685273069, 0.073814336014300028, 0.076379151350125907, 0.078999257188976796, 0.081675140566682625, 0.08440727745428013, 0.08719613215688693, 0.090042156716257177, 0.092945790317425406, 0.095907458699845349, 0.09892757357342627, 0.10200653203986923, 0.10514471601969966, 0.10834249168539431, 0.11160020890099166, 0.11491820066857752, 0.11829678258202875, 0.12173625228839696, 0.12523688895730928, 0.12879895275875847, 0.13242268434965018, 0.1361083043694708, 0.13985601294543293, 0.14366598920745235, 0.14753839081330203, 0.15147335348428598, 0.15547099055176727, 0.15953139251487919, 0.16365462660974361, 0.16784073639051059, 0.17208974132253127, 0.17640163638796383, 0.18077639170410914, 0.18521395215476394, 0.18971423703487098, 0.19427713970874003, 0.19890252728210264, 0.2035902402882592, 0.20834009238856521, 0.21315187008749686, 0.218025332462529, 0.22296021090904578, 0.22795620890049961, 0.23301300176402318, 0.2381302364716896, 0.24330753144760825, 0.24854447639103289, 0.25384063211565033, 0.25919553040520765, 0.26460867388562637, 0.27007953591374234, 0.27560756048280166, 0.28119216214482828, 0.28683272594997611, 0.29252860740296116, 0.29827913243666476, 0.30408359740298374, 0.30994126908099884, 0.31585138470251517, 0.3218131519950253, 0.32782574924213004, 0.33388832536144369, 0.33999999999999991, 0.34615986364716356, 0.35236697776504228, 0.35862037493638421, 0.36491905902993321, 0.37126200538320747, 0.37764816100265119, 0.38407644478110459, 0.39054574773252188, 0.39705493324385926, 0.40360283734404451, 0.41018826898992783, 0.41681001036910403, 0.42346681721948765, 0.43015741916550887, 0.43688052007079137, 0.44363479840716119, 0.45041890763982673, 0.45723147662855934, 0.46407111004469437, 0.47093638880376354, 0.47782587051356035, 0.4847380899374274, 0.49167155947254987, 0.49862476964302743, 0.50559618960748731, 0.51258426768099419, 0.51958743187100298, 0.526604090427091, 0.53363263240419834, 0.54067142823909731, 0.5477188303398014, 0.55477317368762102, 0.5618327764515586, 0.56889594061473336, 0.57596095261251634, 0.58302608398204925, 0.59008959202281352, 0.5971497204679086, 0.60420470016569239, 0.61125274977143074, 0.61829207644859363, 0.62532087657943414, 0.63233733648447599, 0.63933963315053088, 0.64632593496686574, 0.65329440246912585, 0.66024318909062385, 0.66717044192059383, 0.67407430246900757, 0.68095290743754511, 0.68780438949630818, 0.69462687806585954, 0.70141850010417084, 0.70817738089805216, 0.71490164485864349, 0.72158941632053231, 0.7282388203440715, 0.73484798352045921, 0.74141503477914861, 0.74793810619714429, 0.75441533380975301, 0.76084485842234006, 0.76722482642265344, 0.77355339059327366, 0.77982871092374229, 0.78604895542192688, 0.7922123009241796, 0.79831693390384428, 0.80436105127766677, 0.81034286120967125, 0.81626058391205358, 0.82211245244265874, 0.82789671349859684, 0.83361162820556423, 0.83925547290243352, 0.84482653992067935, 0.85032313835820861, 0.85574359484716933, 0.86108625431531149, 0.86634948074047979, 0.87153165789781828, 0.87663119009927604, 0.88164650292500113, 0.88657604394621592, 0.89141828343917606, 0.89617171508981341, 0.90083485668867092, 0.90540625081574555, 0.90988446551485458, 0.91426809495715211, 0.9185557600934271, 0.92274610929481327, 0.92683781898156326, 0.93082959423952683, 0.93472016942399416, 0.93850830875056723, 0.94219280687272511, 0.94577248944576608, 0.94924621367680617, 0.9526128688605292, 0.95587137690038915, 0.95902069281497004, 0.96205980522922363, 0.96498773685030803, 0.96780354492775944, 0.97050632169774165, 0.97309519481112294, 0.97556932774514038, 0.97792792019842123, 0.9801702084691396, 0.98229546581609617, 0.98430300280251803, 0.98619216762238726, 0.98796234640911229, 0.98961296352637218, 0.99114348184096723, 0.99255340297752515, 0.99384226755491845, 0.99500965540426034, 0.99605518576835683, 0.99697851748250432, 0.99777934913652766, 0.99845741921797138, 0.99901250623636195, 0.99944442882846996, 0.99975304584451585, 0.99993825641526857, 1.0}; /************/ /* Convolve */ /************/ typedef struct { pyo_audio_HEAD PyObject *table; PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add MYFLT *input_tmp; int size; int count; } Convolve; static void Convolve_filters(Convolve *self) { int i,j,tmp_count; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *impulse = TableStream_getData(self->table); for (i=0; ibufsize; i++) { self->data[i] = 0.0; tmp_count = self->count; for(j=0; jsize; j++) { if (tmp_count < 0) tmp_count += self->size; self->data[i] += self->input_tmp[tmp_count--] * impulse[j]; } self->count++; if (self->count == self->size) self->count = 0; self->input_tmp[self->count] = in[i]; } } static void Convolve_postprocessing_ii(Convolve *self) { POST_PROCESSING_II }; static void Convolve_postprocessing_ai(Convolve *self) { POST_PROCESSING_AI }; static void Convolve_postprocessing_ia(Convolve *self) { POST_PROCESSING_IA }; static void Convolve_postprocessing_aa(Convolve *self) { POST_PROCESSING_AA }; static void Convolve_postprocessing_ireva(Convolve *self) { POST_PROCESSING_IREVA }; static void Convolve_postprocessing_areva(Convolve *self) { POST_PROCESSING_AREVA }; static void Convolve_postprocessing_revai(Convolve *self) { POST_PROCESSING_REVAI }; static void Convolve_postprocessing_revaa(Convolve *self) { POST_PROCESSING_REVAA }; static void Convolve_postprocessing_revareva(Convolve *self) { POST_PROCESSING_REVAREVA }; static void Convolve_setProcMode(Convolve *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Convolve_filters; switch (muladdmode) { case 0: self->muladd_func_ptr = Convolve_postprocessing_ii; break; case 1: self->muladd_func_ptr = Convolve_postprocessing_ai; break; case 2: self->muladd_func_ptr = Convolve_postprocessing_revai; break; case 10: self->muladd_func_ptr = Convolve_postprocessing_ia; break; case 11: self->muladd_func_ptr = Convolve_postprocessing_aa; break; case 12: self->muladd_func_ptr = Convolve_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Convolve_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Convolve_postprocessing_areva; break; case 22: self->muladd_func_ptr = Convolve_postprocessing_revareva; break; } } static void Convolve_compute_next_data_frame(Convolve *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Convolve_traverse(Convolve *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->table); return 0; } static int Convolve_clear(Convolve *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->table); return 0; } static void Convolve_dealloc(Convolve* self) { pyo_DEALLOC free(self->input_tmp); Convolve_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Convolve_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *tabletmp, *multmp=NULL, *addtmp=NULL; Convolve *self; self = (Convolve *)type->tp_alloc(type, 0); self->count = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Convolve_compute_next_data_frame); self->mode_func_ptr = Convolve_setProcMode; static char *kwlist[] = {"input", "table", "size", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOi|OO", kwlist, &inputtmp, &tabletmp, &self->size, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of Convolve must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); self->input_tmp = (MYFLT *)realloc(self->input_tmp, self->size * sizeof(MYFLT)); for (i=0; isize; i++) { self->input_tmp[i] = 0.0; } return (PyObject *)self; } static PyObject * Convolve_getServer(Convolve* self) { GET_SERVER }; static PyObject * Convolve_getStream(Convolve* self) { GET_STREAM }; static PyObject * Convolve_setMul(Convolve *self, PyObject *arg) { SET_MUL }; static PyObject * Convolve_setAdd(Convolve *self, PyObject *arg) { SET_ADD }; static PyObject * Convolve_setSub(Convolve *self, PyObject *arg) { SET_SUB }; static PyObject * Convolve_setDiv(Convolve *self, PyObject *arg) { SET_DIV }; static PyObject * Convolve_play(Convolve *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Convolve_out(Convolve *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Convolve_stop(Convolve *self) { STOP }; static PyObject * Convolve_multiply(Convolve *self, PyObject *arg) { MULTIPLY }; static PyObject * Convolve_inplace_multiply(Convolve *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Convolve_add(Convolve *self, PyObject *arg) { ADD }; static PyObject * Convolve_inplace_add(Convolve *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Convolve_sub(Convolve *self, PyObject *arg) { SUB }; static PyObject * Convolve_inplace_sub(Convolve *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Convolve_div(Convolve *self, PyObject *arg) { DIV }; static PyObject * Convolve_inplace_div(Convolve *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Convolve_getTable(Convolve* self) { Py_INCREF(self->table); return self->table; }; static PyObject * Convolve_setTable(Convolve *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Convolve_members[] = { {"server", T_OBJECT_EX, offsetof(Convolve, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Convolve, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Convolve, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(Convolve, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Convolve, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Convolve_methods[] = { {"getTable", (PyCFunction)Convolve_getTable, METH_NOARGS, "Returns impulse response table object."}, {"getServer", (PyCFunction)Convolve_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Convolve_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Convolve_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Convolve_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Convolve_stop, METH_NOARGS, "Stops computing."}, {"setTable", (PyCFunction)Convolve_setTable, METH_O, "Sets inpulse response table."}, {"setMul", (PyCFunction)Convolve_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)Convolve_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)Convolve_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Convolve_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Convolve_as_number = { (binaryfunc)Convolve_add, /*nb_add*/ (binaryfunc)Convolve_sub, /*nb_subtract*/ (binaryfunc)Convolve_multiply, /*nb_multiply*/ (binaryfunc)Convolve_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Convolve_inplace_add, /*inplace_add*/ (binaryfunc)Convolve_inplace_sub, /*inplace_subtract*/ (binaryfunc)Convolve_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Convolve_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ConvolveType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Convolve_base", /*tp_name*/ sizeof(Convolve), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Convolve_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Convolve_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Convolve objects. Implements a circular convolution.", /* tp_doc */ (traverseproc)Convolve_traverse, /* tp_traverse */ (inquiry)Convolve_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Convolve_methods, /* tp_methods */ Convolve_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Convolve_new, /* tp_new */ }; /************/ /* IRWinSinc */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *bandwidth; Stream *bandwidth_stream; int modebuffer[4]; // need at least 2 slots for mul & add MYFLT *impulse; MYFLT *impulse_tmp; MYFLT *input_tmp; int count; int filtertype; int order; int size; int changed; MYFLT last_freq; MYFLT last_bandwidth; } IRWinSinc; static void IRWinSinc_alloc_memory(IRWinSinc *self) { int i; if ((self->order % 2) != 0) self->order += 1; self->size = self->order + 1; self->input_tmp = (MYFLT *)realloc(self->input_tmp, self->size * sizeof(MYFLT)); self->impulse = (MYFLT *)realloc(self->impulse, self->size * sizeof(MYFLT)); self->impulse_tmp = (MYFLT *)realloc(self->impulse_tmp, self->size * sizeof(MYFLT)); for (i=0; isize; i++) { self->input_tmp[i] = self->impulse[i] = self->impulse_tmp[i] = 0.0; } } static void IRWinSinc_create_impulse(IRWinSinc *self, MYFLT freq, MYFLT bandwidth) { int i, half, ipart; MYFLT val, fpart, sum, invSum, env, envPointer, envPointerScaling, sincScaling, w; half = self->order / 2; sum = 0.0; envPointerScaling = 1.0 / self->size * 512.0; sincScaling = self->order / 2.0; if (freq < 1) freq = 1.0; else if (freq > (self->sr*0.5)) freq = self->sr*0.5; if (bandwidth < 1) bandwidth = 1.0; else if (bandwidth > (self->sr*0.5)) bandwidth = self->sr*0.5; if (self->filtertype <= 1) w = TWOPI * freq / self->sr; else w = TWOPI * (freq - bandwidth / 2.0) / self->sr; /* LOWPASS */ for (i=0; iimpulse[i] = val; } sum *= 2.0; sum += w; invSum = 1.0 / sum; self->impulse[half] = w * invSum; for (i=0; iimpulse[i] *= invSum; } for (i=half+1; isize; i++) { self->impulse[i] = self->impulse[self->order-i]; } /* HIGHPASS */ if (self->filtertype == 1) { for (i=0; isize; i++) { self->impulse[i] = -self->impulse[i]; } self->impulse[half] = self->impulse[half] + 1.0; } /* BANDREJECT */ if (self->filtertype >= 2) { sum = 0.0; w = TWOPI * (freq + bandwidth / 2.0) / self->sr; for (i=0; iimpulse_tmp[i] = val; } sum *= 2.0; sum += w; invSum = 1.0 / sum; self->impulse_tmp[half] = w * invSum; for (i=0; iimpulse_tmp[i] *= invSum; } for (i=half+1; isize; i++) { self->impulse_tmp[i] = self->impulse_tmp[self->order-i]; } for (i=0; isize; i++) { self->impulse_tmp[i] = -self->impulse_tmp[i]; } self->impulse_tmp[half] = self->impulse_tmp[half] + 1.0; for (i=0; isize; i++) { self->impulse[i] = self->impulse[i] + self->impulse_tmp[i]; } /* BANDPASS */ if (self->filtertype == 3) { for (i=0; isize; i++) { self->impulse[i] = -self->impulse[i]; } self->impulse[half] = self->impulse[half] + 1.0; } } } static void IRWinSinc_filters(IRWinSinc *self) { int i,j,tmp_count; MYFLT freq, bw; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->modebuffer[2] == 0) freq = PyFloat_AS_DOUBLE(self->freq); else { MYFLT *fr = Stream_getData((Stream *)self->freq_stream); freq = fr[0]; } if (self->modebuffer[3] == 0) bw = PyFloat_AS_DOUBLE(self->bandwidth); else { MYFLT *band = Stream_getData((Stream *)self->bandwidth_stream); bw = band[0]; } if (freq != self->last_freq || bw != self->last_bandwidth || self->changed == 1) { IRWinSinc_create_impulse(self, freq, bw); self->last_freq = freq; self->last_bandwidth = bw; self->changed = 0; } for (i=0; ibufsize; i++) { self->data[i] = 0.0; tmp_count = self->count; for(j=0; jsize; j++) { if (tmp_count < 0) tmp_count += self->size; self->data[i] += self->input_tmp[tmp_count--] * self->impulse[j]; } self->count++; if (self->count == self->size) self->count = 0; self->input_tmp[self->count] = in[i]; } } static void IRWinSinc_postprocessing_ii(IRWinSinc *self) { POST_PROCESSING_II }; static void IRWinSinc_postprocessing_ai(IRWinSinc *self) { POST_PROCESSING_AI }; static void IRWinSinc_postprocessing_ia(IRWinSinc *self) { POST_PROCESSING_IA }; static void IRWinSinc_postprocessing_aa(IRWinSinc *self) { POST_PROCESSING_AA }; static void IRWinSinc_postprocessing_ireva(IRWinSinc *self) { POST_PROCESSING_IREVA }; static void IRWinSinc_postprocessing_areva(IRWinSinc *self) { POST_PROCESSING_AREVA }; static void IRWinSinc_postprocessing_revai(IRWinSinc *self) { POST_PROCESSING_REVAI }; static void IRWinSinc_postprocessing_revaa(IRWinSinc *self) { POST_PROCESSING_REVAA }; static void IRWinSinc_postprocessing_revareva(IRWinSinc *self) { POST_PROCESSING_REVAREVA }; static void IRWinSinc_setProcMode(IRWinSinc *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = IRWinSinc_filters; switch (muladdmode) { case 0: self->muladd_func_ptr = IRWinSinc_postprocessing_ii; break; case 1: self->muladd_func_ptr = IRWinSinc_postprocessing_ai; break; case 2: self->muladd_func_ptr = IRWinSinc_postprocessing_revai; break; case 10: self->muladd_func_ptr = IRWinSinc_postprocessing_ia; break; case 11: self->muladd_func_ptr = IRWinSinc_postprocessing_aa; break; case 12: self->muladd_func_ptr = IRWinSinc_postprocessing_revaa; break; case 20: self->muladd_func_ptr = IRWinSinc_postprocessing_ireva; break; case 21: self->muladd_func_ptr = IRWinSinc_postprocessing_areva; break; case 22: self->muladd_func_ptr = IRWinSinc_postprocessing_revareva; break; } } static void IRWinSinc_compute_next_data_frame(IRWinSinc *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int IRWinSinc_traverse(IRWinSinc *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->bandwidth); Py_VISIT(self->bandwidth_stream); return 0; } static int IRWinSinc_clear(IRWinSinc *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->bandwidth); Py_CLEAR(self->bandwidth_stream); return 0; } static void IRWinSinc_dealloc(IRWinSinc* self) { pyo_DEALLOC free(self->input_tmp); free(self->impulse); free(self->impulse_tmp); IRWinSinc_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * IRWinSinc_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *bandwidthtmp=NULL, *multmp=NULL, *addtmp=NULL; IRWinSinc *self; self = (IRWinSinc *)type->tp_alloc(type, 0); self->last_freq = -1.0; self->last_bandwidth = -1.0; self->freq = PyFloat_FromDouble(1000.0); self->bandwidth = PyFloat_FromDouble(500.0); self->filtertype = 0; self->order = 256; self->count = 0; self->changed = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, IRWinSinc_compute_next_data_frame); self->mode_func_ptr = IRWinSinc_setProcMode; static char *kwlist[] = {"input", "freq", "bw", "type", "order", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOiiOO", kwlist, &inputtmp, &freqtmp, &bandwidthtmp, &self->filtertype, &self->order, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (bandwidthtmp) { PyObject_CallMethod((PyObject *)self, "setBandwidth", "O", bandwidthtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); IRWinSinc_alloc_memory(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * IRWinSinc_getServer(IRWinSinc* self) { GET_SERVER }; static PyObject * IRWinSinc_getStream(IRWinSinc* self) { GET_STREAM }; static PyObject * IRWinSinc_setMul(IRWinSinc *self, PyObject *arg) { SET_MUL }; static PyObject * IRWinSinc_setAdd(IRWinSinc *self, PyObject *arg) { SET_ADD }; static PyObject * IRWinSinc_setSub(IRWinSinc *self, PyObject *arg) { SET_SUB }; static PyObject * IRWinSinc_setDiv(IRWinSinc *self, PyObject *arg) { SET_DIV }; static PyObject * IRWinSinc_play(IRWinSinc *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * IRWinSinc_out(IRWinSinc *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * IRWinSinc_stop(IRWinSinc *self) { STOP }; static PyObject * IRWinSinc_multiply(IRWinSinc *self, PyObject *arg) { MULTIPLY }; static PyObject * IRWinSinc_inplace_multiply(IRWinSinc *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * IRWinSinc_add(IRWinSinc *self, PyObject *arg) { ADD }; static PyObject * IRWinSinc_inplace_add(IRWinSinc *self, PyObject *arg) { INPLACE_ADD }; static PyObject * IRWinSinc_sub(IRWinSinc *self, PyObject *arg) { SUB }; static PyObject * IRWinSinc_inplace_sub(IRWinSinc *self, PyObject *arg) { INPLACE_SUB }; static PyObject * IRWinSinc_div(IRWinSinc *self, PyObject *arg) { DIV }; static PyObject * IRWinSinc_inplace_div(IRWinSinc *self, PyObject *arg) { INPLACE_DIV }; static PyObject * IRWinSinc_setFreq(IRWinSinc *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * IRWinSinc_setBandwidth(IRWinSinc *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->bandwidth); if (isNumber == 1) { self->bandwidth = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->bandwidth = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->bandwidth, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->bandwidth_stream); self->bandwidth_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * IRWinSinc_setType(IRWinSinc *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { self->filtertype = PyInt_AsLong(arg); self->changed = 1; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef IRWinSinc_members[] = { {"server", T_OBJECT_EX, offsetof(IRWinSinc, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(IRWinSinc, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(IRWinSinc, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(IRWinSinc, freq), 0, "Cutoff or center frequency."}, {"bandwidth", T_OBJECT_EX, offsetof(IRWinSinc, bandwidth), 0, "Bandwidth, in Hz, for bandreject and bandpass filters."}, {"mul", T_OBJECT_EX, offsetof(IRWinSinc, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(IRWinSinc, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef IRWinSinc_methods[] = { {"getServer", (PyCFunction)IRWinSinc_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)IRWinSinc_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)IRWinSinc_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)IRWinSinc_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)IRWinSinc_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)IRWinSinc_setFreq, METH_O, "Sets center/cutoff frequency."}, {"setBandwidth", (PyCFunction)IRWinSinc_setBandwidth, METH_O, "Sets bandwidth in Hz."}, {"setType", (PyCFunction)IRWinSinc_setType, METH_O, "Sets filter type factor."}, {"setMul", (PyCFunction)IRWinSinc_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)IRWinSinc_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)IRWinSinc_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)IRWinSinc_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods IRWinSinc_as_number = { (binaryfunc)IRWinSinc_add, /*nb_add*/ (binaryfunc)IRWinSinc_sub, /*nb_subtract*/ (binaryfunc)IRWinSinc_multiply, /*nb_multiply*/ (binaryfunc)IRWinSinc_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)IRWinSinc_inplace_add, /*inplace_add*/ (binaryfunc)IRWinSinc_inplace_sub, /*inplace_subtract*/ (binaryfunc)IRWinSinc_inplace_multiply, /*inplace_multiply*/ (binaryfunc)IRWinSinc_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject IRWinSincType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.IRWinSinc_base", /*tp_name*/ sizeof(IRWinSinc), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)IRWinSinc_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &IRWinSinc_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "IRWinSinc objects. Windowed-sinc filter.", /* tp_doc */ (traverseproc)IRWinSinc_traverse, /* tp_traverse */ (inquiry)IRWinSinc_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ IRWinSinc_methods, /* tp_methods */ IRWinSinc_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ IRWinSinc_new, /* tp_new */ }; /************/ /* IRAverage */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add MYFLT *impulse; MYFLT *input_tmp; int count; int order; int size; } IRAverage; static void IRAverage_alloc_memory(IRAverage *self) { int i; MYFLT val, sum; if ((self->order % 2) != 0) self->order += 1; self->size = self->order + 1; self->input_tmp = (MYFLT *)realloc(self->input_tmp, self->size * sizeof(MYFLT)); self->impulse = (MYFLT *)realloc(self->impulse, self->size * sizeof(MYFLT)); sum = 0.0; for (i=0; isize; i++) { self->input_tmp[i] = 0.0; val = 0.42 - 0.5 * MYCOS(TWOPI*i/self->order) + 0.08 * MYCOS(2.0*TWOPI*i/self->order); self->impulse[i] = val; sum += val; } for (i=0; isize; i++) { self->impulse[i] /= sum; } } static void IRAverage_filters(IRAverage *self) { int i,j,tmp_count; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = 0.0; tmp_count = self->count; for(j=0; jsize; j++) { if (tmp_count < 0) tmp_count += self->size; self->data[i] += self->input_tmp[tmp_count--] * self->impulse[j]; } self->count++; if (self->count == self->size) self->count = 0; self->input_tmp[self->count] = in[i]; } } static void IRAverage_postprocessing_ii(IRAverage *self) { POST_PROCESSING_II }; static void IRAverage_postprocessing_ai(IRAverage *self) { POST_PROCESSING_AI }; static void IRAverage_postprocessing_ia(IRAverage *self) { POST_PROCESSING_IA }; static void IRAverage_postprocessing_aa(IRAverage *self) { POST_PROCESSING_AA }; static void IRAverage_postprocessing_ireva(IRAverage *self) { POST_PROCESSING_IREVA }; static void IRAverage_postprocessing_areva(IRAverage *self) { POST_PROCESSING_AREVA }; static void IRAverage_postprocessing_revai(IRAverage *self) { POST_PROCESSING_REVAI }; static void IRAverage_postprocessing_revaa(IRAverage *self) { POST_PROCESSING_REVAA }; static void IRAverage_postprocessing_revareva(IRAverage *self) { POST_PROCESSING_REVAREVA }; static void IRAverage_setProcMode(IRAverage *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = IRAverage_filters; switch (muladdmode) { case 0: self->muladd_func_ptr = IRAverage_postprocessing_ii; break; case 1: self->muladd_func_ptr = IRAverage_postprocessing_ai; break; case 2: self->muladd_func_ptr = IRAverage_postprocessing_revai; break; case 10: self->muladd_func_ptr = IRAverage_postprocessing_ia; break; case 11: self->muladd_func_ptr = IRAverage_postprocessing_aa; break; case 12: self->muladd_func_ptr = IRAverage_postprocessing_revaa; break; case 20: self->muladd_func_ptr = IRAverage_postprocessing_ireva; break; case 21: self->muladd_func_ptr = IRAverage_postprocessing_areva; break; case 22: self->muladd_func_ptr = IRAverage_postprocessing_revareva; break; } } static void IRAverage_compute_next_data_frame(IRAverage *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int IRAverage_traverse(IRAverage *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int IRAverage_clear(IRAverage *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void IRAverage_dealloc(IRAverage* self) { pyo_DEALLOC free(self->input_tmp); free(self->impulse); IRAverage_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * IRAverage_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; IRAverage *self; self = (IRAverage *)type->tp_alloc(type, 0); self->order = 32; self->count = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, IRAverage_compute_next_data_frame); self->mode_func_ptr = IRAverage_setProcMode; static char *kwlist[] = {"input", "order", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &inputtmp, &self->order, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); IRAverage_alloc_memory(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * IRAverage_getServer(IRAverage* self) { GET_SERVER }; static PyObject * IRAverage_getStream(IRAverage* self) { GET_STREAM }; static PyObject * IRAverage_setMul(IRAverage *self, PyObject *arg) { SET_MUL }; static PyObject * IRAverage_setAdd(IRAverage *self, PyObject *arg) { SET_ADD }; static PyObject * IRAverage_setSub(IRAverage *self, PyObject *arg) { SET_SUB }; static PyObject * IRAverage_setDiv(IRAverage *self, PyObject *arg) { SET_DIV }; static PyObject * IRAverage_play(IRAverage *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * IRAverage_out(IRAverage *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * IRAverage_stop(IRAverage *self) { STOP }; static PyObject * IRAverage_multiply(IRAverage *self, PyObject *arg) { MULTIPLY }; static PyObject * IRAverage_inplace_multiply(IRAverage *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * IRAverage_add(IRAverage *self, PyObject *arg) { ADD }; static PyObject * IRAverage_inplace_add(IRAverage *self, PyObject *arg) { INPLACE_ADD }; static PyObject * IRAverage_sub(IRAverage *self, PyObject *arg) { SUB }; static PyObject * IRAverage_inplace_sub(IRAverage *self, PyObject *arg) { INPLACE_SUB }; static PyObject * IRAverage_div(IRAverage *self, PyObject *arg) { DIV }; static PyObject * IRAverage_inplace_div(IRAverage *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef IRAverage_members[] = { {"server", T_OBJECT_EX, offsetof(IRAverage, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(IRAverage, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(IRAverage, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(IRAverage, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(IRAverage, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef IRAverage_methods[] = { {"getServer", (PyCFunction)IRAverage_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)IRAverage_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)IRAverage_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)IRAverage_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)IRAverage_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)IRAverage_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)IRAverage_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)IRAverage_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)IRAverage_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods IRAverage_as_number = { (binaryfunc)IRAverage_add, /*nb_add*/ (binaryfunc)IRAverage_sub, /*nb_subtract*/ (binaryfunc)IRAverage_multiply, /*nb_multiply*/ (binaryfunc)IRAverage_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)IRAverage_inplace_add, /*inplace_add*/ (binaryfunc)IRAverage_inplace_sub, /*inplace_subtract*/ (binaryfunc)IRAverage_inplace_multiply, /*inplace_multiply*/ (binaryfunc)IRAverage_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject IRAverageType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.IRAverage_base", /*tp_name*/ sizeof(IRAverage), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)IRAverage_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &IRAverage_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "IRAverage objects. Moving average FIR filter.", /* tp_doc */ (traverseproc)IRAverage_traverse, /* tp_traverse */ (inquiry)IRAverage_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ IRAverage_methods, /* tp_methods */ IRAverage_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ IRAverage_new, /* tp_new */ }; /************/ /* IRPulse */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *bandwidth; Stream *bandwidth_stream; int modebuffer[4]; // need at least 2 slots for mul & add MYFLT *impulse; MYFLT *input_tmp; int count; int filtertype; int order; int size; int changed; MYFLT last_freq; MYFLT last_bandwidth; } IRPulse; static void IRPulse_alloc_memory(IRPulse *self) { int i; if ((self->order % 2) != 0) self->order += 1; self->size = self->order + 1; self->input_tmp = (MYFLT *)realloc(self->input_tmp, self->size * sizeof(MYFLT)); self->impulse = (MYFLT *)realloc(self->impulse, self->size * sizeof(MYFLT)); for (i=0; isize; i++) { self->input_tmp[i] = self->impulse[i] = 0.0; } } static void IRPulse_create_impulse(IRPulse *self, MYFLT freq, MYFLT bandwidth) { int i, n, w, bw, dir, gate; MYFLT val, sum; sum = 0.0; if (freq < 1) freq = 1.0; else if (freq > (self->sr*0.5)) freq = self->sr*0.5; if (bandwidth < 1) bandwidth = 1.0; else if (bandwidth > (self->sr*0.5)) bandwidth = self->sr*0.5; switch (self->filtertype) { case 0: /* PULSE */ w = (int)(self->sr / freq); bw = (int)(self->sr / bandwidth); for (i=0; isize; i++) { if ((i % w) <= bw) { val = 1.0; self->impulse[i] = val; sum += val; } else { self->impulse[i] = 0.0; } } for (i=0; isize; i++) { self->impulse[i] /= sum; } break; case 1: /* PULSELP */ w = (int)(self->sr / freq); bw = (int)(self->sr / bandwidth); for (i=0; isize; i++) { if ((i % w) <= bw) { n = i % w; val = 0.5 * (1.0 - MYCOS(TWOPI*n/(bw-1))); self->impulse[i] = val; sum += val; } else { self->impulse[i] = 0.0; } } for (i=0; isize; i++) { self->impulse[i] /= sum; } break; case 2: /* PULSEODD */ w = (int)(self->sr / (freq*2)); bw = (int)(self->sr / bandwidth); dir = 0; gate = 0; for (i=0; isize; i++) { if ((i % w) <= bw) { if (gate == 1) { dir++; gate = 0; } if ((dir % 2) == 0) val = 1.0; else val = -1.0; self->impulse[i] = val; sum += MYFABS(val); } else { gate = 1; self->impulse[i] = 0.0; } } for (i=0; isize; i++) { self->impulse[i] /= sum; } break; case 3: /* PULSEODDLP */ w = (int)(self->sr / (freq*2)); bw = (int)(self->sr / bandwidth); dir = 0; gate = 0; for (i=0; isize; i++) { if ((i % w) <= bw) { n = i % w; val = 0.5 * (1.0 - MYCOS(TWOPI*n/(bw-1))); if (gate == 1) { dir++; gate = 0; } if ((dir % 2) == 1) val = -val; self->impulse[i] = val; sum += MYFABS(val); } else { gate = 1; self->impulse[i] = 0.0; } } for (i=0; isize; i++) { self->impulse[i] /= sum; } break; } } static void IRPulse_filters(IRPulse *self) { int i,j,tmp_count; MYFLT freq, bw; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->modebuffer[2] == 0) freq = PyFloat_AS_DOUBLE(self->freq); else { MYFLT *fr = Stream_getData((Stream *)self->freq_stream); freq = fr[0]; } if (self->modebuffer[3] == 0) bw = PyFloat_AS_DOUBLE(self->bandwidth); else { MYFLT *band = Stream_getData((Stream *)self->bandwidth_stream); bw = band[0]; } if (freq != self->last_freq || bw != self->last_bandwidth || self->changed == 1) { IRPulse_create_impulse(self, freq, bw); self->last_freq = freq; self->last_bandwidth = bw; self->changed = 0; } for (i=0; ibufsize; i++) { self->data[i] = 0.0; tmp_count = self->count; for(j=0; jsize; j++) { if (tmp_count < 0) tmp_count += self->size; self->data[i] += self->input_tmp[tmp_count--] * self->impulse[j]; } self->count++; if (self->count == self->size) self->count = 0; self->input_tmp[self->count] = in[i]; } } static void IRPulse_postprocessing_ii(IRPulse *self) { POST_PROCESSING_II }; static void IRPulse_postprocessing_ai(IRPulse *self) { POST_PROCESSING_AI }; static void IRPulse_postprocessing_ia(IRPulse *self) { POST_PROCESSING_IA }; static void IRPulse_postprocessing_aa(IRPulse *self) { POST_PROCESSING_AA }; static void IRPulse_postprocessing_ireva(IRPulse *self) { POST_PROCESSING_IREVA }; static void IRPulse_postprocessing_areva(IRPulse *self) { POST_PROCESSING_AREVA }; static void IRPulse_postprocessing_revai(IRPulse *self) { POST_PROCESSING_REVAI }; static void IRPulse_postprocessing_revaa(IRPulse *self) { POST_PROCESSING_REVAA }; static void IRPulse_postprocessing_revareva(IRPulse *self) { POST_PROCESSING_REVAREVA }; static void IRPulse_setProcMode(IRPulse *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = IRPulse_filters; switch (muladdmode) { case 0: self->muladd_func_ptr = IRPulse_postprocessing_ii; break; case 1: self->muladd_func_ptr = IRPulse_postprocessing_ai; break; case 2: self->muladd_func_ptr = IRPulse_postprocessing_revai; break; case 10: self->muladd_func_ptr = IRPulse_postprocessing_ia; break; case 11: self->muladd_func_ptr = IRPulse_postprocessing_aa; break; case 12: self->muladd_func_ptr = IRPulse_postprocessing_revaa; break; case 20: self->muladd_func_ptr = IRPulse_postprocessing_ireva; break; case 21: self->muladd_func_ptr = IRPulse_postprocessing_areva; break; case 22: self->muladd_func_ptr = IRPulse_postprocessing_revareva; break; } } static void IRPulse_compute_next_data_frame(IRPulse *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int IRPulse_traverse(IRPulse *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->bandwidth); Py_VISIT(self->bandwidth_stream); return 0; } static int IRPulse_clear(IRPulse *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->bandwidth); Py_CLEAR(self->bandwidth_stream); return 0; } static void IRPulse_dealloc(IRPulse* self) { pyo_DEALLOC free(self->input_tmp); free(self->impulse); IRPulse_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * IRPulse_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *bandwidthtmp=NULL, *multmp=NULL, *addtmp=NULL; IRPulse *self; self = (IRPulse *)type->tp_alloc(type, 0); self->last_freq = -1.0; self->last_bandwidth = -1.0; self->freq = PyFloat_FromDouble(500.0); self->bandwidth = PyFloat_FromDouble(2500.0); self->filtertype = 0; self->order = 256; self->count = 0; self->changed = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, IRPulse_compute_next_data_frame); self->mode_func_ptr = IRPulse_setProcMode; static char *kwlist[] = {"input", "freq", "bw", "type", "order", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOiiOO", kwlist, &inputtmp, &freqtmp, &bandwidthtmp, &self->filtertype, &self->order, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (bandwidthtmp) { PyObject_CallMethod((PyObject *)self, "setBandwidth", "O", bandwidthtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); IRPulse_alloc_memory(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * IRPulse_getServer(IRPulse* self) { GET_SERVER }; static PyObject * IRPulse_getStream(IRPulse* self) { GET_STREAM }; static PyObject * IRPulse_setMul(IRPulse *self, PyObject *arg) { SET_MUL }; static PyObject * IRPulse_setAdd(IRPulse *self, PyObject *arg) { SET_ADD }; static PyObject * IRPulse_setSub(IRPulse *self, PyObject *arg) { SET_SUB }; static PyObject * IRPulse_setDiv(IRPulse *self, PyObject *arg) { SET_DIV }; static PyObject * IRPulse_play(IRPulse *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * IRPulse_out(IRPulse *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * IRPulse_stop(IRPulse *self) { STOP }; static PyObject * IRPulse_multiply(IRPulse *self, PyObject *arg) { MULTIPLY }; static PyObject * IRPulse_inplace_multiply(IRPulse *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * IRPulse_add(IRPulse *self, PyObject *arg) { ADD }; static PyObject * IRPulse_inplace_add(IRPulse *self, PyObject *arg) { INPLACE_ADD }; static PyObject * IRPulse_sub(IRPulse *self, PyObject *arg) { SUB }; static PyObject * IRPulse_inplace_sub(IRPulse *self, PyObject *arg) { INPLACE_SUB }; static PyObject * IRPulse_div(IRPulse *self, PyObject *arg) { DIV }; static PyObject * IRPulse_inplace_div(IRPulse *self, PyObject *arg) { INPLACE_DIV }; static PyObject * IRPulse_setFreq(IRPulse *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * IRPulse_setBandwidth(IRPulse *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->bandwidth); if (isNumber == 1) { self->bandwidth = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->bandwidth = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->bandwidth, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->bandwidth_stream); self->bandwidth_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * IRPulse_setType(IRPulse *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { self->filtertype = PyInt_AsLong(arg); self->changed = 1; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef IRPulse_members[] = { {"server", T_OBJECT_EX, offsetof(IRPulse, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(IRPulse, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(IRPulse, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(IRPulse, freq), 0, "Cutoff or center frequency."}, {"bandwidth", T_OBJECT_EX, offsetof(IRPulse, bandwidth), 0, "Bandwidth, in Hz, for bandreject and bandpass filters."}, {"mul", T_OBJECT_EX, offsetof(IRPulse, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(IRPulse, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef IRPulse_methods[] = { {"getServer", (PyCFunction)IRPulse_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)IRPulse_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)IRPulse_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)IRPulse_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)IRPulse_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)IRPulse_setFreq, METH_O, "Sets center/cutoff frequency."}, {"setBandwidth", (PyCFunction)IRPulse_setBandwidth, METH_O, "Sets bandwidth in Hz."}, {"setType", (PyCFunction)IRPulse_setType, METH_O, "Sets filter type factor."}, {"setMul", (PyCFunction)IRPulse_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)IRPulse_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)IRPulse_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)IRPulse_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods IRPulse_as_number = { (binaryfunc)IRPulse_add, /*nb_add*/ (binaryfunc)IRPulse_sub, /*nb_subtract*/ (binaryfunc)IRPulse_multiply, /*nb_multiply*/ (binaryfunc)IRPulse_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)IRPulse_inplace_add, /*inplace_add*/ (binaryfunc)IRPulse_inplace_sub, /*inplace_subtract*/ (binaryfunc)IRPulse_inplace_multiply, /*inplace_multiply*/ (binaryfunc)IRPulse_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject IRPulseType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.IRPulse_base", /*tp_name*/ sizeof(IRPulse), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)IRPulse_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &IRPulse_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "IRPulse objects. Windowed-sinc filter.", /* tp_doc */ (traverseproc)IRPulse_traverse, /* tp_traverse */ (inquiry)IRPulse_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ IRPulse_methods, /* tp_methods */ IRPulse_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ IRPulse_new, /* tp_new */ }; /************/ /* IRFM */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *carrier; Stream *carrier_stream; PyObject *ratio; Stream *ratio_stream; PyObject *index; Stream *index_stream; int modebuffer[5]; // need at least 2 slots for mul & add MYFLT *impulse; MYFLT *input_tmp; int count; int order; int size; MYFLT last_carrier; MYFLT last_ratio; MYFLT last_index; } IRFM; static void IRFM_alloc_memory(IRFM *self) { int i; if ((self->order % 2) != 0) self->order += 1; self->size = self->order + 1; self->input_tmp = (MYFLT *)realloc(self->input_tmp, self->size * sizeof(MYFLT)); self->impulse = (MYFLT *)realloc(self->impulse, self->size * sizeof(MYFLT)); for (i=0; isize; i++) { self->input_tmp[i] = self->impulse[i] = 0.0; } } static void IRFM_create_impulse(IRFM *self, MYFLT carrier, MYFLT ratio, MYFLT index) { int i; MYFLT val, sum, invSum, env, mod, fc, bw, modamp; if (carrier < 1) carrier = 1.0; else if (carrier > (self->sr*0.5)) carrier = self->sr*0.5; if (ratio < 0.0001) ratio = 0.0001; else if (ratio > (self->sr*0.5)) ratio = self->sr*0.5; if (index < 0) index = 0.0; fc = carrier / self->sr * self->order; bw = carrier * ratio / self->sr * self->order; modamp = index*TWOPI*bw/self->order; sum = 0.0; for (i=0; isize; i++) { env = 0.5 * (1.0 - MYCOS(TWOPI*i/self->order)); mod = modamp * MYSIN(TWOPI*bw*i/self->order); val = MYSIN(TWOPI*(fc+mod)*i/self->order) * env; sum += MYFABS(val); self->impulse[i] = val; } invSum = 1.0 / sum; for (i=0; isize; i++) { self->impulse[i] *= invSum; } } static void IRFM_filters(IRFM *self) { int i,j,tmp_count; MYFLT carrier, ratio, index; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->modebuffer[2] == 0) carrier = PyFloat_AS_DOUBLE(self->carrier); else { MYFLT *car = Stream_getData((Stream *)self->carrier_stream); carrier = car[0]; } if (self->modebuffer[3] == 0) ratio = PyFloat_AS_DOUBLE(self->ratio); else { MYFLT *rat = Stream_getData((Stream *)self->ratio_stream); ratio = rat[0]; } if (self->modebuffer[4] == 0) index = PyFloat_AS_DOUBLE(self->index); else { MYFLT *ind = Stream_getData((Stream *)self->index_stream); index = ind[0]; } if (carrier != self->last_carrier || ratio != self->last_ratio || index != self->last_index) { IRFM_create_impulse(self, carrier, ratio, index); self->last_carrier = carrier; self->last_ratio = ratio; self->last_index = index; } for (i=0; ibufsize; i++) { self->data[i] = 0.0; tmp_count = self->count; for(j=0; jsize; j++) { if (tmp_count < 0) tmp_count += self->size; self->data[i] += self->input_tmp[tmp_count--] * self->impulse[j]; } self->count++; if (self->count == self->size) self->count = 0; self->input_tmp[self->count] = in[i]; } } static void IRFM_postprocessing_ii(IRFM *self) { POST_PROCESSING_II }; static void IRFM_postprocessing_ai(IRFM *self) { POST_PROCESSING_AI }; static void IRFM_postprocessing_ia(IRFM *self) { POST_PROCESSING_IA }; static void IRFM_postprocessing_aa(IRFM *self) { POST_PROCESSING_AA }; static void IRFM_postprocessing_ireva(IRFM *self) { POST_PROCESSING_IREVA }; static void IRFM_postprocessing_areva(IRFM *self) { POST_PROCESSING_AREVA }; static void IRFM_postprocessing_revai(IRFM *self) { POST_PROCESSING_REVAI }; static void IRFM_postprocessing_revaa(IRFM *self) { POST_PROCESSING_REVAA }; static void IRFM_postprocessing_revareva(IRFM *self) { POST_PROCESSING_REVAREVA }; static void IRFM_setProcMode(IRFM *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = IRFM_filters; switch (muladdmode) { case 0: self->muladd_func_ptr = IRFM_postprocessing_ii; break; case 1: self->muladd_func_ptr = IRFM_postprocessing_ai; break; case 2: self->muladd_func_ptr = IRFM_postprocessing_revai; break; case 10: self->muladd_func_ptr = IRFM_postprocessing_ia; break; case 11: self->muladd_func_ptr = IRFM_postprocessing_aa; break; case 12: self->muladd_func_ptr = IRFM_postprocessing_revaa; break; case 20: self->muladd_func_ptr = IRFM_postprocessing_ireva; break; case 21: self->muladd_func_ptr = IRFM_postprocessing_areva; break; case 22: self->muladd_func_ptr = IRFM_postprocessing_revareva; break; } } static void IRFM_compute_next_data_frame(IRFM *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int IRFM_traverse(IRFM *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->carrier); Py_VISIT(self->carrier_stream); Py_VISIT(self->ratio); Py_VISIT(self->ratio_stream); Py_VISIT(self->index); Py_VISIT(self->index_stream); return 0; } static int IRFM_clear(IRFM *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->carrier); Py_CLEAR(self->carrier_stream); Py_CLEAR(self->ratio); Py_CLEAR(self->ratio_stream); Py_CLEAR(self->index); Py_CLEAR(self->index_stream); return 0; } static void IRFM_dealloc(IRFM* self) { pyo_DEALLOC free(self->input_tmp); free(self->impulse); IRFM_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * IRFM_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *carriertmp=NULL, *ratiotmp=NULL, *indextmp=NULL, *multmp=NULL, *addtmp=NULL; IRFM *self; self = (IRFM *)type->tp_alloc(type, 0); self->last_carrier = -1.0; self->last_ratio = -1.0; self->last_index = -1.0; self->carrier = PyFloat_FromDouble(1000.0); self->ratio = PyFloat_FromDouble(0.5); self->index = PyFloat_FromDouble(3.0); self->order = 256; self->count = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, IRFM_compute_next_data_frame); self->mode_func_ptr = IRFM_setProcMode; static char *kwlist[] = {"input", "carrier", "ratio", "index", "order", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOiOO", kwlist, &inputtmp, &carriertmp, &ratiotmp, &indextmp, &self->order, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (carriertmp) { PyObject_CallMethod((PyObject *)self, "setCarrier", "O", carriertmp); } if (ratiotmp) { PyObject_CallMethod((PyObject *)self, "setRatio", "O", ratiotmp); } if (indextmp) { PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); IRFM_alloc_memory(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * IRFM_getServer(IRFM* self) { GET_SERVER }; static PyObject * IRFM_getStream(IRFM* self) { GET_STREAM }; static PyObject * IRFM_setMul(IRFM *self, PyObject *arg) { SET_MUL }; static PyObject * IRFM_setAdd(IRFM *self, PyObject *arg) { SET_ADD }; static PyObject * IRFM_setSub(IRFM *self, PyObject *arg) { SET_SUB }; static PyObject * IRFM_setDiv(IRFM *self, PyObject *arg) { SET_DIV }; static PyObject * IRFM_play(IRFM *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * IRFM_out(IRFM *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * IRFM_stop(IRFM *self) { STOP }; static PyObject * IRFM_multiply(IRFM *self, PyObject *arg) { MULTIPLY }; static PyObject * IRFM_inplace_multiply(IRFM *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * IRFM_add(IRFM *self, PyObject *arg) { ADD }; static PyObject * IRFM_inplace_add(IRFM *self, PyObject *arg) { INPLACE_ADD }; static PyObject * IRFM_sub(IRFM *self, PyObject *arg) { SUB }; static PyObject * IRFM_inplace_sub(IRFM *self, PyObject *arg) { INPLACE_SUB }; static PyObject * IRFM_div(IRFM *self, PyObject *arg) { DIV }; static PyObject * IRFM_inplace_div(IRFM *self, PyObject *arg) { INPLACE_DIV }; static PyObject * IRFM_setCarrier(IRFM *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->carrier); if (isNumber == 1) { self->carrier = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->carrier = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->carrier, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->carrier_stream); self->carrier_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * IRFM_setRatio(IRFM *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->ratio); if (isNumber == 1) { self->ratio = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->ratio = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->ratio, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->ratio_stream); self->ratio_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * IRFM_setIndex(IRFM *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->index); if (isNumber == 1) { self->index = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->index = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->index_stream); self->index_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef IRFM_members[] = { {"server", T_OBJECT_EX, offsetof(IRFM, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(IRFM, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(IRFM, input), 0, "Input sound object."}, {"carrier", T_OBJECT_EX, offsetof(IRFM, carrier), 0, "Carrier frequency."}, {"ratio", T_OBJECT_EX, offsetof(IRFM, ratio), 0, "Modulator / carrier ratio."}, {"index", T_OBJECT_EX, offsetof(IRFM, index), 0, "Modulation index."}, {"mul", T_OBJECT_EX, offsetof(IRFM, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(IRFM, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef IRFM_methods[] = { {"getServer", (PyCFunction)IRFM_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)IRFM_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)IRFM_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)IRFM_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)IRFM_stop, METH_NOARGS, "Stops computing."}, {"setCarrier", (PyCFunction)IRFM_setCarrier, METH_O, "Sets carrier frequency."}, {"setRatio", (PyCFunction)IRFM_setRatio, METH_O, "Sets ratio."}, {"setIndex", (PyCFunction)IRFM_setIndex, METH_O, "Sets the modulation index."}, {"setMul", (PyCFunction)IRFM_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)IRFM_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)IRFM_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)IRFM_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods IRFM_as_number = { (binaryfunc)IRFM_add, /*nb_add*/ (binaryfunc)IRFM_sub, /*nb_subtract*/ (binaryfunc)IRFM_multiply, /*nb_multiply*/ (binaryfunc)IRFM_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)IRFM_inplace_add, /*inplace_add*/ (binaryfunc)IRFM_inplace_sub, /*inplace_subtract*/ (binaryfunc)IRFM_inplace_multiply, /*inplace_multiply*/ (binaryfunc)IRFM_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject IRFMType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.IRFM_base", /*tp_name*/ sizeof(IRFM), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)IRFM_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &IRFM_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "IRFM objects. Convolve an input signal with a frequency modulation spectrum.", /* tp_doc */ (traverseproc)IRFM_traverse, /* tp_traverse */ (inquiry)IRFM_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ IRFM_methods, /* tp_methods */ IRFM_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ IRFM_new, /* tp_new */ };pyo/src/objects/phasevocmodule.c0000644000175000017500000105017612652732202016272 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "pvstreammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "tablemodule.h" #include "fft.h" #include "wind.h" static int isPowerOfTwo(int x) { return (x != 0) && ((x & (x - 1)) == 0); } typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PVStream *pv_stream; int size; int olaps; int hsize; int hopsize; int wintype; int incount; int inputLatency; int overcount; MYFLT factor; MYFLT scale; MYFLT *input_buffer; MYFLT *inframe; MYFLT *outframe; MYFLT *real; MYFLT *imag; MYFLT *lastPhase; MYFLT **twiddle; MYFLT *window; MYFLT **magn; MYFLT **freq; int *count; } PVAnal; static void PVAnal_realloc_memories(PVAnal *self) { int i, j, n8; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; self->factor = self->sr / (self->hopsize * TWOPI); self->scale = TWOPI * self->hopsize / self->size; self->inputLatency = self->size - self->hopsize; self->incount = self->inputLatency; self->overcount = 0; n8 = self->size >> 3; self->input_buffer = (MYFLT *)realloc(self->input_buffer, self->size * sizeof(MYFLT)); self->inframe = (MYFLT *)realloc(self->inframe, self->size * sizeof(MYFLT)); self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT)); for (i=0; isize; i++) self->input_buffer[i] = self->inframe[i] = self->outframe[i] = 0.0; self->lastPhase = (MYFLT *)realloc(self->lastPhase, self->hsize * sizeof(MYFLT)); self->real = (MYFLT *)realloc(self->real, self->hsize * sizeof(MYFLT)); self->imag = (MYFLT *)realloc(self->imag, self->hsize * sizeof(MYFLT)); self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } for (i=0; ihsize; i++) self->lastPhase[i] = self->real[i] = self->imag[i] = 0.0; self->twiddle = (MYFLT **)realloc(self->twiddle, 4 * sizeof(MYFLT *)); for(i=0; i<4; i++) self->twiddle[i] = (MYFLT *)malloc(n8 * sizeof(MYFLT)); fft_compute_split_twiddle(self->twiddle, self->size); self->window = (MYFLT *)realloc(self->window, self->size * sizeof(MYFLT)); gen_window(self->window, self->size, self->wintype); for (i=0; ibufsize; i++) self->count[i] = self->incount; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVAnal_process(PVAnal *self) { int i, k, mod; MYFLT real, imag, mag, phase, tmp; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->input_buffer[self->incount] = in[i]; self->count[i] = self->incount; self->incount++; if (self->incount >= self->size) { self->incount = self->inputLatency; mod = self->hopsize * self->overcount; for (k=0; ksize; k++) { self->inframe[(k+mod)%self->size] = self->input_buffer[k] * self->window[k]; } realfft_split(self->inframe, self->outframe, self->size, self->twiddle); self->real[0] = self->outframe[0]; self->imag[0] = 0.0; for (k=1; khsize; k++) { self->real[k] = self->outframe[k]; self->imag[k] = self->outframe[self->size - k]; } for (k=0; khsize; k++) { real = self->real[k]; imag = self->imag[k]; mag = MYSQRT(real*real + imag*imag); phase = MYATAN2(imag, real); tmp = phase - self->lastPhase[k]; self->lastPhase[k] = phase; while (tmp > PI) tmp -= TWOPI; while (tmp < -PI) tmp += TWOPI; self->magn[self->overcount][k] = mag; self->freq[self->overcount][k] = (tmp + k * self->scale) * self->factor; } for (k=0; kinputLatency; k++) { self->input_buffer[k] = self->input_buffer[k + self->hopsize]; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVAnal_setProcMode(PVAnal *self) { self->proc_func_ptr = PVAnal_process; } static void PVAnal_compute_next_data_frame(PVAnal *self) { (*self->proc_func_ptr)(self); } static int PVAnal_traverse(PVAnal *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pv_stream); return 0; } static int PVAnal_clear(PVAnal *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pv_stream); return 0; } static void PVAnal_dealloc(PVAnal* self) { int i; pyo_DEALLOC free(self->input_buffer); free(self->inframe); free(self->outframe); free(self->real); free(self->imag); free(self->lastPhase); for(i=0; i<4; i++) { free(self->twiddle[i]); } free(self->twiddle); free(self->window); for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); free(self->count); PVAnal_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVAnal_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, k; PyObject *inputtmp, *input_streamtmp; PVAnal *self; self = (PVAnal *)type->tp_alloc(type, 0); self->size = 1024; self->olaps = 4; self->wintype = 2; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVAnal_compute_next_data_frame); self->mode_func_ptr = PVAnal_setProcMode; static char *kwlist[] = {"input", "size", "olaps", "wintype", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iii", kwlist, &inputtmp, &self->size, &self->olaps, &self->wintype)) Py_RETURN_NONE; INIT_INPUT_STREAM PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); if (!isPowerOfTwo(self->size)) { k = 1; while (k < self->size) k *= 2; self->size = k; printf("FFT size must be a power-of-2, using the next power-of-2 greater than size : %d\n", self->size); } self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVAnal_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVAnal_getServer(PVAnal* self) { GET_SERVER }; static PyObject * PVAnal_getStream(PVAnal* self) { GET_STREAM }; static PyObject * PVAnal_getPVStream(PVAnal* self) { GET_PV_STREAM }; static PyObject * PVAnal_play(PVAnal *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVAnal_stop(PVAnal *self) { STOP }; static PyObject * PVAnal_setSize(PVAnal *self, PyObject *arg) { int k; if (PyLong_Check(arg) || PyInt_Check(arg)) { self->size = PyInt_AsLong(arg); if (!isPowerOfTwo(self->size)) { k = 1; while (k < self->size) k *= 2; self->size = k; printf("FFT size must be a power-of-2, using the next power-of-2 greater than size : %d\n", self->size); } PVAnal_realloc_memories(self); } Py_INCREF(Py_None); return Py_None; } static PyObject * PVAnal_setOverlaps(PVAnal *self, PyObject *arg) { int k; if (PyLong_Check(arg) || PyInt_Check(arg)) { self->olaps = PyInt_AsLong(arg); if (!isPowerOfTwo(self->olaps)) { k = 1; while (k < self->olaps) k *= 2; self->olaps = k; printf("FFT overlaps must be a power-of-2, using the next power-of-2 greater than olaps : %d\n", self->olaps); } PVAnal_realloc_memories(self); } Py_INCREF(Py_None); return Py_None; } static PyObject * PVAnal_setWinType(PVAnal *self, PyObject *arg) { if (PyLong_Check(arg) || PyInt_Check(arg)) { self->wintype = PyInt_AsLong(arg); gen_window(self->window, self->size, self->wintype); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVAnal_members[] = { {"server", T_OBJECT_EX, offsetof(PVAnal, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVAnal, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVAnal, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVAnal, input), 0, "FFT sound object."}, {NULL} /* Sentinel */ }; static PyMethodDef PVAnal_methods[] = { {"getServer", (PyCFunction)PVAnal_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVAnal_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVAnal_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"play", (PyCFunction)PVAnal_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVAnal_stop, METH_NOARGS, "Stops computing."}, {"setSize", (PyCFunction)PVAnal_setSize, METH_O, "Sets a new FFT size."}, {"setOverlaps", (PyCFunction)PVAnal_setOverlaps, METH_O, "Sets a new number of overlaps."}, {"setWinType", (PyCFunction)PVAnal_setWinType, METH_O, "Sets a new window type."}, {NULL} /* Sentinel */ }; PyTypeObject PVAnalType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVAnal_base", /*tp_name*/ sizeof(PVAnal), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVAnal_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVAnal objects. Phase Vocoder analysis object.", /* tp_doc */ (traverseproc)PVAnal_traverse, /* tp_traverse */ (inquiry)PVAnal_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVAnal_methods, /* tp_methods */ PVAnal_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVAnal_new, /* tp_new */ }; /*****************/ /**** PVSynth ****/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; //PVStream *pv_stream; int size; int hsize; int olaps; int hopsize; int wintype; int inputLatency; int overcount; MYFLT ampscl; MYFLT factor; MYFLT scale; MYFLT *output_buffer; MYFLT *outputAccum; MYFLT *inframe; MYFLT *outframe; MYFLT *real; MYFLT *imag; MYFLT *sumPhase; MYFLT **twiddle; MYFLT *window; int modebuffer[2]; // need at least 2 slots for mul & add } PVSynth; static void PVSynth_realloc_memories(PVSynth *self) { int i, n8; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; self->factor = self->hopsize * TWOPI / self->sr; self->scale = self->sr / self->size; self->inputLatency = self->size - self->hopsize; self->overcount = 0; self->ampscl = 1.0 / MYSQRT(self->olaps); n8 = self->size >> 3; self->output_buffer = (MYFLT *)realloc(self->output_buffer, self->size * sizeof(MYFLT)); self->inframe = (MYFLT *)realloc(self->inframe, self->size * sizeof(MYFLT)); self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT)); for (i=0; isize; i++) self->output_buffer[i] = self->inframe[i] = self->outframe[i] = 0.0; self->sumPhase = (MYFLT *)realloc(self->sumPhase, self->hsize * sizeof(MYFLT)); self->real = (MYFLT *)realloc(self->real, self->hsize * sizeof(MYFLT)); self->imag = (MYFLT *)realloc(self->imag, self->hsize * sizeof(MYFLT)); for (i=0; ihsize; i++) self->sumPhase[i] = self->real[i] = self->imag[i] = 0.0; self->outputAccum = (MYFLT *)realloc(self->outputAccum, (self->size+self->hopsize) * sizeof(MYFLT)); for (i=0; i<(self->size+self->hopsize); i++) self->outputAccum[i] = 0.0; self->twiddle = (MYFLT **)realloc(self->twiddle, 4 * sizeof(MYFLT *)); for(i=0; i<4; i++) self->twiddle[i] = (MYFLT *)malloc(n8 * sizeof(MYFLT)); fft_compute_split_twiddle(self->twiddle, self->size); self->window = (MYFLT *)realloc(self->window, self->size * sizeof(MYFLT)); gen_window(self->window, self->size, self->wintype); } static void PVSynth_process(PVSynth *self) { int i, k, mod; MYFLT mag, phase, tmp; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVSynth_realloc_memories(self); } for (i=0; ibufsize; i++) { self->data[i] = self->output_buffer[count[i] - self->inputLatency]; if (count[i] >= (self->size-1)) { for (k=0; khsize; k++) { mag = magn[self->overcount][k]; tmp = freq[self->overcount][k]; tmp = (tmp - k * self->scale) * self->factor; self->sumPhase[k] += tmp; phase = self->sumPhase[k]; self->real[k] = mag * MYCOS(phase); self->imag[k] = mag * MYSIN(phase); } self->inframe[0] = self->real[0]; self->inframe[self->hsize] = 0.0; for (k=1; khsize; k++) { self->inframe[k] = self->real[k]; self->inframe[self->size - k] = self->imag[k]; } irealfft_split(self->inframe, self->outframe, self->size, self->twiddle); mod = self->hopsize * self->overcount; for (k=0; ksize; k++) { self->outputAccum[k] += self->outframe[(k+mod)%self->size] * self->window[k] * self->ampscl; } for (k=0; khopsize; k++) { self->output_buffer[k] = self->outputAccum[k]; } for (k=0; ksize; k++) { self->outputAccum[k] = self->outputAccum[k + self->hopsize]; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVSynth_postprocessing_ii(PVSynth *self) { POST_PROCESSING_II }; static void PVSynth_postprocessing_ai(PVSynth *self) { POST_PROCESSING_AI }; static void PVSynth_postprocessing_ia(PVSynth *self) { POST_PROCESSING_IA }; static void PVSynth_postprocessing_aa(PVSynth *self) { POST_PROCESSING_AA }; static void PVSynth_postprocessing_ireva(PVSynth *self) { POST_PROCESSING_IREVA }; static void PVSynth_postprocessing_areva(PVSynth *self) { POST_PROCESSING_AREVA }; static void PVSynth_postprocessing_revai(PVSynth *self) { POST_PROCESSING_REVAI }; static void PVSynth_postprocessing_revaa(PVSynth *self) { POST_PROCESSING_REVAA }; static void PVSynth_postprocessing_revareva(PVSynth *self) { POST_PROCESSING_REVAREVA }; static void PVSynth_setProcMode(PVSynth *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = PVSynth_process; switch (muladdmode) { case 0: self->muladd_func_ptr = PVSynth_postprocessing_ii; break; case 1: self->muladd_func_ptr = PVSynth_postprocessing_ai; break; case 2: self->muladd_func_ptr = PVSynth_postprocessing_revai; break; case 10: self->muladd_func_ptr = PVSynth_postprocessing_ia; break; case 11: self->muladd_func_ptr = PVSynth_postprocessing_aa; break; case 12: self->muladd_func_ptr = PVSynth_postprocessing_revaa; break; case 20: self->muladd_func_ptr = PVSynth_postprocessing_ireva; break; case 21: self->muladd_func_ptr = PVSynth_postprocessing_areva; break; case 22: self->muladd_func_ptr = PVSynth_postprocessing_revareva; break; } } static void PVSynth_compute_next_data_frame(PVSynth *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int PVSynth_traverse(PVSynth *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); //Py_VISIT(self->pv_stream); return 0; } static int PVSynth_clear(PVSynth *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); //Py_CLEAR(self->pv_stream); return 0; } static void PVSynth_dealloc(PVSynth* self) { int i; pyo_DEALLOC free(self->output_buffer); free(self->outputAccum); free(self->inframe); free(self->outframe); free(self->real); free(self->imag); free(self->sumPhase); for(i=0; i<4; i++) { free(self->twiddle[i]); } free(self->twiddle); free(self->window); PVSynth_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVSynth_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; PVSynth *self; self = (PVSynth *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->wintype = 2; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVSynth_compute_next_data_frame); self->mode_func_ptr = PVSynth_setProcMode; static char *kwlist[] = {"input", "wintype", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &inputtmp, &self->wintype, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVSynth must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); PVSynth_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVSynth_setInput(PVSynth *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVSynth must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVSynth_setWinType(PVSynth *self, PyObject *arg) { if (PyLong_Check(arg) || PyInt_Check(arg)) { self->wintype = PyInt_AsLong(arg); gen_window(self->window, self->size, self->wintype); } Py_INCREF(Py_None); return Py_None; } static PyObject * PVSynth_getServer(PVSynth* self) { GET_SERVER }; static PyObject * PVSynth_getStream(PVSynth* self) { GET_STREAM }; //static PyObject * PVSynth_getPVStream(PVSynth* self) { GET_PV_STREAM }; static PyObject * PVSynth_setMul(PVSynth *self, PyObject *arg) { SET_MUL }; static PyObject * PVSynth_setAdd(PVSynth *self, PyObject *arg) { SET_ADD }; static PyObject * PVSynth_setSub(PVSynth *self, PyObject *arg) { SET_SUB }; static PyObject * PVSynth_setDiv(PVSynth *self, PyObject *arg) { SET_DIV }; static PyObject * PVSynth_play(PVSynth *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVSynth_out(PVSynth *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * PVSynth_stop(PVSynth *self) { STOP }; static PyObject * PVSynth_multiply(PVSynth *self, PyObject *arg) { MULTIPLY }; static PyObject * PVSynth_inplace_multiply(PVSynth *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * PVSynth_add(PVSynth *self, PyObject *arg) { ADD }; static PyObject * PVSynth_inplace_add(PVSynth *self, PyObject *arg) { INPLACE_ADD }; static PyObject * PVSynth_sub(PVSynth *self, PyObject *arg) { SUB }; static PyObject * PVSynth_inplace_sub(PVSynth *self, PyObject *arg) { INPLACE_SUB }; static PyObject * PVSynth_div(PVSynth *self, PyObject *arg) { DIV }; static PyObject * PVSynth_inplace_div(PVSynth *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef PVSynth_members[] = { {"server", T_OBJECT_EX, offsetof(PVSynth, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVSynth, stream), 0, "Stream object."}, //{"pv_stream", T_OBJECT_EX, offsetof(PVSynth, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVSynth, input), 0, "FFT sound object."}, {"mul", T_OBJECT_EX, offsetof(PVSynth, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(PVSynth, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef PVSynth_methods[] = { {"getServer", (PyCFunction)PVSynth_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVSynth_getStream, METH_NOARGS, "Returns stream object."}, //{"_getPVStream", (PyCFunction)PVSynth_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"play", (PyCFunction)PVSynth_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)PVSynth_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)PVSynth_stop, METH_NOARGS, "Stops computing."}, {"setInput", (PyCFunction)PVSynth_setInput, METH_O, "Sets a new input object."}, {"setWinType", (PyCFunction)PVSynth_setWinType, METH_O, "Sets a new window type."}, {"setMul", (PyCFunction)PVSynth_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)PVSynth_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)PVSynth_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)PVSynth_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods PVSynth_as_number = { (binaryfunc)PVSynth_add, /*nb_add*/ (binaryfunc)PVSynth_sub, /*nb_subtract*/ (binaryfunc)PVSynth_multiply, /*nb_multiply*/ (binaryfunc)PVSynth_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)PVSynth_inplace_add, /*inplace_add*/ (binaryfunc)PVSynth_inplace_sub, /*inplace_subtract*/ (binaryfunc)PVSynth_inplace_multiply, /*inplace_multiply*/ (binaryfunc)PVSynth_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject PVSynthType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVSynth_base", /*tp_name*/ sizeof(PVSynth), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVSynth_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &PVSynth_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVSynth objects. Phase Vocoder synthesis object.", /* tp_doc */ (traverseproc)PVSynth_traverse, /* tp_traverse */ (inquiry)PVSynth_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVSynth_methods, /* tp_methods */ PVSynth_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVSynth_new, /* tp_new */ }; /*****************/ /**** PVAddSynth ****/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PyObject *pitch; Stream *pitch_stream; int size; int hsize; int olaps; int hopsize; int inputLatency; int overcount; int num; int first; int inc; int update; MYFLT *ppos; MYFLT *amp; MYFLT *freq; MYFLT *outbuf; MYFLT *table; int modebuffer[3]; // need at least 2 slots for mul & add } PVAddSynth; static void PVAddSynth_realloc_memories(PVAddSynth *self) { int i; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; self->inputLatency = self->size - self->hopsize; self->overcount = 0; self->ppos = (MYFLT *)realloc(self->ppos, self->num * sizeof(MYFLT)); self->amp = (MYFLT *)realloc(self->amp, self->num * sizeof(MYFLT)); self->freq = (MYFLT *)realloc(self->freq, self->num * sizeof(MYFLT)); for (i=0; inum; i++) { self->ppos[i] = self->amp[i] = 0.0; self->freq[i] = (i * self->inc + self->first) * self->size / self->sr; } self->outbuf = (MYFLT *)realloc(self->outbuf, self->hopsize * sizeof(MYFLT)); for (i=0; ihopsize; i++) self->outbuf[i] = 0.0; } static void PVAddSynth_process_i(PVAddSynth *self) { int i, k, n, bin, ipart; MYFLT pitch, tamp, tfreq, inca, incf, ratio, fpart; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); pitch = PyFloat_AS_DOUBLE(self->pitch); if (self->size != size || self->olaps != olaps || self->update == 1) { self->size = size; self->olaps = olaps; self->update = 0; PVAddSynth_realloc_memories(self); } ratio = 8192.0 / self->sr; for (i=0; ibufsize; i++) { self->data[i] = self->outbuf[count[i] - self->inputLatency]; if (count[i] >= (self->size-1)) { for (n=0; nhopsize; n++) { self->outbuf[n] = 0.0; } for (k=0; knum; k++) { bin = k * self->inc + self->first; if (bin < self->hsize) { tamp = magn[self->overcount][bin]; tfreq = freq[self->overcount][bin] * pitch; inca = (tamp - self->amp[k]) / self->hopsize; incf = (tfreq - self->freq[k]) / self->hopsize; for (n=0; nhopsize; n++) { self->ppos[k] += self->freq[k] * ratio; while (self->ppos[k] < 0.0) self->ppos[k] += 8192.0; while (self->ppos[k] >= 8192.0) self->ppos[k] -= 8192.0; ipart = (int)self->ppos[k]; fpart = self->ppos[k] - ipart; self->outbuf[n] += self->amp[k] * (self->table[ipart] + (self->table[ipart+1] - self->table[ipart]) * fpart); self->amp[k] += inca; self->freq[k] += incf; } } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVAddSynth_process_a(PVAddSynth *self) { int i, k, n, bin, ipart; MYFLT pitch, tamp, tfreq, inca, incf, ratio, fpart; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *pit = Stream_getData((Stream *)self->pitch_stream); if (self->size != size || self->olaps != olaps || self->update == 1) { self->size = size; self->olaps = olaps; self->update = 0; PVAddSynth_realloc_memories(self); } ratio = 8192.0 / self->sr; for (i=0; ibufsize; i++) { self->data[i] = self->outbuf[count[i] - self->inputLatency]; if (count[i] >= (self->size-1)) { pitch = pit[i]; for (n=0; nhopsize; n++) { self->outbuf[n] = 0.0; } for (k=0; knum; k++) { bin = k * self->inc + self->first; if (bin < self->hsize) { tamp = magn[self->overcount][bin]; tfreq = freq[self->overcount][bin] * pitch; inca = (tamp - self->amp[k]) / self->hopsize; incf = (tfreq - self->freq[k]) / self->hopsize; for (n=0; nhopsize; n++) { self->ppos[k] += self->freq[k] * ratio; while (self->ppos[k] < 0.0) self->ppos[k] += 8192.0; while (self->ppos[k] >= 8192.0) self->ppos[k] -= 8192.0; ipart = (int)self->ppos[k]; fpart = self->ppos[k] - ipart; self->outbuf[n] += self->amp[k] * (self->table[ipart] + (self->table[ipart+1] - self->table[ipart]) * fpart); self->amp[k] += inca; self->freq[k] += incf; } } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVAddSynth_postprocessing_ii(PVAddSynth *self) { POST_PROCESSING_II }; static void PVAddSynth_postprocessing_ai(PVAddSynth *self) { POST_PROCESSING_AI }; static void PVAddSynth_postprocessing_ia(PVAddSynth *self) { POST_PROCESSING_IA }; static void PVAddSynth_postprocessing_aa(PVAddSynth *self) { POST_PROCESSING_AA }; static void PVAddSynth_postprocessing_ireva(PVAddSynth *self) { POST_PROCESSING_IREVA }; static void PVAddSynth_postprocessing_areva(PVAddSynth *self) { POST_PROCESSING_AREVA }; static void PVAddSynth_postprocessing_revai(PVAddSynth *self) { POST_PROCESSING_REVAI }; static void PVAddSynth_postprocessing_revaa(PVAddSynth *self) { POST_PROCESSING_REVAA }; static void PVAddSynth_postprocessing_revareva(PVAddSynth *self) { POST_PROCESSING_REVAREVA }; static void PVAddSynth_setProcMode(PVAddSynth *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = PVAddSynth_process_i; break; case 1: self->proc_func_ptr = PVAddSynth_process_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = PVAddSynth_postprocessing_ii; break; case 1: self->muladd_func_ptr = PVAddSynth_postprocessing_ai; break; case 2: self->muladd_func_ptr = PVAddSynth_postprocessing_revai; break; case 10: self->muladd_func_ptr = PVAddSynth_postprocessing_ia; break; case 11: self->muladd_func_ptr = PVAddSynth_postprocessing_aa; break; case 12: self->muladd_func_ptr = PVAddSynth_postprocessing_revaa; break; case 20: self->muladd_func_ptr = PVAddSynth_postprocessing_ireva; break; case 21: self->muladd_func_ptr = PVAddSynth_postprocessing_areva; break; case 22: self->muladd_func_ptr = PVAddSynth_postprocessing_revareva; break; } } static void PVAddSynth_compute_next_data_frame(PVAddSynth *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int PVAddSynth_traverse(PVAddSynth *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pitch); Py_VISIT(self->pitch_stream); return 0; } static int PVAddSynth_clear(PVAddSynth *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pitch); Py_CLEAR(self->pitch_stream); return 0; } static void PVAddSynth_dealloc(PVAddSynth* self) { pyo_DEALLOC free(self->ppos); free(self->outbuf); free(self->table); free(self->amp); free(self->freq); PVAddSynth_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVAddSynth_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *pitchtmp=NULL, *multmp=NULL, *addtmp=NULL; PVAddSynth *self; self = (PVAddSynth *)type->tp_alloc(type, 0); self->pitch = PyFloat_FromDouble(1); self->num = 100; self->first = 0; self->inc = 1; self->update = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVAddSynth_compute_next_data_frame); self->mode_func_ptr = PVAddSynth_setProcMode; static char *kwlist[] = {"input", "pitch", "num", "first", "inc", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OiiiOO", kwlist, &inputtmp, &pitchtmp, &self->num, &self->first, &self->inc, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVAddSynth must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); if (pitchtmp) { PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->table = (MYFLT *)realloc(self->table, 8193 * sizeof(MYFLT)); for (i=0; i<8192; i++) self->table[i] = (MYFLT)(MYSIN(TWOPI * i / 8192.0)); self->table[8192] = 0.0; PVAddSynth_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVAddSynth_setInput(PVAddSynth *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVAddSynth must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVAddSynth_setPitch(PVAddSynth *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pitch); if (isNumber == 1) { self->pitch = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->pitch = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pitch, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pitch_stream); self->pitch_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * PVAddSynth_setNum(PVAddSynth *self, PyObject *arg) { if (PyLong_Check(arg) || PyInt_Check(arg)) { self->num = PyInt_AsLong(arg); if (self->num < 1) self->num = 1; else if (self->num > self->hsize) self->num = self->hsize; self->update = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * PVAddSynth_setFirst(PVAddSynth *self, PyObject *arg) { if (PyLong_Check(arg) || PyInt_Check(arg)) { self->first = PyInt_AsLong(arg); if (self->first < 0) self->first = 0; else if (self->first > self->hsize) self->first = self->hsize; self->update = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * PVAddSynth_setInc(PVAddSynth *self, PyObject *arg) { if (PyLong_Check(arg) || PyInt_Check(arg)) { self->inc = PyInt_AsLong(arg); if (self->inc < 1) self->inc = 1; else if (self->inc > self->hsize) self->inc = self->hsize; self->update = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * PVAddSynth_getServer(PVAddSynth* self) { GET_SERVER }; static PyObject * PVAddSynth_getStream(PVAddSynth* self) { GET_STREAM }; static PyObject * PVAddSynth_setMul(PVAddSynth *self, PyObject *arg) { SET_MUL }; static PyObject * PVAddSynth_setAdd(PVAddSynth *self, PyObject *arg) { SET_ADD }; static PyObject * PVAddSynth_setSub(PVAddSynth *self, PyObject *arg) { SET_SUB }; static PyObject * PVAddSynth_setDiv(PVAddSynth *self, PyObject *arg) { SET_DIV }; static PyObject * PVAddSynth_play(PVAddSynth *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVAddSynth_out(PVAddSynth *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * PVAddSynth_stop(PVAddSynth *self) { STOP }; static PyObject * PVAddSynth_multiply(PVAddSynth *self, PyObject *arg) { MULTIPLY }; static PyObject * PVAddSynth_inplace_multiply(PVAddSynth *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * PVAddSynth_add(PVAddSynth *self, PyObject *arg) { ADD }; static PyObject * PVAddSynth_inplace_add(PVAddSynth *self, PyObject *arg) { INPLACE_ADD }; static PyObject * PVAddSynth_sub(PVAddSynth *self, PyObject *arg) { SUB }; static PyObject * PVAddSynth_inplace_sub(PVAddSynth *self, PyObject *arg) { INPLACE_SUB }; static PyObject * PVAddSynth_div(PVAddSynth *self, PyObject *arg) { DIV }; static PyObject * PVAddSynth_inplace_div(PVAddSynth *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef PVAddSynth_members[] = { {"server", T_OBJECT_EX, offsetof(PVAddSynth, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVAddSynth, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(PVAddSynth, input), 0, "FFT sound object."}, {"pitch", T_OBJECT_EX, offsetof(PVAddSynth, pitch), 0, "Transposition factor."}, {"mul", T_OBJECT_EX, offsetof(PVAddSynth, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(PVAddSynth, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef PVAddSynth_methods[] = { {"getServer", (PyCFunction)PVAddSynth_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVAddSynth_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)PVAddSynth_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)PVAddSynth_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)PVAddSynth_stop, METH_NOARGS, "Stops computing."}, {"setInput", (PyCFunction)PVAddSynth_setInput, METH_O, "Sets a new input object."}, {"setPitch", (PyCFunction)PVAddSynth_setPitch, METH_O, "Sets a new transposition factor."}, {"setNum", (PyCFunction)PVAddSynth_setNum, METH_O, "Sets the number of oscillators."}, {"setFirst", (PyCFunction)PVAddSynth_setFirst, METH_O, "Sets the first bin to synthesize."}, {"setInc", (PyCFunction)PVAddSynth_setInc, METH_O, "Sets the synthesized bin increment."}, {"setMul", (PyCFunction)PVAddSynth_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)PVAddSynth_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)PVAddSynth_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)PVAddSynth_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods PVAddSynth_as_number = { (binaryfunc)PVAddSynth_add, /*nb_add*/ (binaryfunc)PVAddSynth_sub, /*nb_subtract*/ (binaryfunc)PVAddSynth_multiply, /*nb_multiply*/ (binaryfunc)PVAddSynth_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)PVAddSynth_inplace_add, /*inplace_add*/ (binaryfunc)PVAddSynth_inplace_sub, /*inplace_subtract*/ (binaryfunc)PVAddSynth_inplace_multiply, /*inplace_multiply*/ (binaryfunc)PVAddSynth_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject PVAddSynthType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVAddSynth_base", /*tp_name*/ sizeof(PVAddSynth), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVAddSynth_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &PVAddSynth_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVAddSynth objects. Phase Vocoder additive resynthesis object.", /* tp_doc */ (traverseproc)PVAddSynth_traverse, /* tp_traverse */ (inquiry)PVAddSynth_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVAddSynth_methods, /* tp_methods */ PVAddSynth_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVAddSynth_new, /* tp_new */ }; /*****************/ /** PVTranspose **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PVStream *pv_stream; PyObject *transpo; Stream *transpo_stream; int size; int olaps; int hsize; int hopsize; int overcount; MYFLT **magn; MYFLT **freq; int *count; int modebuffer[1]; } PVTranspose; static void PVTranspose_realloc_memories(PVTranspose *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->overcount = 0; self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVTranspose_process_i(PVTranspose *self) { int i, k, index; MYFLT transpo; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); transpo = PyFloat_AS_DOUBLE(self->transpo); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVTranspose_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { for (k=0; khsize; k++) { self->magn[self->overcount][k] = 0.0; self->freq[self->overcount][k] = 0.0; } for (k=0; khsize; k++) { index = (int)(k * transpo); if (index < self->hsize) { self->magn[self->overcount][index] += magn[self->overcount][k]; self->freq[self->overcount][index] = freq[self->overcount][k] * transpo; } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVTranspose_process_a(PVTranspose *self) { int i, k, index; MYFLT transpo; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *tr = Stream_getData((Stream *)self->transpo_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVTranspose_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { transpo = tr[i]; for (k=0; khsize; k++) { self->magn[self->overcount][k] = 0.0; self->freq[self->overcount][k] = 0.0; } for (k=0; khsize; k++) { index = (int)(k * transpo); if (index < self->hsize) { self->magn[self->overcount][index] += magn[self->overcount][k]; self->freq[self->overcount][index] = freq[self->overcount][k] * transpo; } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVTranspose_setProcMode(PVTranspose *self) { int procmode; procmode = self->modebuffer[0]; switch (procmode) { case 0: self->proc_func_ptr = PVTranspose_process_i; break; case 1: self->proc_func_ptr = PVTranspose_process_a; break; } } static void PVTranspose_compute_next_data_frame(PVTranspose *self) { (*self->proc_func_ptr)(self); } static int PVTranspose_traverse(PVTranspose *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pv_stream); Py_VISIT(self->transpo); Py_VISIT(self->transpo_stream); return 0; } static int PVTranspose_clear(PVTranspose *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pv_stream); Py_CLEAR(self->transpo); Py_CLEAR(self->transpo_stream); return 0; } static void PVTranspose_dealloc(PVTranspose* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); free(self->count); PVTranspose_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVTranspose_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *transpotmp; PVTranspose *self; self = (PVTranspose *)type->tp_alloc(type, 0); self->transpo = PyFloat_FromDouble(1); self->size = 1024; self->olaps = 4; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVTranspose_compute_next_data_frame); self->mode_func_ptr = PVTranspose_setProcMode; static char *kwlist[] = {"input", "transpo", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &inputtmp, &transpotmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVTranspose must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); if (transpotmp) { PyObject_CallMethod((PyObject *)self, "setTranspo", "O", transpotmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVTranspose_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVTranspose_getServer(PVTranspose* self) { GET_SERVER }; static PyObject * PVTranspose_getStream(PVTranspose* self) { GET_STREAM }; static PyObject * PVTranspose_getPVStream(PVTranspose* self) { GET_PV_STREAM }; static PyObject * PVTranspose_play(PVTranspose *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVTranspose_stop(PVTranspose *self) { STOP }; static PyObject * PVTranspose_setInput(PVTranspose *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVTranspose must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVTranspose_setTranspo(PVTranspose *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->transpo); if (isNumber == 1) { self->transpo = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->transpo = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->transpo, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->transpo_stream); self->transpo_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVTranspose_members[] = { {"server", T_OBJECT_EX, offsetof(PVTranspose, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVTranspose, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVTranspose, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVTranspose, input), 0, "FFT sound object."}, {"transpo", T_OBJECT_EX, offsetof(PVTranspose, transpo), 0, "Transposition factor."}, {NULL} /* Sentinel */ }; static PyMethodDef PVTranspose_methods[] = { {"getServer", (PyCFunction)PVTranspose_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVTranspose_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVTranspose_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVTranspose_setInput, METH_O, "Sets a new input object."}, {"setTranspo", (PyCFunction)PVTranspose_setTranspo, METH_O, "Sets the transposition factor."}, {"play", (PyCFunction)PVTranspose_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVTranspose_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVTransposeType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVTranspose_base", /*tp_name*/ sizeof(PVTranspose), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVTranspose_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVTranspose objects. Spectral domain transposition.", /* tp_doc */ (traverseproc)PVTranspose_traverse, /* tp_traverse */ (inquiry)PVTranspose_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVTranspose_methods, /* tp_methods */ PVTranspose_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVTranspose_new, /* tp_new */ }; /*****************/ /** PVVerb **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PVStream *pv_stream; PyObject *revtime; Stream *revtime_stream; PyObject *damp; Stream *damp_stream; int size; int olaps; int hsize; int hopsize; int overcount; MYFLT *l_magn; MYFLT *l_freq; MYFLT **magn; MYFLT **freq; int *count; int modebuffer[2]; } PVVerb; static void PVVerb_realloc_memories(PVVerb *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->overcount = 0; self->l_magn = (MYFLT *)realloc(self->l_magn, self->hsize * sizeof(MYFLT)); self->l_freq = (MYFLT *)realloc(self->l_freq, self->hsize * sizeof(MYFLT)); for (i=0; ihsize; i++) self->l_magn[i] = self->l_freq[i] = 0.0; self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVVerb_process_ii(PVVerb *self) { int i, k; MYFLT revtime, damp, mag, amp, fre; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); revtime = PyFloat_AS_DOUBLE(self->revtime); damp = PyFloat_AS_DOUBLE(self->damp); if (revtime < 0.0) revtime = 0.0; else if (revtime > 1.0) revtime = 1.0; revtime = revtime * 0.25 + 0.75; if (damp < 0.0) damp = 0.0; else if (damp > 1.0) damp = 1.0; damp = damp * 0.003 + 0.997; if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVVerb_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { amp = 1.0; for (k=0; khsize; k++) { mag = magn[self->overcount][k]; fre = freq[self->overcount][k]; if (mag > self->l_magn[k]) { self->magn[self->overcount][k] = self->l_magn[k] = mag; self->freq[self->overcount][k] = self->l_freq[k] = fre; } else { self->magn[self->overcount][k] = self->l_magn[k] = mag + (self->l_magn[k] - mag) * revtime * amp; self->freq[self->overcount][k] = self->l_freq[k] = fre + (self->l_freq[k] - fre) * revtime * amp; } amp *= damp; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVVerb_process_ai(PVVerb *self) { int i, k; MYFLT revtime, damp, mag, amp, fre; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *rvt = Stream_getData((Stream *)self->revtime_stream); damp = PyFloat_AS_DOUBLE(self->damp); if (damp < 0.0) damp = 0.0; else if (damp > 1.0) damp = 1.0; damp = damp * 0.003 + 0.997; if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVVerb_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { revtime = rvt[i]; if (revtime < 0.0) revtime = 0.0; else if (revtime > 1.0) revtime = 1.0; revtime = revtime * 0.25 + 0.75; amp = 1.0; for (k=0; khsize; k++) { mag = magn[self->overcount][k]; fre = freq[self->overcount][k]; if (mag > self->l_magn[k]) { self->magn[self->overcount][k] = self->l_magn[k] = mag; self->freq[self->overcount][k] = self->l_freq[k] = fre; } else { self->magn[self->overcount][k] = self->l_magn[k] = mag + (self->l_magn[k] - mag) * revtime * amp; self->freq[self->overcount][k] = self->l_freq[k] = fre + (self->l_freq[k] - fre) * revtime * amp; } amp *= damp; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVVerb_process_ia(PVVerb *self) { int i, k; MYFLT revtime, damp, mag, amp, fre; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); revtime = PyFloat_AS_DOUBLE(self->revtime); MYFLT *dmp = Stream_getData((Stream *)self->damp_stream); if (revtime < 0.0) revtime = 0.0; else if (revtime > 1.0) revtime = 1.0; revtime = revtime * 0.25 + 0.75; if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVVerb_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { damp = dmp[i]; if (damp < 0.0) damp = 0.0; else if (damp > 1.0) damp = 1.0; damp = damp * 0.003 + 0.997; amp = 1.0; for (k=0; khsize; k++) { mag = magn[self->overcount][k]; fre = freq[self->overcount][k]; if (mag > self->l_magn[k]) { self->magn[self->overcount][k] = self->l_magn[k] = mag; self->freq[self->overcount][k] = self->l_freq[k] = fre; } else { self->magn[self->overcount][k] = self->l_magn[k] = mag + (self->l_magn[k] - mag) * revtime * amp; self->freq[self->overcount][k] = self->l_freq[k] = fre + (self->l_freq[k] - fre) * revtime * amp; } amp *= damp; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVVerb_process_aa(PVVerb *self) { int i, k; MYFLT revtime, damp, mag, amp, fre; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *rvt = Stream_getData((Stream *)self->revtime_stream); MYFLT *dmp = Stream_getData((Stream *)self->damp_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVVerb_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { revtime = rvt[i]; if (revtime < 0.0) revtime = 0.0; else if (revtime > 1.0) revtime = 1.0; revtime = revtime * 0.25 + 0.75; damp = dmp[i]; if (damp < 0.0) damp = 0.0; else if (damp > 1.0) damp = 1.0; damp = damp * 0.003 + 0.997; amp = 1.0; for (k=0; khsize; k++) { mag = magn[self->overcount][k]; fre = freq[self->overcount][k]; if (mag > self->l_magn[k]) { self->magn[self->overcount][k] = self->l_magn[k] = mag; self->freq[self->overcount][k] = self->l_freq[k] = fre; } else { self->magn[self->overcount][k] = self->l_magn[k] = mag + (self->l_magn[k] - mag) * revtime * amp; self->freq[self->overcount][k] = self->l_freq[k] = fre + (self->l_freq[k] - fre) * revtime * amp; } amp *= damp; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVVerb_setProcMode(PVVerb *self) { int procmode; procmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = PVVerb_process_ii; break; case 1: self->proc_func_ptr = PVVerb_process_ai; break; case 10: self->proc_func_ptr = PVVerb_process_ia; break; case 11: self->proc_func_ptr = PVVerb_process_aa; break; } } static void PVVerb_compute_next_data_frame(PVVerb *self) { (*self->proc_func_ptr)(self); } static int PVVerb_traverse(PVVerb *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pv_stream); Py_VISIT(self->revtime); Py_VISIT(self->revtime_stream); Py_VISIT(self->damp); Py_VISIT(self->damp_stream); return 0; } static int PVVerb_clear(PVVerb *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pv_stream); Py_CLEAR(self->revtime); Py_CLEAR(self->revtime_stream); Py_CLEAR(self->damp); Py_CLEAR(self->damp_stream); return 0; } static void PVVerb_dealloc(PVVerb* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); free(self->l_magn); free(self->l_freq); free(self->count); PVVerb_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *revtimetmp=NULL, *damptmp=NULL; PVVerb *self; self = (PVVerb *)type->tp_alloc(type, 0); self->revtime = PyFloat_FromDouble(0.75); self->damp = PyFloat_FromDouble(0.75); self->size = 1024; self->olaps = 4; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVVerb_compute_next_data_frame); self->mode_func_ptr = PVVerb_setProcMode; static char *kwlist[] = {"input", "revtime", "damp", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &revtimetmp, &damptmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVVerb must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); if (revtimetmp) { PyObject_CallMethod((PyObject *)self, "setRevtime", "O", revtimetmp); } if (damptmp) { PyObject_CallMethod((PyObject *)self, "setDamp", "O", damptmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVVerb_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVVerb_getServer(PVVerb* self) { GET_SERVER }; static PyObject * PVVerb_getStream(PVVerb* self) { GET_STREAM }; static PyObject * PVVerb_getPVStream(PVVerb* self) { GET_PV_STREAM }; static PyObject * PVVerb_play(PVVerb *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVVerb_stop(PVVerb *self) { STOP }; static PyObject * PVVerb_setInput(PVVerb *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVVerb must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVVerb_setRevtime(PVVerb *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->revtime); if (isNumber == 1) { self->revtime = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->revtime = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->revtime, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->revtime_stream); self->revtime_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * PVVerb_setDamp(PVVerb *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->damp); if (isNumber == 1) { self->damp = PyNumber_Float(tmp); self->modebuffer[1] = 0; } else { self->damp = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->damp, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->damp_stream); self->damp_stream = (Stream *)streamtmp; self->modebuffer[1] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVVerb_members[] = { {"server", T_OBJECT_EX, offsetof(PVVerb, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVVerb, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVVerb, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVVerb, input), 0, "FFT sound object."}, {"revtime", T_OBJECT_EX, offsetof(PVVerb, revtime), 0, "reverberation factor."}, {"damp", T_OBJECT_EX, offsetof(PVVerb, damp), 0, "High frequency damping factor."}, {NULL} /* Sentinel */ }; static PyMethodDef PVVerb_methods[] = { {"getServer", (PyCFunction)PVVerb_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVVerb_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVVerb_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVVerb_setInput, METH_O, "Sets a new input object."}, {"setRevtime", (PyCFunction)PVVerb_setRevtime, METH_O, "Sets the reverberation factor."}, {"setDamp", (PyCFunction)PVVerb_setDamp, METH_O, "Sets the high frequency damping factor."}, {"play", (PyCFunction)PVVerb_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVVerb_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVVerbType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVVerb_base", /*tp_name*/ sizeof(PVVerb), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVVerb_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVVerb objects. Spectral reverberation.", /* tp_doc */ (traverseproc)PVVerb_traverse, /* tp_traverse */ (inquiry)PVVerb_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVVerb_methods, /* tp_methods */ PVVerb_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVVerb_new, /* tp_new */ }; /*****************/ /** PVGate **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PVStream *pv_stream; PyObject *thresh; Stream *thresh_stream; PyObject *damp; Stream *damp_stream; int size; int olaps; int hsize; int hopsize; int overcount; MYFLT **magn; MYFLT **freq; int *count; int modebuffer[2]; } PVGate; static void PVGate_realloc_memories(PVGate *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->overcount = 0; self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVGate_process_ii(PVGate *self) { int i, k; MYFLT thresh, damp, mag; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); thresh = PyFloat_AS_DOUBLE(self->thresh); damp = PyFloat_AS_DOUBLE(self->damp); thresh = MYPOW(10.0, thresh * 0.05); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVGate_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { for (k=0; khsize; k++) { mag = magn[self->overcount][k]; if (mag < thresh) self->magn[self->overcount][k] = mag * damp; else self->magn[self->overcount][k] = mag; self->freq[self->overcount][k] = freq[self->overcount][k]; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVGate_process_ai(PVGate *self) { int i, k; MYFLT thresh, damp, mag; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *rvt = Stream_getData((Stream *)self->thresh_stream); damp = PyFloat_AS_DOUBLE(self->damp); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVGate_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { thresh = rvt[i]; thresh = MYPOW(10.0, thresh * 0.05); for (k=0; khsize; k++) { mag = magn[self->overcount][k]; if (mag < thresh) self->magn[self->overcount][k] = mag * damp; else self->magn[self->overcount][k] = mag; self->freq[self->overcount][k] = freq[self->overcount][k]; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVGate_process_ia(PVGate *self) { int i, k; MYFLT thresh, damp, mag; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); thresh = PyFloat_AS_DOUBLE(self->thresh); MYFLT *dmp = Stream_getData((Stream *)self->damp_stream); thresh = MYPOW(10.0, thresh * 0.05); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVGate_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { damp = dmp[i]; for (k=0; khsize; k++) { mag = magn[self->overcount][k]; if (mag < thresh) self->magn[self->overcount][k] = mag * damp; else self->magn[self->overcount][k] = mag; self->freq[self->overcount][k] = freq[self->overcount][k]; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVGate_process_aa(PVGate *self) { int i, k; MYFLT thresh, damp, mag; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *rvt = Stream_getData((Stream *)self->thresh_stream); MYFLT *dmp = Stream_getData((Stream *)self->damp_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVGate_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { thresh = rvt[i]; thresh = MYPOW(10.0, thresh * 0.05); damp = dmp[i]; for (k=0; khsize; k++) { mag = magn[self->overcount][k]; if (mag < thresh) self->magn[self->overcount][k] = mag * damp; else self->magn[self->overcount][k] = mag; self->freq[self->overcount][k] = freq[self->overcount][k]; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVGate_setProcMode(PVGate *self) { int procmode; procmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = PVGate_process_ii; break; case 1: self->proc_func_ptr = PVGate_process_ai; break; case 10: self->proc_func_ptr = PVGate_process_ia; break; case 11: self->proc_func_ptr = PVGate_process_aa; break; } } static void PVGate_compute_next_data_frame(PVGate *self) { (*self->proc_func_ptr)(self); } static int PVGate_traverse(PVGate *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pv_stream); Py_VISIT(self->thresh); Py_VISIT(self->thresh_stream); Py_VISIT(self->damp); Py_VISIT(self->damp_stream); return 0; } static int PVGate_clear(PVGate *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pv_stream); Py_CLEAR(self->thresh); Py_CLEAR(self->thresh_stream); Py_CLEAR(self->damp); Py_CLEAR(self->damp_stream); return 0; } static void PVGate_dealloc(PVGate* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); free(self->count); PVGate_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVGate_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *threshtmp=NULL, *damptmp=NULL; PVGate *self; self = (PVGate *)type->tp_alloc(type, 0); self->thresh = PyFloat_FromDouble(-20); self->damp = PyFloat_FromDouble(0.0); self->size = 1024; self->olaps = 4; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVGate_compute_next_data_frame); self->mode_func_ptr = PVGate_setProcMode; static char *kwlist[] = {"input", "thresh", "damp", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &threshtmp, &damptmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVGate must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); if (threshtmp) { PyObject_CallMethod((PyObject *)self, "setThresh", "O", threshtmp); } if (damptmp) { PyObject_CallMethod((PyObject *)self, "setDamp", "O", damptmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVGate_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVGate_getServer(PVGate* self) { GET_SERVER }; static PyObject * PVGate_getStream(PVGate* self) { GET_STREAM }; static PyObject * PVGate_getPVStream(PVGate* self) { GET_PV_STREAM }; static PyObject * PVGate_play(PVGate *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVGate_stop(PVGate *self) { STOP }; static PyObject * PVGate_setInput(PVGate *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVGate must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVGate_setThresh(PVGate *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->thresh); if (isNumber == 1) { self->thresh = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->thresh = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->thresh, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->thresh_stream); self->thresh_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * PVGate_setDamp(PVGate *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->damp); if (isNumber == 1) { self->damp = PyNumber_Float(tmp); self->modebuffer[1] = 0; } else { self->damp = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->damp, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->damp_stream); self->damp_stream = (Stream *)streamtmp; self->modebuffer[1] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVGate_members[] = { {"server", T_OBJECT_EX, offsetof(PVGate, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVGate, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVGate, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVGate, input), 0, "FFT sound object."}, {"thresh", T_OBJECT_EX, offsetof(PVGate, thresh), 0, "Threshold factor."}, {"damp", T_OBJECT_EX, offsetof(PVGate, damp), 0, "Damping factor for bins below threshold."}, {NULL} /* Sentinel */ }; static PyMethodDef PVGate_methods[] = { {"getServer", (PyCFunction)PVGate_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVGate_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVGate_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVGate_setInput, METH_O, "Sets a new input object."}, {"setThresh", (PyCFunction)PVGate_setThresh, METH_O, "Sets the Threshold factor."}, {"setDamp", (PyCFunction)PVGate_setDamp, METH_O, "Sets the damping factor."}, {"play", (PyCFunction)PVGate_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVGate_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVGateType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVGate_base", /*tp_name*/ sizeof(PVGate), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVGate_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVGate objects. Spectral gate.", /* tp_doc */ (traverseproc)PVGate_traverse, /* tp_traverse */ (inquiry)PVGate_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVGate_methods, /* tp_methods */ PVGate_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVGate_new, /* tp_new */ }; /*****************/ /** PVCross **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PyObject *input2; PVStream *input2_stream; PVStream *pv_stream; PyObject *fade; Stream *fade_stream; int size; int olaps; int hsize; int hopsize; int overcount; MYFLT **magn; MYFLT **freq; int *count; int modebuffer[1]; } PVCross; static void PVCross_realloc_memories(PVCross *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->overcount = 0; self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVCross_process_i(PVCross *self) { int i, k; MYFLT fade; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); MYFLT **magn2 = PVStream_getMagn((PVStream *)self->input2_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); fade = PyFloat_AS_DOUBLE(self->fade); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVCross_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { for (k=0; khsize; k++) { self->magn[self->overcount][k] = magn[self->overcount][k] + (magn2[self->overcount][k] - magn[self->overcount][k]) * fade; self->freq[self->overcount][k] = freq[self->overcount][k]; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVCross_process_a(PVCross *self) { int i, k; MYFLT fade; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); MYFLT **magn2 = PVStream_getMagn((PVStream *)self->input2_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *fd = Stream_getData((Stream *)self->fade_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVCross_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { fade = fd[i]; for (k=0; khsize; k++) { self->magn[self->overcount][k] = magn[self->overcount][k] + (magn2[self->overcount][k] - magn[self->overcount][k]) * fade; self->freq[self->overcount][k] = freq[self->overcount][k]; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVCross_setProcMode(PVCross *self) { int procmode; procmode = self->modebuffer[0]; switch (procmode) { case 0: self->proc_func_ptr = PVCross_process_i; break; case 1: self->proc_func_ptr = PVCross_process_a; break; } } static void PVCross_compute_next_data_frame(PVCross *self) { (*self->proc_func_ptr)(self); } static int PVCross_traverse(PVCross *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->input2); Py_VISIT(self->input2_stream); Py_VISIT(self->pv_stream); Py_VISIT(self->fade); Py_VISIT(self->fade_stream); return 0; } static int PVCross_clear(PVCross *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->input2); Py_CLEAR(self->input2_stream); Py_CLEAR(self->pv_stream); Py_CLEAR(self->fade); Py_CLEAR(self->fade_stream); return 0; } static void PVCross_dealloc(PVCross* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); free(self->count); PVCross_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVCross_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *fadetmp; PVCross *self; self = (PVCross *)type->tp_alloc(type, 0); self->fade = PyFloat_FromDouble(1); self->size = 1024; self->olaps = 4; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVCross_compute_next_data_frame); self->mode_func_ptr = PVCross_setProcMode; static char *kwlist[] = {"input", "input2", "fade", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, &inputtmp, &input2tmp, &fadetmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVCross must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; if ( PyObject_HasAttrString((PyObject *)input2tmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVCross must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(input2tmp); Py_XDECREF(self->input2); self->input2 = input2tmp; input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getPVStream", NULL); Py_INCREF(input2_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (PVStream *)input2_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); if (fadetmp) { PyObject_CallMethod((PyObject *)self, "setFade", "O", fadetmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVCross_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVCross_getServer(PVCross* self) { GET_SERVER }; static PyObject * PVCross_getStream(PVCross* self) { GET_STREAM }; static PyObject * PVCross_getPVStream(PVCross* self) { GET_PV_STREAM }; static PyObject * PVCross_play(PVCross *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVCross_stop(PVCross *self) { STOP }; static PyObject * PVCross_setInput(PVCross *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVCross must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVCross_setInput2(PVCross *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVCross must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input2); self->input2 = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVCross_setFade(PVCross *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->fade); if (isNumber == 1) { self->fade = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->fade = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->fade, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->fade_stream); self->fade_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVCross_members[] = { {"server", T_OBJECT_EX, offsetof(PVCross, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVCross, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVCross, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVCross, input), 0, "FFT sound object."}, {"input2", T_OBJECT_EX, offsetof(PVCross, input2), 0, "FFT sound object."}, {"fade", T_OBJECT_EX, offsetof(PVCross, fade), 0, "fadesition factor."}, {NULL} /* Sentinel */ }; static PyMethodDef PVCross_methods[] = { {"getServer", (PyCFunction)PVCross_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVCross_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVCross_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVCross_setInput, METH_O, "Sets a new input object."}, {"setInput2", (PyCFunction)PVCross_setInput2, METH_O, "Sets a new input object."}, {"setFade", (PyCFunction)PVCross_setFade, METH_O, "Sets the fadesition factor."}, {"play", (PyCFunction)PVCross_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVCross_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVCrossType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVCross_base", /*tp_name*/ sizeof(PVCross), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVCross_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVCross objects. Cross-synthesis.", /* tp_doc */ (traverseproc)PVCross_traverse, /* tp_traverse */ (inquiry)PVCross_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVCross_methods, /* tp_methods */ PVCross_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVCross_new, /* tp_new */ }; /*****************/ /** PVMult **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PyObject *input2; PVStream *input2_stream; PVStream *pv_stream; int size; int olaps; int hsize; int hopsize; int overcount; MYFLT **magn; MYFLT **freq; int *count; } PVMult; static void PVMult_realloc_memories(PVMult *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->overcount = 0; self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVMult_process_i(PVMult *self) { int i, k; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); MYFLT **magn2 = PVStream_getMagn((PVStream *)self->input2_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVMult_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { for (k=0; khsize; k++) { self->magn[self->overcount][k] = magn[self->overcount][k] * magn2[self->overcount][k] * 10; self->freq[self->overcount][k] = freq[self->overcount][k]; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVMult_setProcMode(PVMult *self) { self->proc_func_ptr = PVMult_process_i; } static void PVMult_compute_next_data_frame(PVMult *self) { (*self->proc_func_ptr)(self); } static int PVMult_traverse(PVMult *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->input2); Py_VISIT(self->input2_stream); Py_VISIT(self->pv_stream); return 0; } static int PVMult_clear(PVMult *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->input2); Py_CLEAR(self->input2_stream); Py_CLEAR(self->pv_stream); return 0; } static void PVMult_dealloc(PVMult* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); free(self->count); PVMult_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVMult_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp; PVMult *self; self = (PVMult *)type->tp_alloc(type, 0); self->size = 1024; self->olaps = 4; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVMult_compute_next_data_frame); self->mode_func_ptr = PVMult_setProcMode; static char *kwlist[] = {"input", "input2", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &inputtmp, &input2tmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVMult must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; if ( PyObject_HasAttrString((PyObject *)input2tmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVMult must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(input2tmp); Py_XDECREF(self->input2); self->input2 = input2tmp; input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getPVStream", NULL); Py_INCREF(input2_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (PVStream *)input2_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVMult_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVMult_getServer(PVMult* self) { GET_SERVER }; static PyObject * PVMult_getStream(PVMult* self) { GET_STREAM }; static PyObject * PVMult_getPVStream(PVMult* self) { GET_PV_STREAM }; static PyObject * PVMult_play(PVMult *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVMult_stop(PVMult *self) { STOP }; static PyObject * PVMult_setInput(PVMult *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVMult must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVMult_setInput2(PVMult *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVMult must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input2); self->input2 = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVMult_members[] = { {"server", T_OBJECT_EX, offsetof(PVMult, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVMult, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVMult, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVMult, input), 0, "FFT sound object."}, {"input2", T_OBJECT_EX, offsetof(PVMult, input2), 0, "FFT sound object."}, {NULL} /* Sentinel */ }; static PyMethodDef PVMult_methods[] = { {"getServer", (PyCFunction)PVMult_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVMult_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVMult_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVMult_setInput, METH_O, "Sets a new input object."}, {"setInput2", (PyCFunction)PVMult_setInput2, METH_O, "Sets a new input object."}, {"play", (PyCFunction)PVMult_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVMult_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVMultType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVMult_base", /*tp_name*/ sizeof(PVMult), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVMult_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVMult objects. Multiply magnitudes from two pv streams.", /* tp_doc */ (traverseproc)PVMult_traverse, /* tp_traverse */ (inquiry)PVMult_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVMult_methods, /* tp_methods */ PVMult_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVMult_new, /* tp_new */ }; /*****************/ /** PVMorph **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PyObject *input2; PVStream *input2_stream; PVStream *pv_stream; PyObject *fade; Stream *fade_stream; int size; int olaps; int hsize; int hopsize; int overcount; MYFLT **magn; MYFLT **freq; int *count; int modebuffer[1]; } PVMorph; static void PVMorph_realloc_memories(PVMorph *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->overcount = 0; self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVMorph_process_i(PVMorph *self) { int i, k; MYFLT fade, fr1, fr2, div; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); MYFLT **magn2 = PVStream_getMagn((PVStream *)self->input2_stream); MYFLT **freq2 = PVStream_getFreq((PVStream *)self->input2_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); fade = PyFloat_AS_DOUBLE(self->fade); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVMorph_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { for (k=0; khsize; k++) { self->magn[self->overcount][k] = magn[self->overcount][k] + (magn2[self->overcount][k] - magn[self->overcount][k]) * fade; fr1 = freq[self->overcount][k]; fr2 = freq2[self->overcount][k]; div = fr1 ? fr2 / fr1 : 1000000.0; div = div > 0 ? div : -div; self->freq[self->overcount][k] = fr1 * MYPOW(div, fade); } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVMorph_process_a(PVMorph *self) { int i, k; MYFLT fade, fr1, fr2, div; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); MYFLT **magn2 = PVStream_getMagn((PVStream *)self->input2_stream); MYFLT **freq2 = PVStream_getFreq((PVStream *)self->input2_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *fd = Stream_getData((Stream *)self->fade_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVMorph_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { fade = fd[i]; for (k=0; khsize; k++) { self->magn[self->overcount][k] = magn[self->overcount][k] + (magn2[self->overcount][k] - magn[self->overcount][k]) * fade; fr1 = freq[self->overcount][k]; fr2 = freq2[self->overcount][k]; div = fr1 ? fr2 / fr1 : 1000000.0; div = div > 0 ? div : -div; self->freq[self->overcount][k] = fr1 * MYPOW(div, fade); } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVMorph_setProcMode(PVMorph *self) { int procmode; procmode = self->modebuffer[0]; switch (procmode) { case 0: self->proc_func_ptr = PVMorph_process_i; break; case 1: self->proc_func_ptr = PVMorph_process_a; break; } } static void PVMorph_compute_next_data_frame(PVMorph *self) { (*self->proc_func_ptr)(self); } static int PVMorph_traverse(PVMorph *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->input2); Py_VISIT(self->input2_stream); Py_VISIT(self->pv_stream); Py_VISIT(self->fade); Py_VISIT(self->fade_stream); return 0; } static int PVMorph_clear(PVMorph *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->input2); Py_CLEAR(self->input2_stream); Py_CLEAR(self->pv_stream); Py_CLEAR(self->fade); Py_CLEAR(self->fade_stream); return 0; } static void PVMorph_dealloc(PVMorph* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); free(self->count); PVMorph_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVMorph_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *fadetmp; PVMorph *self; self = (PVMorph *)type->tp_alloc(type, 0); self->fade = PyFloat_FromDouble(0.5); self->size = 1024; self->olaps = 4; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVMorph_compute_next_data_frame); self->mode_func_ptr = PVMorph_setProcMode; static char *kwlist[] = {"input", "input2", "fade", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, &inputtmp, &input2tmp, &fadetmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVMorph must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; if ( PyObject_HasAttrString((PyObject *)input2tmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVMorph must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(input2tmp); Py_XDECREF(self->input2); self->input2 = input2tmp; input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getPVStream", NULL); Py_INCREF(input2_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (PVStream *)input2_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); if (fadetmp) { PyObject_CallMethod((PyObject *)self, "setFade", "O", fadetmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVMorph_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVMorph_getServer(PVMorph* self) { GET_SERVER }; static PyObject * PVMorph_getStream(PVMorph* self) { GET_STREAM }; static PyObject * PVMorph_getPVStream(PVMorph* self) { GET_PV_STREAM }; static PyObject * PVMorph_play(PVMorph *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVMorph_stop(PVMorph *self) { STOP }; static PyObject * PVMorph_setInput(PVMorph *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVMorph must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVMorph_setInput2(PVMorph *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVMorph must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input2); self->input2 = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVMorph_setFade(PVMorph *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->fade); if (isNumber == 1) { self->fade = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->fade = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->fade, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->fade_stream); self->fade_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVMorph_members[] = { {"server", T_OBJECT_EX, offsetof(PVMorph, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVMorph, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVMorph, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVMorph, input), 0, "FFT sound object."}, {"input2", T_OBJECT_EX, offsetof(PVMorph, input2), 0, "FFT sound object."}, {"fade", T_OBJECT_EX, offsetof(PVMorph, fade), 0, "fadesition factor."}, {NULL} /* Sentinel */ }; static PyMethodDef PVMorph_methods[] = { {"getServer", (PyCFunction)PVMorph_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVMorph_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVMorph_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVMorph_setInput, METH_O, "Sets a new input object."}, {"setInput2", (PyCFunction)PVMorph_setInput2, METH_O, "Sets a new input object."}, {"setFade", (PyCFunction)PVMorph_setFade, METH_O, "Sets the fadesition factor."}, {"play", (PyCFunction)PVMorph_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVMorph_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVMorphType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVMorph_base", /*tp_name*/ sizeof(PVMorph), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVMorph_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVMorph objects. Cross-synthesis.", /* tp_doc */ (traverseproc)PVMorph_traverse, /* tp_traverse */ (inquiry)PVMorph_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVMorph_methods, /* tp_methods */ PVMorph_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVMorph_new, /* tp_new */ }; /*****************/ /** PVFilter **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PVStream *pv_stream; PyObject *gain; Stream *gain_stream; PyObject *table; int size; int olaps; int hsize; int hopsize; int overcount; int mode; MYFLT **magn; MYFLT **freq; int *count; int modebuffer[1]; } PVFilter; static void PVFilter_realloc_memories(PVFilter *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->overcount = 0; self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVFilter_process_i(PVFilter *self) { int i, k, ipart=0; MYFLT gain, amp, binamp, factor, index=0.0; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *tablelist = TableStream_getData(self->table); int tsize = TableStream_getSize(self->table); gain = PyFloat_AS_DOUBLE(self->gain); if (gain < 0) gain = 0.0; else if (gain > 1) gain = 1.0; if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVFilter_realloc_memories(self); } factor = (MYFLT)tsize / self->hsize; for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { if (self->mode == 0) { for (k=0; khsize; k++) { if (k < tsize) binamp = tablelist[k]; else binamp = 0.0; amp = magn[self->overcount][k]; self->magn[self->overcount][k] = amp + ((binamp*amp) - amp) * gain; self->freq[self->overcount][k] = freq[self->overcount][k]; } } else { for (k=0; khsize; k++) { index = k * factor; ipart = (int)index; binamp = tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart); amp = magn[self->overcount][k]; self->magn[self->overcount][k] = amp + ((binamp*amp) - amp) * gain; self->freq[self->overcount][k] = freq[self->overcount][k]; } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVFilter_process_a(PVFilter *self) { int i, k, ipart=0; MYFLT gain, amp, binamp, factor, index=0.0; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *tablelist = TableStream_getData(self->table); int tsize = TableStream_getSize(self->table); MYFLT *gn = Stream_getData((Stream *)self->gain_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVFilter_realloc_memories(self); } factor = (MYFLT)tsize / self->hsize; for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { gain = gn[i]; if (gain < 0) gain = 0.0; else if (gain > 1) gain = 1.0; if (self->mode == 0) { for (k=0; khsize; k++) { if (k < tsize) binamp = tablelist[k]; else binamp = 0.0; amp = magn[self->overcount][k]; self->magn[self->overcount][k] = amp + ((binamp*amp) - amp) * gain; self->freq[self->overcount][k] = freq[self->overcount][k]; } } else { for (k=0; khsize; k++) { index = k * factor; ipart = (int)index; binamp = tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart); amp = magn[self->overcount][k]; self->magn[self->overcount][k] = amp + ((binamp*amp) - amp) * gain; self->freq[self->overcount][k] = freq[self->overcount][k]; } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVFilter_setProcMode(PVFilter *self) { int procmode; procmode = self->modebuffer[0]; switch (procmode) { case 0: self->proc_func_ptr = PVFilter_process_i; break; case 1: self->proc_func_ptr = PVFilter_process_a; break; } } static void PVFilter_compute_next_data_frame(PVFilter *self) { (*self->proc_func_ptr)(self); } static int PVFilter_traverse(PVFilter *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pv_stream); Py_VISIT(self->gain); Py_VISIT(self->gain_stream); Py_VISIT(self->table); return 0; } static int PVFilter_clear(PVFilter *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pv_stream); Py_CLEAR(self->gain); Py_CLEAR(self->gain_stream); Py_CLEAR(self->table); return 0; } static void PVFilter_dealloc(PVFilter* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); free(self->count); PVFilter_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVFilter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *tabletmp, *gaintmp=NULL; PVFilter *self; self = (PVFilter *)type->tp_alloc(type, 0); self->gain = PyFloat_FromDouble(1); self->size = 1024; self->olaps = 4; self->mode = 0; /* 0 : index outside table range clipped to 0 1 : index between 0 and hsize are scaled over table length */ INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVFilter_compute_next_data_frame); self->mode_func_ptr = PVFilter_setProcMode; static char *kwlist[] = {"input", "table", "gain", "mode", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|Oi", kwlist, &inputtmp, &tabletmp, &gaintmp, &self->mode)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVFilter must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if (gaintmp) { PyObject_CallMethod((PyObject *)self, "setGain", "O", gaintmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVFilter_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVFilter_getServer(PVFilter* self) { GET_SERVER }; static PyObject * PVFilter_getStream(PVFilter* self) { GET_STREAM }; static PyObject * PVFilter_getPVStream(PVFilter* self) { GET_PV_STREAM }; static PyObject * PVFilter_play(PVFilter *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVFilter_stop(PVFilter *self) { STOP }; static PyObject * PVFilter_setInput(PVFilter *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVFilter must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVFilter_setGain(PVFilter *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->gain); if (isNumber == 1) { self->gain = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->gain = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->gain, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->gain_stream); self->gain_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * PVFilter_getTable(PVFilter* self) { Py_INCREF(self->table); return self->table; }; static PyObject * PVFilter_setTable(PVFilter *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * PVFilter_setMode(PVFilter *self, PyObject *arg) { int tmp; if (PyLong_Check(arg) || PyInt_Check(arg)) { tmp = PyInt_AsLong(arg); if (tmp <= 0) self->mode = 0; else self->mode = 1; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVFilter_members[] = { {"server", T_OBJECT_EX, offsetof(PVFilter, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVFilter, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVFilter, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVFilter, input), 0, "FFT sound object."}, {"table", T_OBJECT_EX, offsetof(PVFilter, table), 0, "Filter table."}, {"gain", T_OBJECT_EX, offsetof(PVFilter, gain), 0, "gainsition factor."}, {NULL} /* Sentinel */ }; static PyMethodDef PVFilter_methods[] = { {"getServer", (PyCFunction)PVFilter_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVFilter_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVFilter_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVFilter_setInput, METH_O, "Sets a new input object."}, {"getTable", (PyCFunction)PVFilter_getTable, METH_NOARGS, "Returns filter table object."}, {"setTable", (PyCFunction)PVFilter_setTable, METH_O, "Sets filter table."}, {"setGain", (PyCFunction)PVFilter_setGain, METH_O, "Sets the gain factor."}, {"setMode", (PyCFunction)PVFilter_setMode, METH_O, "Sets the table scanning mode."}, {"play", (PyCFunction)PVFilter_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVFilter_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVFilterType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVFilter_base", /*tp_name*/ sizeof(PVFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVFilter_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVFilter objects. Spectral domain gainsition.", /* tp_doc */ (traverseproc)PVFilter_traverse, /* tp_traverse */ (inquiry)PVFilter_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVFilter_methods, /* tp_methods */ PVFilter_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVFilter_new, /* tp_new */ }; /*****************/ /** PVDelay **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PVStream *pv_stream; PyObject *deltable; PyObject *feedtable; int size; int olaps; int hsize; int hopsize; int overcount; MYFLT maxdelay; int numFrames; int framecount; MYFLT **magn; MYFLT **freq; MYFLT **magn_buf; MYFLT **freq_buf; int *count; int mode; } PVDelay; static void PVDelay_realloc_memories(PVDelay *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->numFrames = (int)(self->maxdelay * self->sr / self->hopsize + 0.5); self->overcount = 0; self->framecount = 0; self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } self->magn_buf = (MYFLT **)realloc(self->magn_buf, self->numFrames * sizeof(MYFLT *)); self->freq_buf = (MYFLT **)realloc(self->freq_buf, self->numFrames * sizeof(MYFLT *)); for (i=0; inumFrames; i++) { self->magn_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn_buf[i][j] = self->freq_buf[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVDelay_process_zero(PVDelay *self) { int i, k, bindel; MYFLT binfeed, mg, fr; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *dellist = TableStream_getData(self->deltable); int tsize = TableStream_getSize(self->deltable); MYFLT *feedlist = TableStream_getData(self->feedtable); int fsize = TableStream_getSize(self->feedtable); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVDelay_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { for (k=0; khsize; k++) { if (k < tsize) { bindel = (int)dellist[k]; if (bindel < 0) bindel = 0; else if (bindel >= self->numFrames) bindel = self->numFrames - 1; } else bindel = 0; if (k < fsize) { binfeed = feedlist[k]; if (binfeed < -1.0) binfeed = -1.0; else if (binfeed > 1.0) binfeed = 1.0; } else binfeed = 0; bindel = self->framecount - bindel; if (bindel < 0) bindel += self->numFrames; if (bindel == self->framecount) { self->magn[self->overcount][k] = magn[self->overcount][k]; self->freq[self->overcount][k] = freq[self->overcount][k]; } else { self->magn[self->overcount][k] = mg = self->magn_buf[bindel][k]; self->freq[self->overcount][k] = fr = self->freq_buf[bindel][k]; self->magn_buf[self->framecount][k] = magn[self->overcount][k] + mg * binfeed; self->freq_buf[self->framecount][k] = freq[self->overcount][k] + (fr - freq[self->overcount][k]) * binfeed; } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; self->framecount++; if (self->framecount >= self->numFrames) self->framecount = 0; } } } static void PVDelay_process_scaled(PVDelay *self) { int i, k, bindel, ipart; MYFLT binfeed, mg, fr, tfac, ffac, index; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *dellist = TableStream_getData(self->deltable); int tsize = TableStream_getSize(self->deltable); MYFLT *feedlist = TableStream_getData(self->feedtable); int fsize = TableStream_getSize(self->feedtable); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVDelay_realloc_memories(self); } tfac = (MYFLT)tsize / self->hsize; ffac = (MYFLT)fsize / self->hsize; for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { for (k=0; khsize; k++) { index = k * tfac; ipart = (int)index; bindel = (int)(dellist[ipart] + (dellist[ipart+1] - dellist[ipart]) * (index - ipart)); if (bindel < 0) bindel = 0; else if (bindel >= self->numFrames) bindel = self->numFrames - 1; index = k * ffac; ipart = (int)index; binfeed = feedlist[ipart] + (feedlist[ipart+1] - feedlist[ipart]) * (index - ipart); if (binfeed < -1.0) binfeed = -1.0; else if (binfeed > 1.0) binfeed = 1.0; bindel = self->framecount - bindel; if (bindel < 0) bindel += self->numFrames; if (bindel == self->framecount) { self->magn[self->overcount][k] = magn[self->overcount][k]; self->freq[self->overcount][k] = freq[self->overcount][k]; } else { self->magn[self->overcount][k] = mg = self->magn_buf[bindel][k]; self->freq[self->overcount][k] = fr = self->freq_buf[bindel][k]; self->magn_buf[self->framecount][k] = magn[self->overcount][k] + mg * binfeed; self->freq_buf[self->framecount][k] = freq[self->overcount][k] + (fr - freq[self->overcount][k]) * binfeed; } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; self->framecount++; if (self->framecount >= self->numFrames) self->framecount = 0; } } } static void PVDelay_setProcMode(PVDelay *self) { if (self->mode == 0) self->proc_func_ptr = PVDelay_process_zero; else self->proc_func_ptr = PVDelay_process_scaled; } static void PVDelay_compute_next_data_frame(PVDelay *self) { (*self->proc_func_ptr)(self); } static int PVDelay_traverse(PVDelay *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pv_stream); Py_VISIT(self->deltable); Py_VISIT(self->feedtable); return 0; } static int PVDelay_clear(PVDelay *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pv_stream); Py_CLEAR(self->deltable); Py_CLEAR(self->feedtable); return 0; } static void PVDelay_dealloc(PVDelay* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); for(i=0; inumFrames; i++) { free(self->magn_buf[i]); free(self->freq_buf[i]); } free(self->magn_buf); free(self->freq_buf); free(self->count); PVDelay_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVDelay_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *deltabletmp, *feedtabletmp; PVDelay *self; self = (PVDelay *)type->tp_alloc(type, 0); self->size = 1024; self->olaps = 4; self->maxdelay = 1.0; self->mode = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVDelay_compute_next_data_frame); self->mode_func_ptr = PVDelay_setProcMode; static char *kwlist[] = {"input", "deltable", "feedtable", "maxdelay", "mode", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OOO_FI, kwlist, &inputtmp, &deltabletmp, &feedtabletmp, &self->maxdelay, &self->mode)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVDelay must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); Py_XDECREF(self->deltable); self->deltable = PyObject_CallMethod((PyObject *)deltabletmp, "getTableStream", ""); Py_XDECREF(self->feedtable); self->feedtable = PyObject_CallMethod((PyObject *)feedtabletmp, "getTableStream", ""); PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVDelay_realloc_memories(self); self->mode = self->mode <= 0 ? 0 : 1; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVDelay_getServer(PVDelay* self) { GET_SERVER }; static PyObject * PVDelay_getStream(PVDelay* self) { GET_STREAM }; static PyObject * PVDelay_getPVStream(PVDelay* self) { GET_PV_STREAM }; static PyObject * PVDelay_play(PVDelay *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVDelay_stop(PVDelay *self) { STOP }; static PyObject * PVDelay_setInput(PVDelay *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVDelay must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVDelay_getDeltable(PVDelay* self) { Py_INCREF(self->deltable); return self->deltable; }; static PyObject * PVDelay_setDeltable(PVDelay *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->deltable); self->deltable = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * PVDelay_getFeedtable(PVDelay* self) { Py_INCREF(self->feedtable); return self->feedtable; }; static PyObject * PVDelay_setFeedtable(PVDelay *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->feedtable); self->feedtable = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * PVDelay_setMode(PVDelay *self, PyObject *arg) { int tmp; if (PyLong_Check(arg) || PyInt_Check(arg)) { tmp = PyInt_AsLong(arg); if (tmp <= 0) self->mode = 0; else self->mode = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVDelay_members[] = { {"server", T_OBJECT_EX, offsetof(PVDelay, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVDelay, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVDelay, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVDelay, input), 0, "FFT sound object."}, {"deltable", T_OBJECT_EX, offsetof(PVDelay, deltable), 0, "Delays table."}, {"feedtable", T_OBJECT_EX, offsetof(PVDelay, feedtable), 0, "Feedbacks table."}, {NULL} /* Sentinel */ }; static PyMethodDef PVDelay_methods[] = { {"getServer", (PyCFunction)PVDelay_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVDelay_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVDelay_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVDelay_setInput, METH_O, "Sets a new input object."}, {"getDeltable", (PyCFunction)PVDelay_getDeltable, METH_NOARGS, "Returns delays table object."}, {"setDeltable", (PyCFunction)PVDelay_setDeltable, METH_O, "Sets delays table."}, {"getFeedtable", (PyCFunction)PVDelay_getFeedtable, METH_NOARGS, "Returns feedbacks table object."}, {"setFeedtable", (PyCFunction)PVDelay_setFeedtable, METH_O, "Sets feedbacks table."}, {"setMode", (PyCFunction)PVDelay_setMode, METH_O, "Table scanning method."}, {"play", (PyCFunction)PVDelay_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVDelay_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVDelayType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVDelay_base", /*tp_name*/ sizeof(PVDelay), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVDelay_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVDelay objects. Spectral delay.", /* tp_doc */ (traverseproc)PVDelay_traverse, /* tp_traverse */ (inquiry)PVDelay_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVDelay_methods, /* tp_methods */ PVDelay_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVDelay_new, /* tp_new */ }; /*****************/ /** PVBuffer **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PVStream *pv_stream; PyObject *index; Stream *index_stream; PyObject *pitch; Stream *pitch_stream; int size; int olaps; int hsize; int hopsize; int overcount; MYFLT length; int numFrames; int framecount; MYFLT **magn; MYFLT **freq; MYFLT **magn_buf; MYFLT **freq_buf; int *count; int modebuffer[1]; } PVBuffer; static void PVBuffer_realloc_memories(PVBuffer *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->numFrames = (int)(self->length * self->sr / self->hopsize + 0.5); self->overcount = 0; self->framecount = 0; self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } self->magn_buf = (MYFLT **)realloc(self->magn_buf, self->numFrames * sizeof(MYFLT *)); self->freq_buf = (MYFLT **)realloc(self->freq_buf, self->numFrames * sizeof(MYFLT *)); for (i=0; inumFrames; i++) { self->magn_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn_buf[i][j] = self->freq_buf[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVBuffer_process_i(PVBuffer *self) { int i, k, frame, indexi; MYFLT index, pitch; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *ind = Stream_getData((Stream *)self->index_stream); pitch = PyFloat_AS_DOUBLE(self->pitch); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVBuffer_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { if (self->framecount < self->numFrames) { for (k=0; khsize; k++) { self->magn_buf[self->framecount][k] = magn[self->overcount][k]; self->freq_buf[self->framecount][k] = freq[self->overcount][k]; } self->framecount++; } for (k=0; khsize; k++) { self->magn[self->overcount][k] = 0.0; self->freq[self->overcount][k] = 0.0; } index = ind[i]; if (index < 0.0) index = 0.0; else if (index >= 1.0) index = 1.0; frame = (int)(index * self->numFrames); for (k=0; khsize; k++) { indexi = (int)(k * pitch); if (indexi < self->hsize) { self->magn[self->overcount][indexi] += self->magn_buf[frame][k]; self->freq[self->overcount][indexi] = self->freq_buf[frame][k] * pitch; } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVBuffer_process_a(PVBuffer *self) { int i, k, frame, indexi; MYFLT index, pitch; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *ind = Stream_getData((Stream *)self->index_stream); MYFLT *pit = Stream_getData((Stream *)self->pitch_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVBuffer_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { if (self->framecount < self->numFrames) { for (k=0; khsize; k++) { self->magn_buf[self->framecount][k] = magn[self->overcount][k]; self->freq_buf[self->framecount][k] = freq[self->overcount][k]; } self->framecount++; } for (k=0; khsize; k++) { self->magn[self->overcount][k] = 0.0; self->freq[self->overcount][k] = 0.0; } index = ind[i]; pitch = pit[i]; if (index < 0.0) index = 0.0; else if (index >= 1.0) index = 1.0; frame = (int)(index * self->numFrames); for (k=0; khsize; k++) { indexi = (int)(k * pitch); if (indexi < self->hsize) { self->magn[self->overcount][indexi] += self->magn_buf[frame][k]; self->freq[self->overcount][indexi] = self->freq_buf[frame][k] * pitch; } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVBuffer_setProcMode(PVBuffer *self) { int procmode; procmode = self->modebuffer[0]; switch (procmode) { case 0: self->proc_func_ptr = PVBuffer_process_i; break; case 1: self->proc_func_ptr = PVBuffer_process_a; break; } } static void PVBuffer_compute_next_data_frame(PVBuffer *self) { (*self->proc_func_ptr)(self); } static int PVBuffer_traverse(PVBuffer *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pv_stream); Py_VISIT(self->index); Py_VISIT(self->index_stream); Py_VISIT(self->pitch); Py_VISIT(self->pitch_stream); return 0; } static int PVBuffer_clear(PVBuffer *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pv_stream); Py_CLEAR(self->index); Py_CLEAR(self->index_stream); Py_CLEAR(self->pitch); Py_CLEAR(self->pitch_stream); return 0; } static void PVBuffer_dealloc(PVBuffer* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); for(i=0; inumFrames; i++) { free(self->magn_buf[i]); free(self->freq_buf[i]); } free(self->magn_buf); free(self->freq_buf); free(self->count); PVBuffer_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVBuffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *indextmp, *pitchtmp=NULL; PVBuffer *self; self = (PVBuffer *)type->tp_alloc(type, 0); self->pitch = PyFloat_FromDouble(1); self->size = 1024; self->olaps = 4; self->length = 1.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVBuffer_compute_next_data_frame); self->mode_func_ptr = PVBuffer_setProcMode; static char *kwlist[] = {"input", "index", "pitch", "length", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_OF, kwlist, &inputtmp, &indextmp, &pitchtmp, &self->length)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVBuffer must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); if (indextmp) { PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp); } if (pitchtmp) { PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVBuffer_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVBuffer_getServer(PVBuffer* self) { GET_SERVER }; static PyObject * PVBuffer_getStream(PVBuffer* self) { GET_STREAM }; static PyObject * PVBuffer_getPVStream(PVBuffer* self) { GET_PV_STREAM }; static PyObject * PVBuffer_play(PVBuffer *self, PyObject *args, PyObject *kwds) { self->framecount = 0; PLAY }; static PyObject * PVBuffer_stop(PVBuffer *self) { STOP }; static PyObject * PVBuffer_setInput(PVBuffer *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVBuffer must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVBuffer_setIndex(PVBuffer *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL tmp = arg; if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) { PyErr_SetString(PyExc_TypeError, "\"index\" argument of PVBuffer must be a PyoObject.\n"); Py_RETURN_NONE; } Py_INCREF(tmp); Py_XDECREF(self->index); self->index = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->index_stream); self->index_stream = (Stream *)streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVBuffer_setPitch(PVBuffer *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pitch); if (isNumber == 1) { self->pitch = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->pitch = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pitch, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pitch_stream); self->pitch_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVBuffer_members[] = { {"server", T_OBJECT_EX, offsetof(PVBuffer, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVBuffer, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVBuffer, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVBuffer, input), 0, "FFT sound object."}, {"index", T_OBJECT_EX, offsetof(PVBuffer, index), 0, "Pointer position."}, {"pitch", T_OBJECT_EX, offsetof(PVBuffer, pitch), 0, "Transposition factor."}, {NULL} /* Sentinel */ }; static PyMethodDef PVBuffer_methods[] = { {"getServer", (PyCFunction)PVBuffer_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVBuffer_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVBuffer_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVBuffer_setInput, METH_O, "Sets a new input object."}, {"setIndex", (PyCFunction)PVBuffer_setIndex, METH_O, "Sets a new pointer object."}, {"setPitch", (PyCFunction)PVBuffer_setPitch, METH_O, "Sets a new transposition factor."}, {"play", (PyCFunction)PVBuffer_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVBuffer_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVBufferType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVBuffer_base", /*tp_name*/ sizeof(PVBuffer), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVBuffer_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVBuffer objects. Phase vocoder buffer and playback reader.", /* tp_doc */ (traverseproc)PVBuffer_traverse, /* tp_traverse */ (inquiry)PVBuffer_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVBuffer_methods, /* tp_methods */ PVBuffer_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVBuffer_new, /* tp_new */ }; /*****************/ /** PVShift **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PVStream *pv_stream; PyObject *shift; Stream *shift_stream; int size; int olaps; int hsize; int hopsize; int overcount; MYFLT **magn; MYFLT **freq; int *count; int modebuffer[1]; } PVShift; static void PVShift_realloc_memories(PVShift *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->overcount = 0; self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVShift_process_i(PVShift *self) { int i, k, index, dev; MYFLT shift, freqPerBin; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); shift = PyFloat_AS_DOUBLE(self->shift); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVShift_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { for (k=0; khsize; k++) { self->magn[self->overcount][k] = 0.0; self->freq[self->overcount][k] = 0.0; } freqPerBin = self->sr / self->size; dev = (int)MYFLOOR(shift / freqPerBin); for (k=0; khsize; k++) { index = k + dev; if (index >= 0 && index < self->hsize) { self->magn[self->overcount][index] += magn[self->overcount][k]; self->freq[self->overcount][index] = freq[self->overcount][k] + shift; } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVShift_process_a(PVShift *self) { int i, k, index, dev; MYFLT shift, freqPerBin; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *sh = Stream_getData((Stream *)self->shift_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVShift_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { shift = sh[i]; for (k=0; khsize; k++) { self->magn[self->overcount][k] = 0.0; self->freq[self->overcount][k] = 0.0; } freqPerBin = self->sr / self->size; dev = (int)MYFLOOR(shift / freqPerBin); for (k=0; khsize; k++) { index = k + dev; if (index >= 0 && index < self->hsize) { self->magn[self->overcount][index] += magn[self->overcount][k]; self->freq[self->overcount][index] = freq[self->overcount][k] + shift; } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVShift_setProcMode(PVShift *self) { int procmode; procmode = self->modebuffer[0]; switch (procmode) { case 0: self->proc_func_ptr = PVShift_process_i; break; case 1: self->proc_func_ptr = PVShift_process_a; break; } } static void PVShift_compute_next_data_frame(PVShift *self) { (*self->proc_func_ptr)(self); } static int PVShift_traverse(PVShift *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pv_stream); Py_VISIT(self->shift); Py_VISIT(self->shift_stream); return 0; } static int PVShift_clear(PVShift *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pv_stream); Py_CLEAR(self->shift); Py_CLEAR(self->shift_stream); return 0; } static void PVShift_dealloc(PVShift* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); free(self->count); PVShift_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVShift_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *shifttmp; PVShift *self; self = (PVShift *)type->tp_alloc(type, 0); self->shift = PyFloat_FromDouble(0); self->size = 1024; self->olaps = 4; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVShift_compute_next_data_frame); self->mode_func_ptr = PVShift_setProcMode; static char *kwlist[] = {"input", "shift", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &inputtmp, &shifttmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVShift must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); if (shifttmp) { PyObject_CallMethod((PyObject *)self, "setShift", "O", shifttmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVShift_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVShift_getServer(PVShift* self) { GET_SERVER }; static PyObject * PVShift_getStream(PVShift* self) { GET_STREAM }; static PyObject * PVShift_getPVStream(PVShift* self) { GET_PV_STREAM }; static PyObject * PVShift_play(PVShift *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVShift_stop(PVShift *self) { STOP }; static PyObject * PVShift_setInput(PVShift *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVShift must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVShift_setShift(PVShift *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->shift); if (isNumber == 1) { self->shift = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->shift = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->shift, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->shift_stream); self->shift_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVShift_members[] = { {"server", T_OBJECT_EX, offsetof(PVShift, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVShift, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVShift, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVShift, input), 0, "FFT sound object."}, {"shift", T_OBJECT_EX, offsetof(PVShift, shift), 0, "Frequency shifting factor."}, {NULL} /* Sentinel */ }; static PyMethodDef PVShift_methods[] = { {"getServer", (PyCFunction)PVShift_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVShift_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVShift_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVShift_setInput, METH_O, "Sets a new input object."}, {"setShift", (PyCFunction)PVShift_setShift, METH_O, "Sets the frequency shifting factor."}, {"play", (PyCFunction)PVShift_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVShift_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVShiftType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVShift_base", /*tp_name*/ sizeof(PVShift), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVShift_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVShift objects. Frequency shifter in the spectral domain.", /* tp_doc */ (traverseproc)PVShift_traverse, /* tp_traverse */ (inquiry)PVShift_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVShift_methods, /* tp_methods */ PVShift_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVShift_new, /* tp_new */ }; /*****************/ /** PVAmpMod **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PVStream *pv_stream; PyObject *basefreq; Stream *basefreq_stream; PyObject *spread; Stream *spread_stream; int size; int olaps; int hsize; int hopsize; int overcount; MYFLT factor; MYFLT *table; MYFLT *pointers; MYFLT **magn; MYFLT **freq; int *count; int modebuffer[2]; } PVAmpMod; static void PVAmpMod_realloc_memories(PVAmpMod *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->overcount = 0; self->factor = 8192.0 / (self->sr / self->hopsize); self->pointers = (MYFLT *)realloc(self->pointers, self->hsize * sizeof(MYFLT)); for (i=0; ihsize; i++) self->pointers[i] = 0.0; self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVAmpMod_process_ii(PVAmpMod *self) { int i, k; MYFLT bfreq, spread, pos; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); bfreq = PyFloat_AS_DOUBLE(self->basefreq); spread = PyFloat_AS_DOUBLE(self->spread); spread *= 0.001; spread += 1.0; if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVAmpMod_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { for (k=0; khsize; k++) { pos = self->pointers[k]; self->magn[self->overcount][k] = magn[self->overcount][k] * self->table[(int)pos]; self->freq[self->overcount][k] = freq[self->overcount][k]; pos += bfreq * MYPOW(spread, k) * self->factor; while (pos >= 8192.0) pos -= 8192.0; while (pos < 0.0) pos += 8192.0; self->pointers[k] = pos; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVAmpMod_process_ai(PVAmpMod *self) { int i, k; MYFLT bfreq, spread, pos; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *bf = Stream_getData((Stream *)self->basefreq_stream); spread = PyFloat_AS_DOUBLE(self->spread); spread *= 0.001; spread += 1.0; if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVAmpMod_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { bfreq = bf[i]; for (k=0; khsize; k++) { pos = self->pointers[k]; self->magn[self->overcount][k] = magn[self->overcount][k] * self->table[(int)pos]; self->freq[self->overcount][k] = freq[self->overcount][k]; pos += bfreq * MYPOW(spread, k) * self->factor; while (pos >= 8192.0) pos -= 8192.0; while (pos < 0.0) pos += 8192.0; self->pointers[k] = pos; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVAmpMod_process_ia(PVAmpMod *self) { int i, k; MYFLT bfreq, spread, pos; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); bfreq = PyFloat_AS_DOUBLE(self->basefreq); MYFLT *sp = Stream_getData((Stream *)self->spread_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVAmpMod_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { spread = sp[i]; spread *= 0.001; spread += 1.0; for (k=0; khsize; k++) { pos = self->pointers[k]; self->magn[self->overcount][k] = magn[self->overcount][k] * self->table[(int)pos]; self->freq[self->overcount][k] = freq[self->overcount][k]; pos += bfreq * MYPOW(spread, k) * self->factor; while (pos >= 8192.0) pos -= 8192.0; while (pos < 0.0) pos += 8192.0; self->pointers[k] = pos; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVAmpMod_process_aa(PVAmpMod *self) { int i, k; MYFLT bfreq, spread, pos; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *bf = Stream_getData((Stream *)self->basefreq_stream); MYFLT *sp = Stream_getData((Stream *)self->spread_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVAmpMod_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { bfreq = bf[i]; spread = sp[i]; spread *= 0.001; spread += 1.0; for (k=0; khsize; k++) { pos = self->pointers[k]; self->magn[self->overcount][k] = magn[self->overcount][k] * self->table[(int)pos]; self->freq[self->overcount][k] = freq[self->overcount][k]; pos += bfreq * MYPOW(spread, k) * self->factor; while (pos >= 8192.0) pos -= 8192.0; while (pos < 0.0) pos += 8192.0; self->pointers[k] = pos; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVAmpMod_setProcMode(PVAmpMod *self) { int procmode; procmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = PVAmpMod_process_ii; break; case 1: self->proc_func_ptr = PVAmpMod_process_ai; break; case 10: self->proc_func_ptr = PVAmpMod_process_ia; break; case 11: self->proc_func_ptr = PVAmpMod_process_aa; break; } } static void PVAmpMod_compute_next_data_frame(PVAmpMod *self) { (*self->proc_func_ptr)(self); } static int PVAmpMod_traverse(PVAmpMod *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pv_stream); Py_VISIT(self->basefreq); Py_VISIT(self->basefreq_stream); Py_VISIT(self->spread); Py_VISIT(self->spread_stream); return 0; } static int PVAmpMod_clear(PVAmpMod *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pv_stream); Py_CLEAR(self->basefreq); Py_CLEAR(self->basefreq_stream); Py_CLEAR(self->spread); Py_CLEAR(self->spread_stream); return 0; } static void PVAmpMod_dealloc(PVAmpMod* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); free(self->table); free(self->pointers); free(self->count); PVAmpMod_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVAmpMod_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *basefreqtmp=NULL, *spreadtmp=NULL; PVAmpMod *self; self = (PVAmpMod *)type->tp_alloc(type, 0); self->basefreq = PyFloat_FromDouble(1); self->spread = PyFloat_FromDouble(0); self->size = 1024; self->olaps = 4; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVAmpMod_compute_next_data_frame); self->mode_func_ptr = PVAmpMod_setProcMode; static char *kwlist[] = {"input", "basefreq", "spread", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &basefreqtmp, &spreadtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVAmpMod must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); if (basefreqtmp) { PyObject_CallMethod((PyObject *)self, "setBasefreq", "O", basefreqtmp); } if (spreadtmp) { PyObject_CallMethod((PyObject *)self, "setSpread", "O", spreadtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); self->table = (MYFLT *)realloc(self->table, 8193 * sizeof(MYFLT)); for (i=0; i<8192; i++) self->table[i] = (MYFLT)(MYSIN(TWOPI * i / 8192.0) * 0.5 + 0.5); self->table[8192] = 0.5; PVAmpMod_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVAmpMod_getServer(PVAmpMod* self) { GET_SERVER }; static PyObject * PVAmpMod_getStream(PVAmpMod* self) { GET_STREAM }; static PyObject * PVAmpMod_getPVStream(PVAmpMod* self) { GET_PV_STREAM }; static PyObject * PVAmpMod_play(PVAmpMod *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVAmpMod_stop(PVAmpMod *self) { STOP }; static PyObject * PVAmpMod_setInput(PVAmpMod *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVAmpMod must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVAmpMod_setBasefreq(PVAmpMod *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->basefreq); if (isNumber == 1) { self->basefreq = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->basefreq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->basefreq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->basefreq_stream); self->basefreq_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * PVAmpMod_setSpread(PVAmpMod *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->spread); if (isNumber == 1) { self->spread = PyNumber_Float(tmp); self->modebuffer[1] = 0; } else { self->spread = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->spread, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->spread_stream); self->spread_stream = (Stream *)streamtmp; self->modebuffer[1] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * PVAmpMod_reset(PVAmpMod *self) { int i; for (i=0; ihsize; i++) self->pointers[i] = 0.0; Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVAmpMod_members[] = { {"server", T_OBJECT_EX, offsetof(PVAmpMod, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVAmpMod, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVAmpMod, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVAmpMod, input), 0, "FFT sound object."}, {"basefreq", T_OBJECT_EX, offsetof(PVAmpMod, basefreq), 0, "Modulator's base frequency."}, {"spread", T_OBJECT_EX, offsetof(PVAmpMod, spread), 0, "High frequency spreading factor."}, {NULL} /* Sentinel */ }; static PyMethodDef PVAmpMod_methods[] = { {"getServer", (PyCFunction)PVAmpMod_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVAmpMod_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVAmpMod_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVAmpMod_setInput, METH_O, "Sets a new input object."}, {"setBasefreq", (PyCFunction)PVAmpMod_setBasefreq, METH_O, "Sets the modulator's base frequency."}, {"setSpread", (PyCFunction)PVAmpMod_setSpread, METH_O, "Sets the high frequency spreading factor."}, {"reset", (PyCFunction)PVAmpMod_reset, METH_NOARGS, "Resets pointer positions."}, {"play", (PyCFunction)PVAmpMod_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVAmpMod_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVAmpModType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVAmpMod_base", /*tp_name*/ sizeof(PVAmpMod), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVAmpMod_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVAmpMod objects. Frequency independent modulators.", /* tp_doc */ (traverseproc)PVAmpMod_traverse, /* tp_traverse */ (inquiry)PVAmpMod_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVAmpMod_methods, /* tp_methods */ PVAmpMod_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVAmpMod_new, /* tp_new */ }; /*****************/ /** PVFreqMod **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PVStream *pv_stream; PyObject *basefreq; Stream *basefreq_stream; PyObject *spread; Stream *spread_stream; PyObject *depth; Stream *depth_stream; int size; int olaps; int hsize; int hopsize; int overcount; MYFLT factor; MYFLT *table; MYFLT *pointers; MYFLT **magn; MYFLT **freq; int *count; int modebuffer[3]; } PVFreqMod; static void PVFreqMod_realloc_memories(PVFreqMod *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->overcount = 0; self->factor = 8192.0 / (self->sr / self->hopsize); self->pointers = (MYFLT *)realloc(self->pointers, self->hsize * sizeof(MYFLT)); for (i=0; ihsize; i++) self->pointers[i] = 0.0; self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVFreqMod_process_ii(PVFreqMod *self) { int i, k, nbin; MYFLT bfreq, spread, pos, nfreq, freqPerBin, depth; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); bfreq = PyFloat_AS_DOUBLE(self->basefreq); spread = PyFloat_AS_DOUBLE(self->spread); spread *= 0.001; spread += 1.0; if (self->modebuffer[2] == 0) depth = PyFloat_AS_DOUBLE(self->depth); else depth = Stream_getData((Stream *)self->depth_stream)[0]; if (depth < 0) depth = 0.0; else if (depth > 1) depth = 1.0; if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVFreqMod_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { freqPerBin = self->sr / self->size; for (k=0; khsize; k++) { self->magn[self->overcount][k] = self->freq[self->overcount][k] = 0.0; } for (k=0; khsize; k++) { pos = self->pointers[k]; nfreq = freq[self->overcount][k] * (self->table[(int)pos] * depth + 1.0); nbin = (int)(nfreq / freqPerBin); if (nbin > 0 && nbin < self->hsize) { self->magn[self->overcount][nbin] += magn[self->overcount][k]; self->freq[self->overcount][nbin] = nfreq; } pos += bfreq * MYPOW(spread, k) * self->factor; while (pos >= 8192.0) pos -= 8192.0; while (pos < 0.0) pos += 8192.0; self->pointers[k] = pos; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVFreqMod_process_ai(PVFreqMod *self) { int i, k, nbin; MYFLT bfreq, spread, pos, nfreq, freqPerBin, depth; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *bf = Stream_getData((Stream *)self->basefreq_stream); spread = PyFloat_AS_DOUBLE(self->spread); spread *= 0.001; spread += 1.0; if (self->modebuffer[2] == 0) depth = PyFloat_AS_DOUBLE(self->depth); else depth = Stream_getData((Stream *)self->depth_stream)[0]; if (depth < 0) depth = 0.0; else if (depth > 1) depth = 1.0; if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVFreqMod_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { bfreq = bf[i]; freqPerBin = self->sr / self->size; for (k=0; khsize; k++) { self->magn[self->overcount][k] = self->freq[self->overcount][k] = 0.0; } for (k=0; khsize; k++) { pos = self->pointers[k]; nfreq = freq[self->overcount][k] * (self->table[(int)pos] * depth + 1.0); nbin = (int)(nfreq / freqPerBin); if (nbin > 0 && nbin < self->hsize) { self->magn[self->overcount][nbin] += magn[self->overcount][k]; self->freq[self->overcount][nbin] = nfreq; } pos += bfreq * MYPOW(spread, k) * self->factor; while (pos >= 8192.0) pos -= 8192.0; while (pos < 0.0) pos += 8192.0; self->pointers[k] = pos; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVFreqMod_process_ia(PVFreqMod *self) { int i, k, nbin; MYFLT bfreq, spread, pos, nfreq, freqPerBin, depth; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); bfreq = PyFloat_AS_DOUBLE(self->basefreq); MYFLT *sp = Stream_getData((Stream *)self->spread_stream); if (self->modebuffer[2] == 0) depth = PyFloat_AS_DOUBLE(self->depth); else depth = Stream_getData((Stream *)self->depth_stream)[0]; if (depth < 0) depth = 0.0; else if (depth > 1) depth = 1.0; if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVFreqMod_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { spread = sp[i]; spread *= 0.001; spread += 1.0; freqPerBin = self->sr / self->size; for (k=0; khsize; k++) { self->magn[self->overcount][k] = self->freq[self->overcount][k] = 0.0; } for (k=0; khsize; k++) { pos = self->pointers[k]; nfreq = freq[self->overcount][k] * (self->table[(int)pos] * depth + 1.0); nbin = (int)(nfreq / freqPerBin); if (nbin > 0 && nbin < self->hsize) { self->magn[self->overcount][nbin] += magn[self->overcount][k]; self->freq[self->overcount][nbin] = nfreq; } pos += bfreq * MYPOW(spread, k) * self->factor; while (pos >= 8192.0) pos -= 8192.0; while (pos < 0.0) pos += 8192.0; self->pointers[k] = pos; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVFreqMod_process_aa(PVFreqMod *self) { int i, k, nbin; MYFLT bfreq, spread, pos, nfreq, freqPerBin, depth; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *bf = Stream_getData((Stream *)self->basefreq_stream); MYFLT *sp = Stream_getData((Stream *)self->spread_stream); if (self->modebuffer[2] == 0) depth = PyFloat_AS_DOUBLE(self->depth); else depth = Stream_getData((Stream *)self->depth_stream)[0]; if (depth < 0) depth = 0.0; else if (depth > 1) depth = 1.0; if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVFreqMod_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { bfreq = bf[i]; spread = sp[i]; spread *= 0.001; spread += 1.0; freqPerBin = self->sr / self->size; for (k=0; khsize; k++) { self->magn[self->overcount][k] = self->freq[self->overcount][k] = 0.0; } for (k=0; khsize; k++) { pos = self->pointers[k]; nfreq = freq[self->overcount][k] * (self->table[(int)pos] * depth + 1.0); nbin = (int)(nfreq / freqPerBin); if (nbin > 0 && nbin < self->hsize) { self->magn[self->overcount][nbin] += magn[self->overcount][k]; self->freq[self->overcount][nbin] = nfreq; } pos += bfreq * MYPOW(spread, k) * self->factor; while (pos >= 8192.0) pos -= 8192.0; while (pos < 0.0) pos += 8192.0; self->pointers[k] = pos; } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVFreqMod_setProcMode(PVFreqMod *self) { int procmode; procmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = PVFreqMod_process_ii; break; case 1: self->proc_func_ptr = PVFreqMod_process_ai; break; case 10: self->proc_func_ptr = PVFreqMod_process_ia; break; case 11: self->proc_func_ptr = PVFreqMod_process_aa; break; } } static void PVFreqMod_compute_next_data_frame(PVFreqMod *self) { (*self->proc_func_ptr)(self); } static int PVFreqMod_traverse(PVFreqMod *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pv_stream); Py_VISIT(self->basefreq); Py_VISIT(self->basefreq_stream); Py_VISIT(self->spread); Py_VISIT(self->spread_stream); Py_VISIT(self->depth); Py_VISIT(self->depth_stream); return 0; } static int PVFreqMod_clear(PVFreqMod *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pv_stream); Py_CLEAR(self->basefreq); Py_CLEAR(self->basefreq_stream); Py_CLEAR(self->spread); Py_CLEAR(self->spread_stream); Py_CLEAR(self->depth); Py_CLEAR(self->depth_stream); return 0; } static void PVFreqMod_dealloc(PVFreqMod* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); free(self->table); free(self->pointers); free(self->count); PVFreqMod_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVFreqMod_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *basefreqtmp=NULL, *spreadtmp=NULL, *depthtmp=NULL; PVFreqMod *self; self = (PVFreqMod *)type->tp_alloc(type, 0); self->basefreq = PyFloat_FromDouble(1); self->spread = PyFloat_FromDouble(0); self->depth = PyFloat_FromDouble(0.1); self->size = 1024; self->olaps = 4; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVFreqMod_compute_next_data_frame); self->mode_func_ptr = PVFreqMod_setProcMode; static char *kwlist[] = {"input", "basefreq", "spread", "depth", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &basefreqtmp, &spreadtmp, &depthtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVFreqMod must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); if (basefreqtmp) { PyObject_CallMethod((PyObject *)self, "setBasefreq", "O", basefreqtmp); } if (spreadtmp) { PyObject_CallMethod((PyObject *)self, "setSpread", "O", spreadtmp); } if (depthtmp) { PyObject_CallMethod((PyObject *)self, "setDepth", "O", depthtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); self->table = (MYFLT *)realloc(self->table, 8193 * sizeof(MYFLT)); for (i=0; i<8192; i++) self->table[i] = (MYFLT)(MYSIN(TWOPI * i / 8192.0) * 0.5 + 0.5); self->table[8192] = 0.5; PVFreqMod_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVFreqMod_getServer(PVFreqMod* self) { GET_SERVER }; static PyObject * PVFreqMod_getStream(PVFreqMod* self) { GET_STREAM }; static PyObject * PVFreqMod_getPVStream(PVFreqMod* self) { GET_PV_STREAM }; static PyObject * PVFreqMod_play(PVFreqMod *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVFreqMod_stop(PVFreqMod *self) { STOP }; static PyObject * PVFreqMod_setInput(PVFreqMod *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVFreqMod must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVFreqMod_setBasefreq(PVFreqMod *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->basefreq); if (isNumber == 1) { self->basefreq = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->basefreq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->basefreq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->basefreq_stream); self->basefreq_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * PVFreqMod_setSpread(PVFreqMod *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->spread); if (isNumber == 1) { self->spread = PyNumber_Float(tmp); self->modebuffer[1] = 0; } else { self->spread = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->spread, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->spread_stream); self->spread_stream = (Stream *)streamtmp; self->modebuffer[1] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * PVFreqMod_setDepth(PVFreqMod *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->depth); if (isNumber == 1) { self->depth = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->depth = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->depth, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->depth_stream); self->depth_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * PVFreqMod_reset(PVFreqMod *self) { int i; for (i=0; ihsize; i++) self->pointers[i] = 0.0; Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVFreqMod_members[] = { {"server", T_OBJECT_EX, offsetof(PVFreqMod, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVFreqMod, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVFreqMod, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVFreqMod, input), 0, "FFT sound object."}, {"basefreq", T_OBJECT_EX, offsetof(PVFreqMod, basefreq), 0, "Modulator's base frequency."}, {"spread", T_OBJECT_EX, offsetof(PVFreqMod, spread), 0, "High frequency spreading factor."}, {"depth", T_OBJECT_EX, offsetof(PVFreqMod, depth), 0, "Depth of modulators."}, {NULL} /* Sentinel */ }; static PyMethodDef PVFreqMod_methods[] = { {"getServer", (PyCFunction)PVFreqMod_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVFreqMod_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVFreqMod_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVFreqMod_setInput, METH_O, "Sets a new input object."}, {"setBasefreq", (PyCFunction)PVFreqMod_setBasefreq, METH_O, "Sets the modulator's base frequency."}, {"setSpread", (PyCFunction)PVFreqMod_setSpread, METH_O, "Sets the high frequency spreading factor."}, {"setDepth", (PyCFunction)PVFreqMod_setDepth, METH_O, "Sets the modulator's depth."}, {"reset", (PyCFunction)PVFreqMod_reset, METH_NOARGS, "Resets pointer positions."}, {"play", (PyCFunction)PVFreqMod_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVFreqMod_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVFreqModType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVFreqMod_base", /*tp_name*/ sizeof(PVFreqMod), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVFreqMod_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVFreqMod objects. Spectral reverberation.", /* tp_doc */ (traverseproc)PVFreqMod_traverse, /* tp_traverse */ (inquiry)PVFreqMod_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVFreqMod_methods, /* tp_methods */ PVFreqMod_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVFreqMod_new, /* tp_new */ }; /*****************/ /** PVBufLoops **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PVStream *pv_stream; PyObject *low; Stream *low_stream; PyObject *high; Stream *high_stream; int size; int olaps; int hsize; int hopsize; int overcount; int mode; MYFLT last_low; MYFLT last_high; int last_mode; MYFLT length; int numFrames; MYFLT OneOnNumFrames; int framecount; MYFLT *speeds; MYFLT *pointers; MYFLT **magn; MYFLT **freq; MYFLT **magn_buf; MYFLT **freq_buf; int *count; int modebuffer[2]; } PVBufLoops; static void PVBufLoops_realloc_memories(PVBufLoops *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->numFrames = (int)(self->length * self->sr / self->hopsize + 0.5); self->OneOnNumFrames = 1.0 / self->numFrames; self->overcount = 0; self->framecount = 0; self->speeds = (MYFLT *)realloc(self->speeds, self->hsize * sizeof(MYFLT)); self->pointers = (MYFLT *)realloc(self->pointers, self->hsize * sizeof(MYFLT)); for (i=0; ihsize; i++) { self->speeds[i] = 1.0; self->pointers[i] = 0.0; } self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } self->magn_buf = (MYFLT **)realloc(self->magn_buf, self->numFrames * sizeof(MYFLT *)); self->freq_buf = (MYFLT **)realloc(self->freq_buf, self->numFrames * sizeof(MYFLT *)); for (i=0; inumFrames; i++) { self->magn_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn_buf[i][j] = self->freq_buf[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVBufLoops_setSpeeds(PVBufLoops *self, MYFLT low, MYFLT high) { int i; MYFLT tmp; switch (self->mode) { case 0: /* linear */ tmp = (high - low) / self->hsize; for (i=0; ihsize; i++) self->speeds[i] = low + i * tmp; break; case 1: /* exponential */ tmp = high - low; for (i=0; ihsize; i++) self->speeds[i] = low + tmp * MYPOW((float)i/self->hsize, 3.0); break; case 2: /* logarithmic */ tmp = high - low; for (i=0; ihsize; i++) self->speeds[i] = low + tmp * (1.0 - MYPOW(1.0-(float)i/self->hsize, 3.0)); break; case 3: /* random uniform */ tmp = high - low; for (i=0; ihsize; i++) self->speeds[i] = RANDOM_UNIFORM * tmp + low; break; case 4: /* random exponential min */ for (i=0; ihsize; i++) { tmp = -MYLOG(RANDOM_UNIFORM) * 0.05; tmp = tmp < 0 ? 0.0 : tmp; tmp = tmp > 1.0 ? 1.0 : tmp; self->speeds[i] = tmp * (high - low) + low; } break; case 5: /* random exponential max */ for (i=0; ihsize; i++) { tmp = 1.0 - (-MYLOG(RANDOM_UNIFORM) * 0.05); tmp = tmp < 0 ? 0.0 : tmp; tmp = tmp > 1.0 ? 1.0 : tmp; self->speeds[i] = tmp * (high - low) + low; } break; case 6: /* random bi-exponential */ for (i=0; ihsize; i++) { tmp = RANDOM_UNIFORM * 2.0; if (tmp > 1.0) tmp = 0.5 * (-MYLOG(2.0 - tmp) * 0.05) + 0.5; else tmp = 0.5 * (MYLOG(tmp) * 0.05) + 0.5; tmp = tmp < 0 ? 0.0 : tmp; tmp = tmp > 1.0 ? 1.0 : tmp; self->speeds[i] = tmp * (high - low) + low; } break; default: /* linear */ tmp = (high - low) / self->hsize; for (i=0; ihsize; i++) self->speeds[i] = low + i * tmp; break; } } static void PVBufLoops_process(PVBufLoops *self) { int i, k, frame; MYFLT low, high, pos; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVBufLoops_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { if (self->framecount < self->numFrames) { for (k=0; khsize; k++) { self->magn_buf[self->framecount][k] = magn[self->overcount][k]; self->freq_buf[self->framecount][k] = freq[self->overcount][k]; self->magn[self->overcount][k] = 0.0; self->freq[self->overcount][k] = 0.0; } self->framecount++; } else { if (self->modebuffer[0] == 0) low = PyFloat_AS_DOUBLE(self->low); else low = Stream_getData((Stream *)self->low_stream)[i]; if (self->modebuffer[1] == 0) high = PyFloat_AS_DOUBLE(self->high); else high = Stream_getData((Stream *)self->high_stream)[i]; if (low != self->last_low || high != self->last_high || self->mode != self->last_mode) { self->last_low = low; self->last_high = high; self->last_mode = self->mode; PVBufLoops_setSpeeds(self, low, high); } for (k=0; khsize; k++) { pos = self->pointers[k]; frame = (int)(pos * (self->numFrames-1)); self->magn[self->overcount][k] = self->magn_buf[frame][k]; self->freq[self->overcount][k] = self->freq_buf[frame][k]; pos += self->OneOnNumFrames * self->speeds[k]; if (pos < 0.0) pos += 1.0; else if (pos >= 1.0) pos -= 1.0; self->pointers[k] = pos; } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVBufLoops_setProcMode(PVBufLoops *self) { self->proc_func_ptr = PVBufLoops_process; } static void PVBufLoops_compute_next_data_frame(PVBufLoops *self) { (*self->proc_func_ptr)(self); } static int PVBufLoops_traverse(PVBufLoops *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pv_stream); Py_VISIT(self->low); Py_VISIT(self->low_stream); Py_VISIT(self->high); Py_VISIT(self->high_stream); return 0; } static int PVBufLoops_clear(PVBufLoops *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pv_stream); Py_CLEAR(self->low); Py_CLEAR(self->low_stream); Py_CLEAR(self->high); Py_CLEAR(self->high_stream); return 0; } static void PVBufLoops_dealloc(PVBufLoops* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); for(i=0; inumFrames; i++) { free(self->magn_buf[i]); free(self->freq_buf[i]); } free(self->magn_buf); free(self->freq_buf); free(self->count); free(self->speeds); free(self->pointers); PVBufLoops_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVBufLoops_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *lowtmp=NULL, *hightmp=NULL; PVBufLoops *self; self = (PVBufLoops *)type->tp_alloc(type, 0); self->low = PyFloat_FromDouble(1.0); self->high = PyFloat_FromDouble(1.0); self->last_low = self->last_high = -1.0; self->mode = 0; self->last_mode = -1; self->size = 1024; self->olaps = 4; self->length = 1.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVBufLoops_compute_next_data_frame); self->mode_func_ptr = PVBufLoops_setProcMode; static char *kwlist[] = {"input", "low", "high", "mode", "length", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOIF, kwlist, &inputtmp, &lowtmp, &hightmp, &self->mode, &self->length)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVBufLoops must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); if (lowtmp) { PyObject_CallMethod((PyObject *)self, "setLow", "O", lowtmp); } if (hightmp) { PyObject_CallMethod((PyObject *)self, "setHigh", "O", hightmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVBufLoops_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVBufLoops_getServer(PVBufLoops* self) { GET_SERVER }; static PyObject * PVBufLoops_getStream(PVBufLoops* self) { GET_STREAM }; static PyObject * PVBufLoops_getPVStream(PVBufLoops* self) { GET_PV_STREAM }; static PyObject * PVBufLoops_play(PVBufLoops *self, PyObject *args, PyObject *kwds) { int k; for (k=0; khsize; k++) self->pointers[k] = 0.0; self->framecount = 0; PLAY }; static PyObject * PVBufLoops_stop(PVBufLoops *self) { STOP }; static PyObject * PVBufLoops_setInput(PVBufLoops *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVBufLoops must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVBufLoops_setLow(PVBufLoops *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->low); if (isNumber == 1) { self->low = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->low = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->low, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->low_stream); self->low_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * PVBufLoops_setHigh(PVBufLoops *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->high); if (isNumber == 1) { self->high = PyNumber_Float(tmp); self->modebuffer[1] = 0; } else { self->high = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->high, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->high_stream); self->high_stream = (Stream *)streamtmp; self->modebuffer[1] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * PVBufLoops_setMode(PVBufLoops *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { tmp = PyInt_AsLong(arg); if (tmp >= 0 && tmp < 7) self->mode = tmp; } Py_INCREF(Py_None); return Py_None; } static PyObject * PVBufLoops_reset(PVBufLoops *self) { int i; for (i=0; ihsize; i++) self->pointers[i] = 0.0; Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVBufLoops_members[] = { {"server", T_OBJECT_EX, offsetof(PVBufLoops, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVBufLoops, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVBufLoops, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVBufLoops, input), 0, "FFT sound object."}, {"low", T_OBJECT_EX, offsetof(PVBufLoops, low), 0, "Speed of lowest bin."}, {"high", T_OBJECT_EX, offsetof(PVBufLoops, high), 0, "Speed of highest bin."}, {NULL} /* Sentinel */ }; static PyMethodDef PVBufLoops_methods[] = { {"getServer", (PyCFunction)PVBufLoops_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVBufLoops_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVBufLoops_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVBufLoops_setInput, METH_O, "Sets a new input object."}, {"setLow", (PyCFunction)PVBufLoops_setLow, METH_O, "Sets a new lowest speed."}, {"setHigh", (PyCFunction)PVBufLoops_setHigh, METH_O, "Sets a new highest speed."}, {"setMode", (PyCFunction)PVBufLoops_setMode, METH_O, "Sets a new mode."}, {"reset", (PyCFunction)PVBufLoops_reset, METH_NOARGS, "Preset pointer positions."}, {"play", (PyCFunction)PVBufLoops_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVBufLoops_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVBufLoopsType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVBufLoops_base", /*tp_name*/ sizeof(PVBufLoops), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVBufLoops_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVBufLoops objects. Phase vocoder buffer and playback reader.", /* tp_doc */ (traverseproc)PVBufLoops_traverse, /* tp_traverse */ (inquiry)PVBufLoops_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVBufLoops_methods, /* tp_methods */ PVBufLoops_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVBufLoops_new, /* tp_new */ }; /*****************/ /** PVBufTabLoops **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PVStream *pv_stream; PyObject *speed; int size; int olaps; int hsize; int hopsize; int overcount; MYFLT length; int numFrames; MYFLT OneOnNumFrames; int framecount; MYFLT *pointers; MYFLT **magn; MYFLT **freq; MYFLT **magn_buf; MYFLT **freq_buf; int *count; } PVBufTabLoops; static void PVBufTabLoops_realloc_memories(PVBufTabLoops *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->numFrames = (int)(self->length * self->sr / self->hopsize + 0.5); self->OneOnNumFrames = 1.0 / self->numFrames; self->overcount = 0; self->framecount = 0; self->pointers = (MYFLT *)realloc(self->pointers, self->hsize * sizeof(MYFLT)); for (i=0; ihsize; i++) { self->pointers[i] = 0.0; } self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } self->magn_buf = (MYFLT **)realloc(self->magn_buf, self->numFrames * sizeof(MYFLT *)); self->freq_buf = (MYFLT **)realloc(self->freq_buf, self->numFrames * sizeof(MYFLT *)); for (i=0; inumFrames; i++) { self->magn_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn_buf[i][j] = self->freq_buf[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVBufTabLoops_process(PVBufTabLoops *self) { int i, k, frame; MYFLT pos; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); MYFLT *spds = TableStream_getData(self->speed); int splen = TableStream_getSize(self->speed); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVBufTabLoops_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { if (self->framecount < self->numFrames) { for (k=0; khsize; k++) { self->magn_buf[self->framecount][k] = magn[self->overcount][k]; self->freq_buf[self->framecount][k] = freq[self->overcount][k]; self->magn[self->overcount][k] = 0.0; self->freq[self->overcount][k] = 0.0; } self->framecount++; } else { for (k=0; khsize; k++) { pos = self->pointers[k]; frame = (int)(pos * (self->numFrames-1)); self->magn[self->overcount][k] = self->magn_buf[frame][k]; self->freq[self->overcount][k] = self->freq_buf[frame][k]; if (k < splen) { pos += self->OneOnNumFrames * spds[k]; if (pos < 0.0) pos += 1.0; else if (pos >= 1.0) pos -= 1.0; } self->pointers[k] = pos; } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVBufTabLoops_setProcMode(PVBufTabLoops *self) { self->proc_func_ptr = PVBufTabLoops_process; } static void PVBufTabLoops_compute_next_data_frame(PVBufTabLoops *self) { (*self->proc_func_ptr)(self); } static int PVBufTabLoops_traverse(PVBufTabLoops *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pv_stream); Py_VISIT(self->speed); return 0; } static int PVBufTabLoops_clear(PVBufTabLoops *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pv_stream); Py_CLEAR(self->speed); return 0; } static void PVBufTabLoops_dealloc(PVBufTabLoops* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); for(i=0; inumFrames; i++) { free(self->magn_buf[i]); free(self->freq_buf[i]); } free(self->magn_buf); free(self->freq_buf); free(self->count); free(self->pointers); PVBufTabLoops_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVBufTabLoops_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *speedtmp; PVBufTabLoops *self; self = (PVBufTabLoops *)type->tp_alloc(type, 0); self->size = 1024; self->olaps = 4; self->length = 1.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVBufTabLoops_compute_next_data_frame); self->mode_func_ptr = PVBufTabLoops_setProcMode; static char *kwlist[] = {"input", "speed", "length", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_F, kwlist, &inputtmp, &speedtmp, &self->length)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVBufTabLoops must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); Py_XDECREF(self->speed); self->speed = PyObject_CallMethod((PyObject *)speedtmp, "getTableStream", ""); PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVBufTabLoops_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVBufTabLoops_getServer(PVBufTabLoops* self) { GET_SERVER }; static PyObject * PVBufTabLoops_getStream(PVBufTabLoops* self) { GET_STREAM }; static PyObject * PVBufTabLoops_getPVStream(PVBufTabLoops* self) { GET_PV_STREAM }; static PyObject * PVBufTabLoops_play(PVBufTabLoops *self, PyObject *args, PyObject *kwds) { int k; for (k=0; khsize; k++) self->pointers[k] = 0.0; self->framecount = 0; PLAY }; static PyObject * PVBufTabLoops_stop(PVBufTabLoops *self) { STOP }; static PyObject * PVBufTabLoops_setInput(PVBufTabLoops *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVBufTabLoops must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVBufTabLoops_setSpeed(PVBufTabLoops *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->speed); self->speed = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * PVBufTabLoops_reset(PVBufTabLoops *self) { int i; for (i=0; ihsize; i++) self->pointers[i] = 0.0; Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVBufTabLoops_members[] = { {"server", T_OBJECT_EX, offsetof(PVBufTabLoops, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVBufTabLoops, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVBufTabLoops, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVBufTabLoops, input), 0, "FFT sound object."}, {"speed", T_OBJECT_EX, offsetof(PVBufTabLoops, speed), 0, "Table containing speed of every bin."}, {NULL} /* Sentinel */ }; static PyMethodDef PVBufTabLoops_methods[] = { {"getServer", (PyCFunction)PVBufTabLoops_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVBufTabLoops_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVBufTabLoops_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVBufTabLoops_setInput, METH_O, "Sets a new input object."}, {"setSpeed", (PyCFunction)PVBufTabLoops_setSpeed, METH_O, "Change speed table."}, {"reset", (PyCFunction)PVBufTabLoops_reset, METH_NOARGS, "Preset pointer positions."}, {"play", (PyCFunction)PVBufTabLoops_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVBufTabLoops_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVBufTabLoopsType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVBufTabLoops_base", /*tp_name*/ sizeof(PVBufTabLoops), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVBufTabLoops_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVBufTabLoops objects. Phase vocoder buffer and playback reader.", /* tp_doc */ (traverseproc)PVBufTabLoops_traverse, /* tp_traverse */ (inquiry)PVBufTabLoops_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVBufTabLoops_methods, /* tp_methods */ PVBufTabLoops_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVBufTabLoops_new, /* tp_new */ }; /*****************/ /** PVMix **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; PVStream *input_stream; PyObject *input2; PVStream *input2_stream; PVStream *pv_stream; int size; int olaps; int hsize; int hopsize; int overcount; MYFLT **magn; MYFLT **freq; int *count; } PVMix; static void PVMix_realloc_memories(PVMix *self) { int i, j, inputLatency; self->hsize = self->size / 2; self->hopsize = self->size / self->olaps; inputLatency = self->size - self->hopsize; self->overcount = 0; self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *)); for (i=0; iolaps; i++) { self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT)); for (j=0; jhsize; j++) self->magn[i][j] = self->freq[i][j] = 0.0; } for (i=0; ibufsize; i++) self->count[i] = inputLatency; PVStream_setFFTsize(self->pv_stream, self->size); PVStream_setOlaps(self->pv_stream, self->olaps); PVStream_setMagn(self->pv_stream, self->magn); PVStream_setFreq(self->pv_stream, self->freq); PVStream_setCount(self->pv_stream, self->count); } static void PVMix_process_i(PVMix *self) { int i, k; MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream); MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream); MYFLT **magn2 = PVStream_getMagn((PVStream *)self->input2_stream); MYFLT **freq2 = PVStream_getFreq((PVStream *)self->input2_stream); int *count = PVStream_getCount((PVStream *)self->input_stream); int size = PVStream_getFFTsize((PVStream *)self->input_stream); int olaps = PVStream_getOlaps((PVStream *)self->input_stream); if (self->size != size || self->olaps != olaps) { self->size = size; self->olaps = olaps; PVMix_realloc_memories(self); } for (i=0; ibufsize; i++) { self->count[i] = count[i]; if (count[i] >= (self->size-1)) { for (k=0; khsize; k++) { if (magn[self->overcount][k] > magn2[self->overcount][k]) { self->magn[self->overcount][k] = magn[self->overcount][k]; self->freq[self->overcount][k] = freq[self->overcount][k]; } else { self->magn[self->overcount][k] = magn2[self->overcount][k]; self->freq[self->overcount][k] = freq2[self->overcount][k]; } } self->overcount++; if (self->overcount >= self->olaps) self->overcount = 0; } } } static void PVMix_setProcMode(PVMix *self) { self->proc_func_ptr = PVMix_process_i; } static void PVMix_compute_next_data_frame(PVMix *self) { (*self->proc_func_ptr)(self); } static int PVMix_traverse(PVMix *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->input2); Py_VISIT(self->input2_stream); Py_VISIT(self->pv_stream); return 0; } static int PVMix_clear(PVMix *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->input2); Py_CLEAR(self->input2_stream); Py_CLEAR(self->pv_stream); return 0; } static void PVMix_dealloc(PVMix* self) { int i; pyo_DEALLOC for(i=0; iolaps; i++) { free(self->magn[i]); free(self->freq[i]); } free(self->magn); free(self->freq); free(self->count); PVMix_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PVMix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp; PVMix *self; self = (PVMix *)type->tp_alloc(type, 0); self->size = 1024; self->olaps = 4; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PVMix_compute_next_data_frame); self->mode_func_ptr = PVMix_setProcMode; static char *kwlist[] = {"input", "input2", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &inputtmp, &input2tmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVMix must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; if ( PyObject_HasAttrString((PyObject *)input2tmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVMix must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(input2tmp); Py_XDECREF(self->input2); self->input2 = input2tmp; input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getPVStream", NULL); Py_INCREF(input2_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (PVStream *)input2_streamtmp; self->size = PVStream_getFFTsize(self->input_stream); self->olaps = PVStream_getOlaps(self->input_stream); PyObject_CallMethod(self->server, "addStream", "O", self->stream); MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL); self->count = (int *)realloc(self->count, self->bufsize * sizeof(int)); PVMix_realloc_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PVMix_getServer(PVMix* self) { GET_SERVER }; static PyObject * PVMix_getStream(PVMix* self) { GET_STREAM }; static PyObject * PVMix_getPVStream(PVMix* self) { GET_PV_STREAM }; static PyObject * PVMix_play(PVMix *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PVMix_stop(PVMix *self) { STOP }; static PyObject * PVMix_setInput(PVMix *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVMix must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input); self->input = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input_stream); self->input_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * PVMix_setInput2(PVMix *self, PyObject *arg) { PyObject *inputtmp, *input_streamtmp; inputtmp = arg; if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVMix must be a PyoPVObject.\n"); Py_RETURN_NONE; } Py_INCREF(inputtmp); Py_XDECREF(self->input2); self->input2 = inputtmp; input_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getPVStream", NULL); Py_INCREF(input_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (PVStream *)input_streamtmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef PVMix_members[] = { {"server", T_OBJECT_EX, offsetof(PVMix, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PVMix, stream), 0, "Stream object."}, {"pv_stream", T_OBJECT_EX, offsetof(PVMix, pv_stream), 0, "Phase Vocoder Stream object."}, {"input", T_OBJECT_EX, offsetof(PVMix, input), 0, "FFT sound object."}, {"input2", T_OBJECT_EX, offsetof(PVMix, input2), 0, "FFT sound object."}, {NULL} /* Sentinel */ }; static PyMethodDef PVMix_methods[] = { {"getServer", (PyCFunction)PVMix_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PVMix_getStream, METH_NOARGS, "Returns stream object."}, {"_getPVStream", (PyCFunction)PVMix_getPVStream, METH_NOARGS, "Returns pvstream object."}, {"setInput", (PyCFunction)PVMix_setInput, METH_O, "Sets a new input object."}, {"setInput2", (PyCFunction)PVMix_setInput2, METH_O, "Sets a new input object."}, {"play", (PyCFunction)PVMix_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PVMix_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject PVMixType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PVMix_base", /*tp_name*/ sizeof(PVMix), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PVMix_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PVMix objects. Mix two pv streams.", /* tp_doc */ (traverseproc)PVMix_traverse, /* tp_traverse */ (inquiry)PVMix_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PVMix_methods, /* tp_methods */ PVMix_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PVMix_new, /* tp_new */ };pyo/src/objects/delaymodule.c0000644000175000017500000037544212652732202015565 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *delay; Stream *delay_stream; PyObject *feedback; Stream *feedback_stream; MYFLT maxdelay; MYFLT oneOverSr; long size; long in_count; int modebuffer[4]; MYFLT *buffer; // samples memory } Delay; static void Delay_process_ii(Delay *self) { MYFLT val, xind, frac; int i; long ind; MYFLT del = PyFloat_AS_DOUBLE(self->delay); MYFLT feed = PyFloat_AS_DOUBLE(self->feedback); if (del < self->oneOverSr) del = self->oneOverSr; else if (del > self->maxdelay) del = self->maxdelay; MYFLT sampdel = del * self->sr; if (feed < 0) feed = 0; else if (feed > 1) feed = 1; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac; self->data[i] = val; self->buffer[self->in_count] = in[i] + (val * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[self->in_count]; self->in_count++; if (self->in_count >= self->size) self->in_count = 0; } } static void Delay_process_ai(Delay *self) { MYFLT val, xind, frac, sampdel, del; int i; long ind; MYFLT *delobj = Stream_getData((Stream *)self->delay_stream); MYFLT feed = PyFloat_AS_DOUBLE(self->feedback); if (feed < 0) feed = 0; else if (feed > 1) feed = 1; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { del = delobj[i]; if (del < self->oneOverSr) del = self->oneOverSr; else if (del > self->maxdelay) del = self->maxdelay; sampdel = del * self->sr; xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac; self->data[i] = val; self->buffer[self->in_count] = in[i] + (val * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[self->in_count]; self->in_count++; if (self->in_count >= self->size) self->in_count = 0; } } static void Delay_process_ia(Delay *self) { MYFLT val, xind, frac, feed; int i; long ind; MYFLT del = PyFloat_AS_DOUBLE(self->delay); MYFLT *fdb = Stream_getData((Stream *)self->feedback_stream); if (del < self->oneOverSr) del = self->oneOverSr; else if (del > self->maxdelay) del = self->maxdelay; MYFLT sampdel = del * self->sr; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac; self->data[i] = val; feed = fdb[i]; if (feed < 0) feed = 0; else if (feed > 1) feed = 1; self->buffer[self->in_count] = in[i] + (val * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[self->in_count]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void Delay_process_aa(Delay *self) { MYFLT val, xind, frac, sampdel, feed, del; int i; long ind; MYFLT *delobj = Stream_getData((Stream *)self->delay_stream); MYFLT *fdb = Stream_getData((Stream *)self->feedback_stream); MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { del = delobj[i]; if (del < self->oneOverSr) del = self->oneOverSr; else if (del > self->maxdelay) del = self->maxdelay; sampdel = del * self->sr; xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac; self->data[i] = val; feed = fdb[i]; if (feed < 0) feed = 0; else if (feed > 1) feed = 1; self->buffer[self->in_count] = in[i] + (val * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[self->in_count]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void Delay_postprocessing_ii(Delay *self) { POST_PROCESSING_II }; static void Delay_postprocessing_ai(Delay *self) { POST_PROCESSING_AI }; static void Delay_postprocessing_ia(Delay *self) { POST_PROCESSING_IA }; static void Delay_postprocessing_aa(Delay *self) { POST_PROCESSING_AA }; static void Delay_postprocessing_ireva(Delay *self) { POST_PROCESSING_IREVA }; static void Delay_postprocessing_areva(Delay *self) { POST_PROCESSING_AREVA }; static void Delay_postprocessing_revai(Delay *self) { POST_PROCESSING_REVAI }; static void Delay_postprocessing_revaa(Delay *self) { POST_PROCESSING_REVAA }; static void Delay_postprocessing_revareva(Delay *self) { POST_PROCESSING_REVAREVA }; static void Delay_setProcMode(Delay *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Delay_process_ii; break; case 1: self->proc_func_ptr = Delay_process_ai; break; case 10: self->proc_func_ptr = Delay_process_ia; break; case 11: self->proc_func_ptr = Delay_process_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Delay_postprocessing_ii; break; case 1: self->muladd_func_ptr = Delay_postprocessing_ai; break; case 2: self->muladd_func_ptr = Delay_postprocessing_revai; break; case 10: self->muladd_func_ptr = Delay_postprocessing_ia; break; case 11: self->muladd_func_ptr = Delay_postprocessing_aa; break; case 12: self->muladd_func_ptr = Delay_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Delay_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Delay_postprocessing_areva; break; case 22: self->muladd_func_ptr = Delay_postprocessing_revareva; break; } } static void Delay_compute_next_data_frame(Delay *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Delay_traverse(Delay *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->delay); Py_VISIT(self->delay_stream); Py_VISIT(self->feedback); Py_VISIT(self->feedback_stream); return 0; } static int Delay_clear(Delay *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->delay); Py_CLEAR(self->delay_stream); Py_CLEAR(self->feedback); Py_CLEAR(self->feedback_stream); return 0; } static void Delay_dealloc(Delay* self) { pyo_DEALLOC free(self->buffer); Delay_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Delay_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *delaytmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL; Delay *self; self = (Delay *)type->tp_alloc(type, 0); self->delay = PyFloat_FromDouble(0.25); self->feedback = PyFloat_FromDouble(0); self->maxdelay = 1; self->in_count = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON self->oneOverSr = 1.0 / self->sr; Stream_setFunctionPtr(self->stream, Delay_compute_next_data_frame); self->mode_func_ptr = Delay_setProcMode; static char *kwlist[] = {"input", "delay", "feedback", "maxdelay", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOFOO, kwlist, &inputtmp, &delaytmp, &feedbacktmp, &self->maxdelay, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (delaytmp) { PyObject_CallMethod((PyObject *)self, "setDelay", "O", delaytmp); } if (feedbacktmp) { PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->size = (long)(self->maxdelay * self->sr + 0.5); self->buffer = (MYFLT *)realloc(self->buffer, (self->size+1) * sizeof(MYFLT)); for (i=0; i<(self->size+1); i++) { self->buffer[i] = 0.; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Delay_getServer(Delay* self) { GET_SERVER }; static PyObject * Delay_getStream(Delay* self) { GET_STREAM }; static PyObject * Delay_setMul(Delay *self, PyObject *arg) { SET_MUL }; static PyObject * Delay_setAdd(Delay *self, PyObject *arg) { SET_ADD }; static PyObject * Delay_setSub(Delay *self, PyObject *arg) { SET_SUB }; static PyObject * Delay_setDiv(Delay *self, PyObject *arg) { SET_DIV }; static PyObject * Delay_play(Delay *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Delay_out(Delay *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Delay_stop(Delay *self) { STOP }; static PyObject * Delay_multiply(Delay *self, PyObject *arg) { MULTIPLY }; static PyObject * Delay_inplace_multiply(Delay *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Delay_add(Delay *self, PyObject *arg) { ADD }; static PyObject * Delay_inplace_add(Delay *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Delay_sub(Delay *self, PyObject *arg) { SUB }; static PyObject * Delay_inplace_sub(Delay *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Delay_div(Delay *self, PyObject *arg) { DIV }; static PyObject * Delay_inplace_div(Delay *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Delay_setDelay(Delay *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->delay); if (isNumber == 1) { self->delay = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->delay = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->delay, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->delay_stream); self->delay_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Delay_setFeedback(Delay *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->feedback); if (isNumber == 1) { self->feedback = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->feedback = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->feedback_stream); self->feedback_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Delay_reset(Delay *self) { int i; for (i=0; i<(self->size+1); i++) { self->buffer[i] = 0.; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Delay_members[] = { {"server", T_OBJECT_EX, offsetof(Delay, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Delay, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Delay, input), 0, "Input sound object."}, {"delay", T_OBJECT_EX, offsetof(Delay, delay), 0, "Delay time in seconds."}, {"feedback", T_OBJECT_EX, offsetof(Delay, feedback), 0, "Feedback value."}, {"mul", T_OBJECT_EX, offsetof(Delay, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Delay, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Delay_methods[] = { {"getServer", (PyCFunction)Delay_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Delay_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Delay_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Delay_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Delay_stop, METH_NOARGS, "Stops computing."}, {"setDelay", (PyCFunction)Delay_setDelay, METH_O, "Sets delay time in seconds."}, {"setFeedback", (PyCFunction)Delay_setFeedback, METH_O, "Sets feedback value between 0 -> 1."}, {"reset", (PyCFunction)Delay_reset, METH_NOARGS, "Resets the memory buffer to zeros."}, {"setMul", (PyCFunction)Delay_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Delay_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Delay_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Delay_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Delay_as_number = { (binaryfunc)Delay_add, /*nb_add*/ (binaryfunc)Delay_sub, /*nb_subtract*/ (binaryfunc)Delay_multiply, /*nb_multiply*/ (binaryfunc)Delay_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Delay_inplace_add, /*inplace_add*/ (binaryfunc)Delay_inplace_sub, /*inplace_subtract*/ (binaryfunc)Delay_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Delay_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject DelayType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Delay_base", /*tp_name*/ sizeof(Delay), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Delay_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Delay_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Delay objects. Delay signal by x samples.", /* tp_doc */ (traverseproc)Delay_traverse, /* tp_traverse */ (inquiry)Delay_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Delay_methods, /* tp_methods */ Delay_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Delay_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *delay; Stream *delay_stream; MYFLT maxdelay; long size; long in_count; int modebuffer[3]; MYFLT *buffer; // samples memory } SDelay; static void SDelay_process_i(SDelay *self) { int i; long ind; MYFLT del = PyFloat_AS_DOUBLE(self->delay); if (del < 0.) del = 0.; else if (del > self->maxdelay) del = self->maxdelay; long sampdel = (long)(del * self->sr); MYFLT *in = Stream_getData((Stream *)self->input_stream); if (sampdel == 0) { for (i=0; ibufsize; i++) { self->data[i] = self->buffer[self->in_count] = in[i]; self->in_count++; if (self->in_count >= self->size) self->in_count = 0; } } else { for (i=0; ibufsize; i++) { ind = self->in_count - sampdel; if (ind < 0) ind += self->size; self->data[i] = self->buffer[ind]; self->buffer[self->in_count] = in[i]; self->in_count++; if (self->in_count >= self->size) self->in_count = 0; } } } static void SDelay_process_a(SDelay *self) { MYFLT del; int i; long ind, sampdel; MYFLT *delobj = Stream_getData((Stream *)self->delay_stream); MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { del = delobj[i]; if (del < 0.) del = 0.; else if (del > self->maxdelay) del = self->maxdelay; sampdel = (long)(del * self->sr); if (sampdel == 0) { self->data[i] = self->buffer[self->in_count] = in[i]; } else { ind = self->in_count - sampdel; if (ind < 0) ind += self->size; self->data[i] = self->buffer[ind]; } self->buffer[self->in_count++] = in[i]; if (self->in_count >= self->size) self->in_count = 0; } } static void SDelay_postprocessing_ii(SDelay *self) { POST_PROCESSING_II }; static void SDelay_postprocessing_ai(SDelay *self) { POST_PROCESSING_AI }; static void SDelay_postprocessing_ia(SDelay *self) { POST_PROCESSING_IA }; static void SDelay_postprocessing_aa(SDelay *self) { POST_PROCESSING_AA }; static void SDelay_postprocessing_ireva(SDelay *self) { POST_PROCESSING_IREVA }; static void SDelay_postprocessing_areva(SDelay *self) { POST_PROCESSING_AREVA }; static void SDelay_postprocessing_revai(SDelay *self) { POST_PROCESSING_REVAI }; static void SDelay_postprocessing_revaa(SDelay *self) { POST_PROCESSING_REVAA }; static void SDelay_postprocessing_revareva(SDelay *self) { POST_PROCESSING_REVAREVA }; static void SDelay_setProcMode(SDelay *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = SDelay_process_i; break; case 1: self->proc_func_ptr = SDelay_process_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = SDelay_postprocessing_ii; break; case 1: self->muladd_func_ptr = SDelay_postprocessing_ai; break; case 2: self->muladd_func_ptr = SDelay_postprocessing_revai; break; case 10: self->muladd_func_ptr = SDelay_postprocessing_ia; break; case 11: self->muladd_func_ptr = SDelay_postprocessing_aa; break; case 12: self->muladd_func_ptr = SDelay_postprocessing_revaa; break; case 20: self->muladd_func_ptr = SDelay_postprocessing_ireva; break; case 21: self->muladd_func_ptr = SDelay_postprocessing_areva; break; case 22: self->muladd_func_ptr = SDelay_postprocessing_revareva; break; } } static void SDelay_compute_next_data_frame(SDelay *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int SDelay_traverse(SDelay *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->delay); Py_VISIT(self->delay_stream); return 0; } static int SDelay_clear(SDelay *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->delay); Py_CLEAR(self->delay_stream); return 0; } static void SDelay_dealloc(SDelay* self) { pyo_DEALLOC free(self->buffer); SDelay_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SDelay_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *delaytmp=NULL, *multmp=NULL, *addtmp=NULL; SDelay *self; self = (SDelay *)type->tp_alloc(type, 0); self->delay = PyFloat_FromDouble(0.25); self->maxdelay = 1; self->in_count = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, SDelay_compute_next_data_frame); self->mode_func_ptr = SDelay_setProcMode; static char *kwlist[] = {"input", "delay", "maxdelay", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OFOO, kwlist, &inputtmp, &delaytmp, &self->maxdelay, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (delaytmp) { PyObject_CallMethod((PyObject *)self, "setDelay", "O", delaytmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->size = (long)(self->maxdelay * self->sr + 0.5); self->buffer = (MYFLT *)realloc(self->buffer, (self->size+1) * sizeof(MYFLT)); for (i=0; i<(self->size+1); i++) { self->buffer[i] = 0.; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * SDelay_getServer(SDelay* self) { GET_SERVER }; static PyObject * SDelay_getStream(SDelay* self) { GET_STREAM }; static PyObject * SDelay_setMul(SDelay *self, PyObject *arg) { SET_MUL }; static PyObject * SDelay_setAdd(SDelay *self, PyObject *arg) { SET_ADD }; static PyObject * SDelay_setSub(SDelay *self, PyObject *arg) { SET_SUB }; static PyObject * SDelay_setDiv(SDelay *self, PyObject *arg) { SET_DIV }; static PyObject * SDelay_play(SDelay *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SDelay_out(SDelay *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * SDelay_stop(SDelay *self) { STOP }; static PyObject * SDelay_multiply(SDelay *self, PyObject *arg) { MULTIPLY }; static PyObject * SDelay_inplace_multiply(SDelay *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * SDelay_add(SDelay *self, PyObject *arg) { ADD }; static PyObject * SDelay_inplace_add(SDelay *self, PyObject *arg) { INPLACE_ADD }; static PyObject * SDelay_sub(SDelay *self, PyObject *arg) { SUB }; static PyObject * SDelay_inplace_sub(SDelay *self, PyObject *arg) { INPLACE_SUB }; static PyObject * SDelay_div(SDelay *self, PyObject *arg) { DIV }; static PyObject * SDelay_inplace_div(SDelay *self, PyObject *arg) { INPLACE_DIV }; static PyObject * SDelay_setDelay(SDelay *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->delay); if (isNumber == 1) { self->delay = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->delay = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->delay, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->delay_stream); self->delay_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SDelay_reset(SDelay *self) { int i; for (i=0; i<(self->size+1); i++) { self->buffer[i] = 0.; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef SDelay_members[] = { {"server", T_OBJECT_EX, offsetof(SDelay, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SDelay, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(SDelay, input), 0, "Input sound object."}, {"delay", T_OBJECT_EX, offsetof(SDelay, delay), 0, "Delay time in seconds."}, {"mul", T_OBJECT_EX, offsetof(SDelay, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(SDelay, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef SDelay_methods[] = { {"getServer", (PyCFunction)SDelay_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SDelay_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SDelay_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)SDelay_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)SDelay_stop, METH_NOARGS, "Stops computing."}, {"setDelay", (PyCFunction)SDelay_setDelay, METH_O, "Sets delay time in seconds."}, {"reset", (PyCFunction)SDelay_reset, METH_NOARGS, "Resets the memory buffer to zeros."}, {"setMul", (PyCFunction)SDelay_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)SDelay_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)SDelay_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)SDelay_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods SDelay_as_number = { (binaryfunc)SDelay_add, /*nb_add*/ (binaryfunc)SDelay_sub, /*nb_subtract*/ (binaryfunc)SDelay_multiply, /*nb_multiply*/ (binaryfunc)SDelay_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)SDelay_inplace_add, /*inplace_add*/ (binaryfunc)SDelay_inplace_sub, /*inplace_subtract*/ (binaryfunc)SDelay_inplace_multiply, /*inplace_multiply*/ (binaryfunc)SDelay_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SDelayType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SDelay_base", /*tp_name*/ sizeof(SDelay), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SDelay_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &SDelay_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SDelay objects. Simple Delay with no interpolation and no feedback.", /* tp_doc */ (traverseproc)SDelay_traverse, /* tp_traverse */ (inquiry)SDelay_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SDelay_methods, /* tp_methods */ SDelay_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SDelay_new, /* tp_new */ }; /*********************/ /***** Waveguide *****/ /*********************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *dur; Stream *dur_stream; MYFLT minfreq; MYFLT lastFreq; MYFLT lastSampDel; MYFLT lastDur; MYFLT lastFeed; long size; int in_count; MYFLT nyquist; int modebuffer[4]; MYFLT lpsamp; // lowpass sample memory MYFLT coeffs[5]; // lagrange coefficients MYFLT lagrange[4]; // lagrange samples memories MYFLT xn1; // dc block input delay MYFLT yn1; // dc block output delay MYFLT *buffer; // samples memory } Waveguide; static void Waveguide_process_ii(Waveguide *self) { MYFLT val, x, y, sampdel, frac, feed, tmp; int i, ind, isamp; MYFLT fr = PyFloat_AS_DOUBLE(self->freq); MYFLT dur = PyFloat_AS_DOUBLE(self->dur); MYFLT *in = Stream_getData((Stream *)self->input_stream); /* Check boundaries */ if (fr < self->minfreq) fr = self->minfreq; else if (fr >= self->nyquist) fr = self->nyquist; if (dur <= 0) dur = 0.1; sampdel = self->lastSampDel; feed = self->lastFeed; /* lagrange coeffs and feedback coeff */ if (fr != self->lastFreq) { self->lastFreq = fr; sampdel = self->sr / fr - 0.5; self->lastSampDel = sampdel; isamp = (int)sampdel; frac = sampdel - isamp; self->coeffs[0] = (frac-1)*(frac-2)*(frac-3)*(frac-4)/24.0; self->coeffs[1] = -frac*(frac-2)*(frac-3)*(frac-4)/6.0; self->coeffs[2] = frac*(frac-1)*(frac-3)*(frac-4)/4.0; self->coeffs[3] = -frac*(frac-1)*(frac-2)*(frac-4)/6.0; self->coeffs[4] = frac*(frac-1)*(frac-2)*(frac-3)/24.0; self->lastDur = dur; feed = MYPOW(100, -1.0/(fr*dur)); self->lastFeed = feed; } else if (dur != self->lastDur) { self->lastDur = dur; feed = MYPOW(100, -1.0/(fr*dur)); self->lastFeed = feed; } /* pick a new value in th delay line */ isamp = (int)sampdel; for (i=0; ibufsize; i++) { ind = self->in_count - isamp; if (ind < 0) ind += self->size; val = self->buffer[ind]; /* simple lowpass filtering */ tmp = val; val = (val + self->lpsamp) * 0.5; self->lpsamp = tmp; /* lagrange filtering */ x = (val*self->coeffs[0])+(self->lagrange[0]*self->coeffs[1])+(self->lagrange[1]*self->coeffs[2])+ (self->lagrange[2]*self->coeffs[3])+(self->lagrange[3]*self->coeffs[4]); self->lagrange[3] = self->lagrange[2]; self->lagrange[2] = self->lagrange[1]; self->lagrange[1] = self->lagrange[0]; self->lagrange[0] = val; /* DC filtering */ y = x - self->xn1 + 0.995 * self->yn1; self->xn1 = x; self->yn1 = y; self->data[i] = y; /* write current value in the delay line */ self->buffer[self->in_count] = in[i] + (x * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void Waveguide_process_ai(Waveguide *self) { MYFLT val, x, y, sampdel, frac, feed, freq, tmp; int i, ind, isamp; MYFLT *fr =Stream_getData((Stream *)self->freq_stream); MYFLT dur = PyFloat_AS_DOUBLE(self->dur); MYFLT *in = Stream_getData((Stream *)self->input_stream); /* Check dur boundary */ if (dur <= 0) dur = 0.1; for (i=0; ibufsize; i++) { freq = fr[i]; /* Check frequency boundary */ if (freq < self->minfreq) freq = self->minfreq; else if (freq >= self->nyquist) freq = self->nyquist; sampdel = self->lastSampDel; feed = self->lastFeed; /* lagrange coeffs and feedback coeff */ if (freq != self->lastFreq) { self->lastFreq = freq; sampdel = self->sr / freq - 0.5; self->lastSampDel = sampdel; isamp = (int)sampdel; frac = sampdel - isamp; self->coeffs[0] = (frac-1)*(frac-2)*(frac-3)*(frac-4)/24.0; self->coeffs[1] = -frac*(frac-2)*(frac-3)*(frac-4)/6.0; self->coeffs[2] = frac*(frac-1)*(frac-3)*(frac-4)/4.0; self->coeffs[3] = -frac*(frac-1)*(frac-2)*(frac-4)/6.0; self->coeffs[4] = frac*(frac-1)*(frac-2)*(frac-3)/24.0; self->lastDur = dur; feed = MYPOW(100, -1.0/(freq*dur)); self->lastFeed = feed; } else if (dur != self->lastDur) { self->lastDur = dur; feed = MYPOW(100, -1.0/(freq*dur)); self->lastFeed = feed; } /* pick a new value in th delay line */ isamp = (int)sampdel; ind = self->in_count - isamp; if (ind < 0) ind += self->size; val = self->buffer[ind]; /* simple lowpass filtering */ tmp = val; val = (val + self->lpsamp) * 0.5; self->lpsamp = tmp; /* lagrange filtering */ x = (val*self->coeffs[0])+(self->lagrange[0]*self->coeffs[1])+(self->lagrange[1]*self->coeffs[2])+ (self->lagrange[2]*self->coeffs[3])+(self->lagrange[3]*self->coeffs[4]); self->lagrange[3] = self->lagrange[2]; self->lagrange[2] = self->lagrange[1]; self->lagrange[1] = self->lagrange[0]; self->lagrange[0] = val; /* DC filtering */ y = x - self->xn1 + 0.995 * self->yn1; self->xn1 = x; self->yn1 = y; self->data[i] = y; /* write current value in the delay line */ self->buffer[self->in_count] = in[i] + (x * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void Waveguide_process_ia(Waveguide *self) { MYFLT val, x, y, sampdel, frac, feed, dur, tmp; int i, ind, isamp; MYFLT fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *du = Stream_getData((Stream *)self->dur_stream); MYFLT *in = Stream_getData((Stream *)self->input_stream); /* Check boundaries */ if (fr < self->minfreq) fr = self->minfreq; else if (fr >= self->nyquist) fr = self->nyquist; sampdel = self->lastSampDel; /* lagrange coeffs and feedback coeff */ if (fr != self->lastFreq) { self->lastFreq = fr; sampdel = self->sr / fr - 0.5; self->lastSampDel = sampdel; isamp = (int)sampdel; frac = sampdel - isamp; self->coeffs[0] = (frac-1)*(frac-2)*(frac-3)*(frac-4)/24.0; self->coeffs[1] = -frac*(frac-2)*(frac-3)*(frac-4)/6.0; self->coeffs[2] = frac*(frac-1)*(frac-3)*(frac-4)/4.0; self->coeffs[3] = -frac*(frac-1)*(frac-2)*(frac-4)/6.0; self->coeffs[4] = frac*(frac-1)*(frac-2)*(frac-3)/24.0; } /* pick a new value in th delay line */ isamp = (int)sampdel; for (i=0; ibufsize; i++) { feed = self->lastFeed; dur = du[i]; if (dur <= 0) dur = 0.1; if (dur != self->lastDur) { self->lastDur = dur; feed = MYPOW(100, -1.0/(fr*dur)); self->lastFeed = feed; } ind = self->in_count - isamp; if (ind < 0) ind += self->size; val = self->buffer[ind]; /* simple lowpass filtering */ tmp = val; val = (val + self->lpsamp) * 0.5; self->lpsamp = tmp; /* lagrange filtering */ x = (val*self->coeffs[0])+(self->lagrange[0]*self->coeffs[1])+(self->lagrange[1]*self->coeffs[2])+ (self->lagrange[2]*self->coeffs[3])+(self->lagrange[3]*self->coeffs[4]); self->lagrange[3] = self->lagrange[2]; self->lagrange[2] = self->lagrange[1]; self->lagrange[1] = self->lagrange[0]; self->lagrange[0] = val; /* DC filtering */ y = x - self->xn1 + 0.995 * self->yn1; self->xn1 = x; self->yn1 = y; self->data[i] = y; /* write current value in the delay line */ self->buffer[self->in_count] = in[i] + (x * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void Waveguide_process_aa(Waveguide *self) { MYFLT val, x, y, sampdel, frac, feed, freq, dur, tmp; int i, ind, isamp; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *du = Stream_getData((Stream *)self->dur_stream); MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { freq = fr[i]; dur = du[i]; /* Check boundaries */ if (freq < self->minfreq) freq = self->minfreq; else if (freq >= self->nyquist) freq = self->nyquist; if (dur <= 0) dur = 0.1; sampdel = self->lastSampDel; feed = self->lastFeed; /* lagrange coeffs and feedback coeff */ if (freq != self->lastFreq) { self->lastFreq = freq; sampdel = self->sr / freq - 0.5; self->lastSampDel = sampdel; isamp = (int)sampdel; frac = sampdel - isamp; self->coeffs[0] = (frac-1)*(frac-2)*(frac-3)*(frac-4)/24.0; self->coeffs[1] = -frac*(frac-2)*(frac-3)*(frac-4)/6.0; self->coeffs[2] = frac*(frac-1)*(frac-3)*(frac-4)/4.0; self->coeffs[3] = -frac*(frac-1)*(frac-2)*(frac-4)/6.0; self->coeffs[4] = frac*(frac-1)*(frac-2)*(frac-3)/24.0; self->lastDur = dur; feed = MYPOW(100, -1.0/(freq*dur)); self->lastFeed = feed; } else if (dur != self->lastDur) { self->lastDur = dur; feed = MYPOW(100, -1.0/(freq*dur)); self->lastFeed = feed; } /* pick a new value in th delay line */ isamp = (int)sampdel; ind = self->in_count - isamp; if (ind < 0) ind += self->size; val = self->buffer[ind]; /* simple lowpass filtering */ tmp = val; val = (val + self->lpsamp) * 0.5; self->lpsamp = tmp; /* lagrange filtering */ x = (val*self->coeffs[0])+(self->lagrange[0]*self->coeffs[1])+(self->lagrange[1]*self->coeffs[2])+ (self->lagrange[2]*self->coeffs[3])+(self->lagrange[3]*self->coeffs[4]); self->lagrange[3] = self->lagrange[2]; self->lagrange[2] = self->lagrange[1]; self->lagrange[1] = self->lagrange[0]; self->lagrange[0] = val; /* DC filtering */ y = x - self->xn1 + 0.995 * self->yn1; self->xn1 = x; self->yn1 = y; self->data[i] = y; /* write current value in the delay line */ self->buffer[self->in_count] = in[i] + (x * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void Waveguide_postprocessing_ii(Waveguide *self) { POST_PROCESSING_II }; static void Waveguide_postprocessing_ai(Waveguide *self) { POST_PROCESSING_AI }; static void Waveguide_postprocessing_ia(Waveguide *self) { POST_PROCESSING_IA }; static void Waveguide_postprocessing_aa(Waveguide *self) { POST_PROCESSING_AA }; static void Waveguide_postprocessing_ireva(Waveguide *self) { POST_PROCESSING_IREVA }; static void Waveguide_postprocessing_areva(Waveguide *self) { POST_PROCESSING_AREVA }; static void Waveguide_postprocessing_revai(Waveguide *self) { POST_PROCESSING_REVAI }; static void Waveguide_postprocessing_revaa(Waveguide *self) { POST_PROCESSING_REVAA }; static void Waveguide_postprocessing_revareva(Waveguide *self) { POST_PROCESSING_REVAREVA }; static void Waveguide_setProcMode(Waveguide *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Waveguide_process_ii; break; case 1: self->proc_func_ptr = Waveguide_process_ai; break; case 10: self->proc_func_ptr = Waveguide_process_ia; break; case 11: self->proc_func_ptr = Waveguide_process_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Waveguide_postprocessing_ii; break; case 1: self->muladd_func_ptr = Waveguide_postprocessing_ai; break; case 2: self->muladd_func_ptr = Waveguide_postprocessing_revai; break; case 10: self->muladd_func_ptr = Waveguide_postprocessing_ia; break; case 11: self->muladd_func_ptr = Waveguide_postprocessing_aa; break; case 12: self->muladd_func_ptr = Waveguide_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Waveguide_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Waveguide_postprocessing_areva; break; case 22: self->muladd_func_ptr = Waveguide_postprocessing_revareva; break; } } static void Waveguide_compute_next_data_frame(Waveguide *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Waveguide_traverse(Waveguide *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->dur); Py_VISIT(self->dur_stream); return 0; } static int Waveguide_clear(Waveguide *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->dur); Py_CLEAR(self->dur_stream); return 0; } static void Waveguide_dealloc(Waveguide* self) { pyo_DEALLOC free(self->buffer); Waveguide_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Waveguide_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *durtmp=NULL, *multmp=NULL, *addtmp=NULL; Waveguide *self; self = (Waveguide *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(100); self->dur = PyFloat_FromDouble(0.99); self->minfreq = 20; self->lastFreq = -1.0; self->lastSampDel = -1.0; self->lastDur = -1.0; self->lastFeed = 0.0; self->in_count = 0; self->lpsamp = 0.0; for(i=0; i<4; i++) { self->lagrange[i] = 0.0; } self->xn1 = 0.0; self->yn1 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.45; Stream_setFunctionPtr(self->stream, Waveguide_compute_next_data_frame); self->mode_func_ptr = Waveguide_setProcMode; static char *kwlist[] = {"input", "freq", "dur", "minfreq", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOFOO, kwlist, &inputtmp, &freqtmp, &durtmp, &self->minfreq, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (durtmp) { PyObject_CallMethod((PyObject *)self, "setDur", "O", durtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->size = (long)(1.0 / self->minfreq * self->sr + 0.5); self->buffer = (MYFLT *)realloc(self->buffer, (self->size+1) * sizeof(MYFLT)); for (i=0; i<(self->size+1); i++) { self->buffer[i] = 0.; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Waveguide_getServer(Waveguide* self) { GET_SERVER }; static PyObject * Waveguide_getStream(Waveguide* self) { GET_STREAM }; static PyObject * Waveguide_setMul(Waveguide *self, PyObject *arg) { SET_MUL }; static PyObject * Waveguide_setAdd(Waveguide *self, PyObject *arg) { SET_ADD }; static PyObject * Waveguide_setSub(Waveguide *self, PyObject *arg) { SET_SUB }; static PyObject * Waveguide_setDiv(Waveguide *self, PyObject *arg) { SET_DIV }; static PyObject * Waveguide_play(Waveguide *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Waveguide_out(Waveguide *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Waveguide_stop(Waveguide *self) { STOP }; static PyObject * Waveguide_multiply(Waveguide *self, PyObject *arg) { MULTIPLY }; static PyObject * Waveguide_inplace_multiply(Waveguide *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Waveguide_add(Waveguide *self, PyObject *arg) { ADD }; static PyObject * Waveguide_inplace_add(Waveguide *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Waveguide_sub(Waveguide *self, PyObject *arg) { SUB }; static PyObject * Waveguide_inplace_sub(Waveguide *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Waveguide_div(Waveguide *self, PyObject *arg) { DIV }; static PyObject * Waveguide_inplace_div(Waveguide *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Waveguide_setFreq(Waveguide *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Waveguide_setDur(Waveguide *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->dur); if (isNumber == 1) { self->dur = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->dur = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->dur, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->dur_stream); self->dur_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Waveguide_members[] = { {"server", T_OBJECT_EX, offsetof(Waveguide, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Waveguide, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Waveguide, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(Waveguide, freq), 0, "Waveguide time in seconds."}, {"dur", T_OBJECT_EX, offsetof(Waveguide, dur), 0, "Feedback value."}, {"mul", T_OBJECT_EX, offsetof(Waveguide, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Waveguide, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Waveguide_methods[] = { {"getServer", (PyCFunction)Waveguide_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Waveguide_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Waveguide_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Waveguide_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Waveguide_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Waveguide_setFreq, METH_O, "Sets freq time in seconds."}, {"setDur", (PyCFunction)Waveguide_setDur, METH_O, "Sets dur value between 0 -> 1."}, {"setMul", (PyCFunction)Waveguide_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Waveguide_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Waveguide_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Waveguide_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Waveguide_as_number = { (binaryfunc)Waveguide_add, /*nb_add*/ (binaryfunc)Waveguide_sub, /*nb_subtract*/ (binaryfunc)Waveguide_multiply, /*nb_multiply*/ (binaryfunc)Waveguide_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Waveguide_inplace_add, /*inplace_add*/ (binaryfunc)Waveguide_inplace_sub, /*inplace_subtract*/ (binaryfunc)Waveguide_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Waveguide_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject WaveguideType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Waveguide_base", /*tp_name*/ sizeof(Waveguide), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Waveguide_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Waveguide_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Waveguide objects. Waveguide signal by x samples.", /* tp_doc */ (traverseproc)Waveguide_traverse, /* tp_traverse */ (inquiry)Waveguide_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Waveguide_methods, /* tp_methods */ Waveguide_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Waveguide_new, /* tp_new */ }; /*********************/ /***** AllpassWG *****/ /*********************/ static const MYFLT alp_chorus_factor[3] = {1.0, 0.9981, 0.9957}; static const MYFLT alp_feedback = 0.3; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *feed; Stream *feed_stream; PyObject *detune; Stream *detune_stream; MYFLT minfreq; MYFLT nyquist; long size; int alpsize; int in_count; int alp_in_count[3]; int modebuffer[5]; MYFLT *alpbuffer[3]; // allpass samples memories MYFLT xn1; // dc block input delay MYFLT yn1; // dc block output delay MYFLT *buffer; // samples memory } AllpassWG; static void AllpassWG_process_iii(AllpassWG *self) { int i, j; long ind; MYFLT val, y, xind, sampdel, frac, freqshift, alpsampdel, alpsampdelin, alpdetune; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); MYFLT feed = PyFloat_AS_DOUBLE(self->feed); MYFLT detune = PyFloat_AS_DOUBLE(self->detune); /* Check boundaries */ if (fr < self->minfreq) fr = self->minfreq; else if (fr >= self->nyquist) fr = self->nyquist; feed *= 0.4525; if (feed > 0.4525) feed = 0.4525; else if (feed < 0) feed = 0; freqshift = detune * 0.5 + 1.; detune = detune * 0.95 + 0.05; if (detune < 0.05) detune = 0.05; else if (detune > 1.0) detune = 1.0; sampdel = self->sr / (fr * freqshift); alpdetune = detune * self->alpsize; for (i=0; ibufsize; i++) { /* pick a new value in the delay line */ xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; /* all-pass filter */ for (j=0; j<3; j++) { xind = self->alp_in_count[j] - (alpdetune * alp_chorus_factor[j]); if (xind < 0) xind += self->alpsize; ind = (long)xind; frac = xind - ind; alpsampdel = self->alpbuffer[j][ind] + (self->alpbuffer[j][ind+1] - self->alpbuffer[j][ind]) * frac; alpsampdelin = val + ((val - alpsampdel) * alp_feedback); val = alpsampdelin * alp_feedback + alpsampdel; /* write current allpass value in the allpass delay line */ self->alpbuffer[j][self->alp_in_count[j]] = alpsampdelin; if (self->alp_in_count[j] == 0) self->alpbuffer[j][self->alpsize] = alpsampdelin; self->alp_in_count[j]++; if (self->alp_in_count[j] == self->alpsize) self->alp_in_count[j] = 0; } /* DC filtering and output */ y = val - self->xn1 + 0.995 * self->yn1; self->xn1 = val; self->data[i] = self->yn1 = y; /* write current value in the delay line */ self->buffer[self->in_count] = in[i] + val * feed; if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void AllpassWG_process_aii(AllpassWG *self) { int i, j; long ind; MYFLT val, y, xind, sampdel, frac, fr, freqshift, alpsampdel, alpsampdelin, alpdetune; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT feed = PyFloat_AS_DOUBLE(self->feed); MYFLT detune = PyFloat_AS_DOUBLE(self->detune); feed *= 0.4525; if (feed > 0.4525) feed = 0.4525; else if (feed < 0) feed = 0; freqshift = detune * 0.5 + 1.; detune = detune * 0.95 + 0.05; if (detune < 0.05) detune = 0.05; else if (detune > 1.0) detune = 1.0; alpdetune = detune * self->alpsize; for (i=0; ibufsize; i++) { fr = freq[i]; if (fr < self->minfreq) fr = self->minfreq; else if (fr >= self->nyquist) fr = self->nyquist; /* pick a new value in the delay line */ sampdel = self->sr / (fr * freqshift); xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; /* all-pass filter */ for (j=0; j<3; j++) { xind = self->alp_in_count[j] - (alpdetune * alp_chorus_factor[j]); if (xind < 0) xind += self->alpsize; ind = (long)xind; frac = xind - ind; alpsampdel = self->alpbuffer[j][ind] + (self->alpbuffer[j][ind+1] - self->alpbuffer[j][ind]) * frac; alpsampdelin = val + ((val - alpsampdel) * alp_feedback); val = alpsampdelin * alp_feedback + alpsampdel; /* write current allpass value in the allpass delay line */ self->alpbuffer[j][self->alp_in_count[j]] = alpsampdelin; if (self->alp_in_count[j] == 0) self->alpbuffer[j][self->alpsize] = alpsampdelin; self->alp_in_count[j]++; if (self->alp_in_count[j] == self->alpsize) self->alp_in_count[j] = 0; } /* DC filtering and output */ y = val - self->xn1 + 0.995 * self->yn1; self->xn1 = val; self->data[i] = self->yn1 = y; /* write current value in the delay line */ self->buffer[self->in_count] = in[i] + val * feed; if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void AllpassWG_process_iai(AllpassWG *self) { int i, j; long ind; MYFLT val, y, xind, sampdel, frac, feed, freqshift, alpsampdel, alpsampdelin, alpdetune; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *fdb = Stream_getData((Stream *)self->feed_stream); MYFLT detune = PyFloat_AS_DOUBLE(self->detune); /* Check boundaries */ if (fr < self->minfreq) fr = self->minfreq; else if (fr >= self->nyquist) fr = self->nyquist; freqshift = detune * 0.5 + 1.; detune = detune * 0.95 + 0.05; if (detune < 0.05) detune = 0.05; else if (detune > 1.0) detune = 1.0; sampdel = self->sr / (fr * freqshift); alpdetune = detune * self->alpsize; for (i=0; ibufsize; i++) { feed = fdb[i] * 0.4525; if (feed > 0.4525) feed = 0.4525; else if (feed < 0) feed = 0; /* pick a new value in the delay line */ xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; /* all-pass filter */ for (j=0; j<3; j++) { xind = self->alp_in_count[j] - (alpdetune * alp_chorus_factor[j]); if (xind < 0) xind += self->alpsize; ind = (long)xind; frac = xind - ind; alpsampdel = self->alpbuffer[j][ind] + (self->alpbuffer[j][ind+1] - self->alpbuffer[j][ind]) * frac; alpsampdelin = val + ((val - alpsampdel) * alp_feedback); val = alpsampdelin * alp_feedback + alpsampdel; /* write current allpass value in the allpass delay line */ self->alpbuffer[j][self->alp_in_count[j]] = alpsampdelin; if (self->alp_in_count[j] == 0) self->alpbuffer[j][self->alpsize] = alpsampdelin; self->alp_in_count[j]++; if (self->alp_in_count[j] == self->alpsize) self->alp_in_count[j] = 0; } /* DC filtering and output */ y = val - self->xn1 + 0.995 * self->yn1; self->xn1 = val; self->data[i] = self->yn1 = y; /* write current value in the delay line */ self->buffer[self->in_count] = in[i] + val * feed; if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void AllpassWG_process_aai(AllpassWG *self) { int i, j; long ind; MYFLT val, y, xind, sampdel, frac, fr, feed, freqshift, alpsampdel, alpsampdelin, alpdetune; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT *fdb = Stream_getData((Stream *)self->feed_stream); MYFLT detune = PyFloat_AS_DOUBLE(self->detune); freqshift = detune * 0.5 + 1.; detune = detune * 0.95 + 0.05; if (detune < 0.05) detune = 0.05; else if (detune > 1.0) detune = 1.0; alpdetune = detune * self->alpsize; for (i=0; ibufsize; i++) { fr = freq[i]; if (fr < self->minfreq) fr = self->minfreq; else if (fr >= self->nyquist) fr = self->nyquist; feed = fdb[i] * 0.4525; if (feed > 0.4525) feed = 0.4525; else if (feed < 0) feed = 0; /* pick a new value in the delay line */ sampdel = self->sr / (fr * freqshift); xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; /* all-pass filter */ for (j=0; j<3; j++) { xind = self->alp_in_count[j] - (alpdetune * alp_chorus_factor[j]); if (xind < 0) xind += self->alpsize; ind = (long)xind; frac = xind - ind; alpsampdel = self->alpbuffer[j][ind] + (self->alpbuffer[j][ind+1] - self->alpbuffer[j][ind]) * frac; alpsampdelin = val + ((val - alpsampdel) * alp_feedback); val = alpsampdelin * alp_feedback + alpsampdel; /* write current allpass value in the allpass delay line */ self->alpbuffer[j][self->alp_in_count[j]] = alpsampdelin; if (self->alp_in_count[j] == 0) self->alpbuffer[j][self->alpsize] = alpsampdelin; self->alp_in_count[j]++; if (self->alp_in_count[j] == self->alpsize) self->alp_in_count[j] = 0; } /* DC filtering and output */ y = val - self->xn1 + 0.995 * self->yn1; self->xn1 = val; self->data[i] = self->yn1 = y; /* write current value in the delay line */ self->buffer[self->in_count] = in[i] + val * feed; if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void AllpassWG_process_iia(AllpassWG *self) { int i, j; long ind; MYFLT val, y, xind, sampdel, frac, detune, freqshift, alpsampdel, alpsampdelin, alpdetune; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); MYFLT feed = PyFloat_AS_DOUBLE(self->feed); MYFLT *det = Stream_getData((Stream *)self->detune_stream); /* Check boundaries */ if (fr < self->minfreq) fr = self->minfreq; else if (fr >= self->nyquist) fr = self->nyquist; feed *= 0.4525; if (feed > 0.4525) feed = 0.4525; else if (feed < 0) feed = 0; for (i=0; ibufsize; i++) { detune = det[i]; freqshift = detune * 0.5 + 1.; detune = detune * 0.95 + 0.05; if (detune < 0.05) detune = 0.05; else if (detune > 1.0) detune = 1.0; /* pick a new value in the delay line */ sampdel = self->sr / (fr * freqshift); xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; /* all-pass filter */ alpdetune = detune * self->alpsize; for (j=0; j<3; j++) { xind = self->alp_in_count[j] - (alpdetune * alp_chorus_factor[j]); if (xind < 0) xind += self->alpsize; ind = (long)xind; frac = xind - ind; alpsampdel = self->alpbuffer[j][ind] + (self->alpbuffer[j][ind+1] - self->alpbuffer[j][ind]) * frac; alpsampdelin = val + ((val - alpsampdel) * alp_feedback); val = alpsampdelin * alp_feedback + alpsampdel; /* write current allpass value in the allpass delay line */ self->alpbuffer[j][self->alp_in_count[j]] = alpsampdelin; if (self->alp_in_count[j] == 0) self->alpbuffer[j][self->alpsize] = alpsampdelin; self->alp_in_count[j]++; if (self->alp_in_count[j] == self->alpsize) self->alp_in_count[j] = 0; } /* DC filtering and output */ y = val - self->xn1 + 0.995 * self->yn1; self->xn1 = val; self->data[i] = self->yn1 = y; /* write current value in the delay line */ self->buffer[self->in_count] = in[i] + val * feed; if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void AllpassWG_process_aia(AllpassWG *self) { int i, j; long ind; MYFLT val, y, xind, sampdel, frac, fr, detune, freqshift, alpsampdel, alpsampdelin, alpdetune; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT feed = PyFloat_AS_DOUBLE(self->feed); MYFLT *det = Stream_getData((Stream *)self->detune_stream); feed *= 0.4525; if (feed > 0.4525) feed = 0.4525; else if (feed < 0) feed = 0; for (i=0; ibufsize; i++) { fr = freq[i]; if (fr < self->minfreq) fr = self->minfreq; else if (fr >= self->nyquist) fr = self->nyquist; detune = det[i]; freqshift = detune * 0.5 + 1.; detune = detune * 0.95 + 0.05; if (detune < 0.05) detune = 0.05; else if (detune > 1.0) detune = 1.0; /* pick a new value in the delay line */ sampdel = self->sr / (fr * freqshift); xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; /* all-pass filter */ alpdetune = detune * self->alpsize; for (j=0; j<3; j++) { xind = self->alp_in_count[j] - (alpdetune * alp_chorus_factor[j]); if (xind < 0) xind += self->alpsize; ind = (long)xind; frac = xind - ind; alpsampdel = self->alpbuffer[j][ind] + (self->alpbuffer[j][ind+1] - self->alpbuffer[j][ind]) * frac; alpsampdelin = val + ((val - alpsampdel) * alp_feedback); val = alpsampdelin * alp_feedback + alpsampdel; /* write current allpass value in the allpass delay line */ self->alpbuffer[j][self->alp_in_count[j]] = alpsampdelin; if (self->alp_in_count[j] == 0) self->alpbuffer[j][self->alpsize] = alpsampdelin; self->alp_in_count[j]++; if (self->alp_in_count[j] == self->alpsize) self->alp_in_count[j] = 0; } /* DC filtering and output */ y = val - self->xn1 + 0.995 * self->yn1; self->xn1 = val; self->data[i] = self->yn1 = y; /* write current value in the delay line */ self->buffer[self->in_count] = in[i] + val * feed; if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void AllpassWG_process_iaa(AllpassWG *self) { int i, j; long ind; MYFLT val, y, xind, sampdel, frac, feed, detune, freqshift, alpsampdel, alpsampdelin, alpdetune; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *fdb = Stream_getData((Stream *)self->feed_stream); MYFLT *det = Stream_getData((Stream *)self->detune_stream); /* Check boundaries */ if (fr < self->minfreq) fr = self->minfreq; else if (fr >= self->nyquist) fr = self->nyquist; for (i=0; ibufsize; i++) { feed = fdb[i] * 0.4525; if (feed > 0.4525) feed = 0.4525; else if (feed < 0) feed = 0; detune = det[i]; freqshift = detune * 0.5 + 1.; detune = detune * 0.95 + 0.05; if (detune < 0.05) detune = 0.05; else if (detune > 1.0) detune = 1.0; /* pick a new value in the delay line */ sampdel = self->sr / (fr * freqshift); xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; /* all-pass filter */ alpdetune = detune * self->alpsize; for (j=0; j<3; j++) { xind = self->alp_in_count[j] - (alpdetune * alp_chorus_factor[j]); if (xind < 0) xind += self->alpsize; ind = (long)xind; frac = xind - ind; alpsampdel = self->alpbuffer[j][ind] + (self->alpbuffer[j][ind+1] - self->alpbuffer[j][ind]) * frac; alpsampdelin = val + ((val - alpsampdel) * alp_feedback); val = alpsampdelin * alp_feedback + alpsampdel; /* write current allpass value in the allpass delay line */ self->alpbuffer[j][self->alp_in_count[j]] = alpsampdelin; if (self->alp_in_count[j] == 0) self->alpbuffer[j][self->alpsize] = alpsampdelin; self->alp_in_count[j]++; if (self->alp_in_count[j] == self->alpsize) self->alp_in_count[j] = 0; } /* DC filtering and output */ y = val - self->xn1 + 0.995 * self->yn1; self->xn1 = val; self->data[i] = self->yn1 = y; /* write current value in the delay line */ self->buffer[self->in_count] = in[i] + val * feed; if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void AllpassWG_process_aaa(AllpassWG *self) { int i, j; long ind; MYFLT val, y, xind, sampdel, frac, fr, feed, detune, freqshift, alpsampdel, alpsampdelin, alpdetune; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT *fdb = Stream_getData((Stream *)self->feed_stream); MYFLT *det = Stream_getData((Stream *)self->detune_stream); for (i=0; ibufsize; i++) { fr = freq[i]; if (fr < self->minfreq) fr = self->minfreq; else if (fr >= self->nyquist) fr = self->nyquist; feed = fdb[i] * 0.4525; if (feed > 0.4525) feed = 0.4525; else if (feed < 0) feed = 0; detune = det[i]; freqshift = detune * 0.5 + 1.; detune = detune * 0.95 + 0.05; if (detune < 0.05) detune = 0.05; else if (detune > 1.0) detune = 1.0; /* pick a new value in the delay line */ sampdel = self->sr / (fr * freqshift); xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; /* all-pass filter */ alpdetune = detune * self->alpsize; for (j=0; j<3; j++) { xind = self->alp_in_count[j] - (alpdetune * alp_chorus_factor[j]); if (xind < 0) xind += self->alpsize; ind = (long)xind; frac = xind - ind; alpsampdel = self->alpbuffer[j][ind] + (self->alpbuffer[j][ind+1] - self->alpbuffer[j][ind]) * frac; alpsampdelin = val + ((val - alpsampdel) * alp_feedback); val = alpsampdelin * alp_feedback + alpsampdel; /* write current allpass value in the allpass delay line */ self->alpbuffer[j][self->alp_in_count[j]] = alpsampdelin; if (self->alp_in_count[j] == 0) self->alpbuffer[j][self->alpsize] = alpsampdelin; self->alp_in_count[j]++; if (self->alp_in_count[j] == self->alpsize) self->alp_in_count[j] = 0; } /* DC filtering and output */ y = val - self->xn1 + 0.995 * self->yn1; self->xn1 = val; self->data[i] = self->yn1 = y; /* write current value in the delay line */ self->buffer[self->in_count] = in[i] + val * feed; if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void AllpassWG_postprocessing_ii(AllpassWG *self) { POST_PROCESSING_II }; static void AllpassWG_postprocessing_ai(AllpassWG *self) { POST_PROCESSING_AI }; static void AllpassWG_postprocessing_ia(AllpassWG *self) { POST_PROCESSING_IA }; static void AllpassWG_postprocessing_aa(AllpassWG *self) { POST_PROCESSING_AA }; static void AllpassWG_postprocessing_ireva(AllpassWG *self) { POST_PROCESSING_IREVA }; static void AllpassWG_postprocessing_areva(AllpassWG *self) { POST_PROCESSING_AREVA }; static void AllpassWG_postprocessing_revai(AllpassWG *self) { POST_PROCESSING_REVAI }; static void AllpassWG_postprocessing_revaa(AllpassWG *self) { POST_PROCESSING_REVAA }; static void AllpassWG_postprocessing_revareva(AllpassWG *self) { POST_PROCESSING_REVAREVA }; static void AllpassWG_setProcMode(AllpassWG *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = AllpassWG_process_iii; break; case 1: self->proc_func_ptr = AllpassWG_process_aii; break; case 10: self->proc_func_ptr = AllpassWG_process_iai; break; case 11: self->proc_func_ptr = AllpassWG_process_aai; break; case 100: self->proc_func_ptr = AllpassWG_process_iia; break; case 101: self->proc_func_ptr = AllpassWG_process_aia; break; case 110: self->proc_func_ptr = AllpassWG_process_iaa; break; case 111: self->proc_func_ptr = AllpassWG_process_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = AllpassWG_postprocessing_ii; break; case 1: self->muladd_func_ptr = AllpassWG_postprocessing_ai; break; case 2: self->muladd_func_ptr = AllpassWG_postprocessing_revai; break; case 10: self->muladd_func_ptr = AllpassWG_postprocessing_ia; break; case 11: self->muladd_func_ptr = AllpassWG_postprocessing_aa; break; case 12: self->muladd_func_ptr = AllpassWG_postprocessing_revaa; break; case 20: self->muladd_func_ptr = AllpassWG_postprocessing_ireva; break; case 21: self->muladd_func_ptr = AllpassWG_postprocessing_areva; break; case 22: self->muladd_func_ptr = AllpassWG_postprocessing_revareva; break; } } static void AllpassWG_compute_next_data_frame(AllpassWG *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int AllpassWG_traverse(AllpassWG *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->feed); Py_VISIT(self->feed_stream); Py_VISIT(self->detune); Py_VISIT(self->detune_stream); return 0; } static int AllpassWG_clear(AllpassWG *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->feed); Py_CLEAR(self->feed_stream); Py_CLEAR(self->detune); Py_CLEAR(self->detune_stream); return 0; } static void AllpassWG_dealloc(AllpassWG* self) { int i; pyo_DEALLOC free(self->buffer); for(i=0; i<3; i++) { free(self->alpbuffer[i]); } AllpassWG_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * AllpassWG_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, j; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *feedtmp=NULL, *detunetmp=NULL, *multmp=NULL, *addtmp=NULL; AllpassWG *self; self = (AllpassWG *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(100); self->feed = PyFloat_FromDouble(0.); self->detune = PyFloat_FromDouble(0.5); self->minfreq = 20; self->in_count = self->alp_in_count[0] = self->alp_in_count[1] = self->alp_in_count[2] = 0; self->xn1 = 0.0; self->yn1 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.45; Stream_setFunctionPtr(self->stream, AllpassWG_compute_next_data_frame); self->mode_func_ptr = AllpassWG_setProcMode; static char *kwlist[] = {"input", "freq", "feed", "detune", "minfreq", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOOFOO, kwlist, &inputtmp, &freqtmp, &feedtmp, &detunetmp, &self->minfreq, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (feedtmp) { PyObject_CallMethod((PyObject *)self, "setFeed", "O", feedtmp); } if (detunetmp) { PyObject_CallMethod((PyObject *)self, "setDetune", "O", detunetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->size = (long)(1.0 / self->minfreq * self->sr + 0.5); self->buffer = (MYFLT *)realloc(self->buffer, (self->size+1) * sizeof(MYFLT)); for (i=0; i<(self->size+1); i++) { self->buffer[i] = 0.; } self->alpsize = (int)(self->sr * 0.0025); for (i=0; i<3; i++) { self->alpbuffer[i] = (MYFLT *)realloc(self->alpbuffer[i], (self->alpsize+1) * sizeof(MYFLT)); for (j=0; j<(self->alpsize+1); j++) { self->alpbuffer[i][j] = 0.; } } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * AllpassWG_getServer(AllpassWG* self) { GET_SERVER }; static PyObject * AllpassWG_getStream(AllpassWG* self) { GET_STREAM }; static PyObject * AllpassWG_setMul(AllpassWG *self, PyObject *arg) { SET_MUL }; static PyObject * AllpassWG_setAdd(AllpassWG *self, PyObject *arg) { SET_ADD }; static PyObject * AllpassWG_setSub(AllpassWG *self, PyObject *arg) { SET_SUB }; static PyObject * AllpassWG_setDiv(AllpassWG *self, PyObject *arg) { SET_DIV }; static PyObject * AllpassWG_play(AllpassWG *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * AllpassWG_out(AllpassWG *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * AllpassWG_stop(AllpassWG *self) { STOP }; static PyObject * AllpassWG_multiply(AllpassWG *self, PyObject *arg) { MULTIPLY }; static PyObject * AllpassWG_inplace_multiply(AllpassWG *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * AllpassWG_add(AllpassWG *self, PyObject *arg) { ADD }; static PyObject * AllpassWG_inplace_add(AllpassWG *self, PyObject *arg) { INPLACE_ADD }; static PyObject * AllpassWG_sub(AllpassWG *self, PyObject *arg) { SUB }; static PyObject * AllpassWG_inplace_sub(AllpassWG *self, PyObject *arg) { INPLACE_SUB }; static PyObject * AllpassWG_div(AllpassWG *self, PyObject *arg) { DIV }; static PyObject * AllpassWG_inplace_div(AllpassWG *self, PyObject *arg) { INPLACE_DIV }; static PyObject * AllpassWG_setFreq(AllpassWG *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * AllpassWG_setFeed(AllpassWG *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->feed); if (isNumber == 1) { self->feed = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->feed = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->feed, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->feed_stream); self->feed_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * AllpassWG_setDetune(AllpassWG *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->detune); if (isNumber == 1) { self->detune = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->detune = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->detune, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->detune_stream); self->detune_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef AllpassWG_members[] = { {"server", T_OBJECT_EX, offsetof(AllpassWG, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(AllpassWG, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(AllpassWG, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(AllpassWG, freq), 0, "AllpassWG time in seconds."}, {"feed", T_OBJECT_EX, offsetof(AllpassWG, feed), 0, "Feedback value."}, {"detune", T_OBJECT_EX, offsetof(AllpassWG, detune), 0, "Detune value between 0 and 1."}, {"mul", T_OBJECT_EX, offsetof(AllpassWG, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(AllpassWG, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef AllpassWG_methods[] = { {"getServer", (PyCFunction)AllpassWG_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)AllpassWG_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)AllpassWG_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)AllpassWG_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)AllpassWG_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)AllpassWG_setFreq, METH_O, "Sets freq time in seconds."}, {"setFeed", (PyCFunction)AllpassWG_setFeed, METH_O, "Sets feed value between 0 -> 1."}, {"setDetune", (PyCFunction)AllpassWG_setDetune, METH_O, "Sets detune value between 0 -> 1."}, {"setMul", (PyCFunction)AllpassWG_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)AllpassWG_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)AllpassWG_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)AllpassWG_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods AllpassWG_as_number = { (binaryfunc)AllpassWG_add, /*nb_add*/ (binaryfunc)AllpassWG_sub, /*nb_subtract*/ (binaryfunc)AllpassWG_multiply, /*nb_multiply*/ (binaryfunc)AllpassWG_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)AllpassWG_inplace_add, /*inplace_add*/ (binaryfunc)AllpassWG_inplace_sub, /*inplace_subtract*/ (binaryfunc)AllpassWG_inplace_multiply, /*inplace_multiply*/ (binaryfunc)AllpassWG_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject AllpassWGType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.AllpassWG_base", /*tp_name*/ sizeof(AllpassWG), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)AllpassWG_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &AllpassWG_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "AllpassWG objects. Waveguide model with builtin allpass circuit to detune resonance frequencies.", /* tp_doc */ (traverseproc)AllpassWG_traverse, /* tp_traverse */ (inquiry)AllpassWG_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ AllpassWG_methods, /* tp_methods */ AllpassWG_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ AllpassWG_new, /* tp_new */ }; /************/ /* Delay1 */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add MYFLT x1; } Delay1; static void Delay1_filters(Delay1 *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = self->x1; self->x1 = in[i]; } } static void Delay1_postprocessing_ii(Delay1 *self) { POST_PROCESSING_II }; static void Delay1_postprocessing_ai(Delay1 *self) { POST_PROCESSING_AI }; static void Delay1_postprocessing_ia(Delay1 *self) { POST_PROCESSING_IA }; static void Delay1_postprocessing_aa(Delay1 *self) { POST_PROCESSING_AA }; static void Delay1_postprocessing_ireva(Delay1 *self) { POST_PROCESSING_IREVA }; static void Delay1_postprocessing_areva(Delay1 *self) { POST_PROCESSING_AREVA }; static void Delay1_postprocessing_revai(Delay1 *self) { POST_PROCESSING_REVAI }; static void Delay1_postprocessing_revaa(Delay1 *self) { POST_PROCESSING_REVAA }; static void Delay1_postprocessing_revareva(Delay1 *self) { POST_PROCESSING_REVAREVA }; static void Delay1_setProcMode(Delay1 *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Delay1_filters; switch (muladdmode) { case 0: self->muladd_func_ptr = Delay1_postprocessing_ii; break; case 1: self->muladd_func_ptr = Delay1_postprocessing_ai; break; case 2: self->muladd_func_ptr = Delay1_postprocessing_revai; break; case 10: self->muladd_func_ptr = Delay1_postprocessing_ia; break; case 11: self->muladd_func_ptr = Delay1_postprocessing_aa; break; case 12: self->muladd_func_ptr = Delay1_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Delay1_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Delay1_postprocessing_areva; break; case 22: self->muladd_func_ptr = Delay1_postprocessing_revareva; break; } } static void Delay1_compute_next_data_frame(Delay1 *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Delay1_traverse(Delay1 *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Delay1_clear(Delay1 *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Delay1_dealloc(Delay1* self) { pyo_DEALLOC Delay1_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Delay1_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; Delay1 *self; self = (Delay1 *)type->tp_alloc(type, 0); self->x1 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Delay1_compute_next_data_frame); self->mode_func_ptr = Delay1_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Delay1_getServer(Delay1* self) { GET_SERVER }; static PyObject * Delay1_getStream(Delay1* self) { GET_STREAM }; static PyObject * Delay1_setMul(Delay1 *self, PyObject *arg) { SET_MUL }; static PyObject * Delay1_setAdd(Delay1 *self, PyObject *arg) { SET_ADD }; static PyObject * Delay1_setSub(Delay1 *self, PyObject *arg) { SET_SUB }; static PyObject * Delay1_setDiv(Delay1 *self, PyObject *arg) { SET_DIV }; static PyObject * Delay1_play(Delay1 *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Delay1_out(Delay1 *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Delay1_stop(Delay1 *self) { STOP }; static PyObject * Delay1_multiply(Delay1 *self, PyObject *arg) { MULTIPLY }; static PyObject * Delay1_inplace_multiply(Delay1 *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Delay1_add(Delay1 *self, PyObject *arg) { ADD }; static PyObject * Delay1_inplace_add(Delay1 *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Delay1_sub(Delay1 *self, PyObject *arg) { SUB }; static PyObject * Delay1_inplace_sub(Delay1 *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Delay1_div(Delay1 *self, PyObject *arg) { DIV }; static PyObject * Delay1_inplace_div(Delay1 *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Delay1_members[] = { {"server", T_OBJECT_EX, offsetof(Delay1, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Delay1, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Delay1, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(Delay1, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Delay1, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Delay1_methods[] = { {"getServer", (PyCFunction)Delay1_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Delay1_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Delay1_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Delay1_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Delay1_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Delay1_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Delay1_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Delay1_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Delay1_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Delay1_as_number = { (binaryfunc)Delay1_add, /*nb_add*/ (binaryfunc)Delay1_sub, /*nb_subtract*/ (binaryfunc)Delay1_multiply, /*nb_multiply*/ (binaryfunc)Delay1_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Delay1_inplace_add, /*inplace_add*/ (binaryfunc)Delay1_inplace_sub, /*inplace_subtract*/ (binaryfunc)Delay1_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Delay1_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject Delay1Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Delay1_base", /*tp_name*/ sizeof(Delay1), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Delay1_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Delay1_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Delay1 objects. Delays a signal by one sample.", /* tp_doc */ (traverseproc)Delay1_traverse, /* tp_traverse */ (inquiry)Delay1_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Delay1_methods, /* tp_methods */ Delay1_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Delay1_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *delay; Stream *delay_stream; PyObject *feedback; Stream *feedback_stream; MYFLT crossfade; MYFLT maxdelay; MYFLT oneOverSr; MYFLT amp1; MYFLT amp2; MYFLT inc1; MYFLT inc2; int current; long timer; long size; long in_count; long sampdel; MYFLT sampdel1; MYFLT sampdel2; int modebuffer[4]; MYFLT *buffer; // samples memory } SmoothDelay; static void SmoothDelay_process_ii(SmoothDelay *self) { MYFLT val, xind, frac, sum; int i; long ind, xsamps = 0; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT del = PyFloat_AS_DOUBLE(self->delay); MYFLT feed = PyFloat_AS_DOUBLE(self->feedback); if (del < self->oneOverSr) del = self->oneOverSr; else if (del > self->maxdelay) del = self->maxdelay; if (feed < 0) feed = 0.0; else if (feed > 1) feed = 1.0; for (i=0; ibufsize; i++) { if (self->timer == 0) { self->current = (self->current + 1) % 2; self->sampdel = (long)(del * self->sr + 0.5); xsamps = (long)(self->crossfade * self->sr + 0.5); if (xsamps > self->sampdel) xsamps = self->sampdel; if (xsamps <= 0) xsamps = 1; if (self->current == 0) { self->sampdel1 = del * self->sr; self->inc1 = 1.0 / xsamps; self->inc2 = -self->inc1; } else { self->sampdel2 = del * self->sr; self->inc2 = 1.0 / xsamps; self->inc1 = -self->inc2; } } xind = self->in_count - self->sampdel1; while (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; sum = val * self->amp1; self->amp1 += self->inc1; if (self->amp1 < 0) self->amp1 = 0.0; else if (self->amp1 > 1) self->amp1 = 1.0; xind = self->in_count - self->sampdel2; while (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; sum += val * self->amp2; self->amp2 += self->inc2; if (self->amp2 < 0) self->amp2 = 0.0; else if (self->amp2 > 1) self->amp2 = 1.0; self->data[i] = sum; self->buffer[self->in_count] = in[i] + (sum * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count >= self->size) self->in_count = 0; self->timer++; if (self->timer == self->sampdel) self->timer = 0; } } static void SmoothDelay_process_ai(SmoothDelay *self) { MYFLT val, xind, frac, sum, del; int i; long ind, xsamps = 0; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *dl = Stream_getData((Stream *)self->delay_stream); MYFLT feed = PyFloat_AS_DOUBLE(self->feedback); if (feed < 0) feed = 0.0; else if (feed > 1) feed = 1.0; for (i=0; ibufsize; i++) { if (self->timer == 0) { del = dl[i]; if (del < self->oneOverSr) del = self->oneOverSr; else if (del > self->maxdelay) del = self->maxdelay; self->current = (self->current + 1) % 2; self->sampdel = (long)(del * self->sr + 0.5); xsamps = (long)(self->crossfade * self->sr + 0.5); if (xsamps > self->sampdel) xsamps = self->sampdel; if (xsamps <= 0) xsamps = 1; if (self->current == 0) { self->sampdel1 = del * self->sr; self->inc1 = 1.0 / xsamps; self->inc2 = -self->inc1; } else { self->sampdel2 = del * self->sr; self->inc2 = 1.0 / xsamps; self->inc1 = -self->inc2; } } xind = self->in_count - self->sampdel1; while (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; sum = val * self->amp1; self->amp1 += self->inc1; if (self->amp1 < 0) self->amp1 = 0.0; else if (self->amp1 > 1) self->amp1 = 1.0; xind = self->in_count - self->sampdel2; while (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; sum += val * self->amp2; self->amp2 += self->inc2; if (self->amp2 < 0) self->amp2 = 0.0; else if (self->amp2 > 1) self->amp2 = 1.0; self->data[i] = sum; self->buffer[self->in_count] = in[i] + (sum * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count >= self->size) self->in_count = 0; self->timer++; if (self->timer == self->sampdel) self->timer = 0; } } static void SmoothDelay_process_ia(SmoothDelay *self) { MYFLT val, xind, frac, sum, feed; int i; long ind, xsamps = 0; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT del = PyFloat_AS_DOUBLE(self->delay); MYFLT *fd = Stream_getData((Stream *)self->feedback_stream); if (del < self->oneOverSr) del = self->oneOverSr; else if (del > self->maxdelay) del = self->maxdelay; for (i=0; ibufsize; i++) { feed = fd[i]; if (feed < 0) feed = 0.0; else if (feed > 1) feed = 1.0; if (self->timer == 0) { self->current = (self->current + 1) % 2; self->sampdel = (long)(del * self->sr + 0.5); xsamps = (long)(self->crossfade * self->sr + 0.5); if (xsamps > self->sampdel) xsamps = self->sampdel; if (xsamps <= 0) xsamps = 1; if (self->current == 0) { self->sampdel1 = del * self->sr; self->inc1 = 1.0 / xsamps; self->inc2 = -self->inc1; } else { self->sampdel2 = del * self->sr; self->inc2 = 1.0 / xsamps; self->inc1 = -self->inc2; } } xind = self->in_count - self->sampdel1; while (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; sum = val * self->amp1; self->amp1 += self->inc1; if (self->amp1 < 0) self->amp1 = 0.0; else if (self->amp1 > 1) self->amp1 = 1.0; xind = self->in_count - self->sampdel2; while (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; sum += val * self->amp2; self->amp2 += self->inc2; if (self->amp2 < 0) self->amp2 = 0.0; else if (self->amp2 > 1) self->amp2 = 1.0; self->data[i] = sum; self->buffer[self->in_count] = in[i] + (sum * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count >= self->size) self->in_count = 0; self->timer++; if (self->timer == self->sampdel) self->timer = 0; } } static void SmoothDelay_process_aa(SmoothDelay *self) { MYFLT val, xind, frac, sum, del, feed; int i; long ind, xsamps = 0; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *dl = Stream_getData((Stream *)self->delay_stream); MYFLT *fd = Stream_getData((Stream *)self->feedback_stream); for (i=0; ibufsize; i++) { feed = fd[i]; if (feed < 0) feed = 0.0; else if (feed > 1) feed = 1.0; if (self->timer == 0) { del = dl[i]; if (del < self->oneOverSr) del = self->oneOverSr; else if (del > self->maxdelay) del = self->maxdelay; self->current = (self->current + 1) % 2; self->sampdel = (long)(del * self->sr + 0.5); xsamps = (long)(self->crossfade * self->sr + 0.5); if (xsamps > self->sampdel) xsamps = self->sampdel; if (xsamps <= 0) xsamps = 1; if (self->current == 0) { self->sampdel1 = del * self->sr; self->inc1 = 1.0 / xsamps; self->inc2 = -self->inc1; } else { self->sampdel2 = del * self->sr; self->inc2 = 1.0 / xsamps; self->inc1 = -self->inc2; } } xind = self->in_count - self->sampdel1; while (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; sum = val * self->amp1; self->amp1 += self->inc1; if (self->amp1 < 0) self->amp1 = 0.0; else if (self->amp1 > 1) self->amp1 = 1.0; xind = self->in_count - self->sampdel2; while (xind < 0) xind += self->size; ind = (long)xind; frac = xind - ind; val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac; sum += val * self->amp2; self->amp2 += self->inc2; if (self->amp2 < 0) self->amp2 = 0.0; else if (self->amp2 > 1) self->amp2 = 1.0; self->data[i] = sum; self->buffer[self->in_count] = in[i] + (sum * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count >= self->size) self->in_count = 0; self->timer++; if (self->timer == self->sampdel) self->timer = 0; } } static void SmoothDelay_postprocessing_ii(SmoothDelay *self) { POST_PROCESSING_II }; static void SmoothDelay_postprocessing_ai(SmoothDelay *self) { POST_PROCESSING_AI }; static void SmoothDelay_postprocessing_ia(SmoothDelay *self) { POST_PROCESSING_IA }; static void SmoothDelay_postprocessing_aa(SmoothDelay *self) { POST_PROCESSING_AA }; static void SmoothDelay_postprocessing_ireva(SmoothDelay *self) { POST_PROCESSING_IREVA }; static void SmoothDelay_postprocessing_areva(SmoothDelay *self) { POST_PROCESSING_AREVA }; static void SmoothDelay_postprocessing_revai(SmoothDelay *self) { POST_PROCESSING_REVAI }; static void SmoothDelay_postprocessing_revaa(SmoothDelay *self) { POST_PROCESSING_REVAA }; static void SmoothDelay_postprocessing_revareva(SmoothDelay *self) { POST_PROCESSING_REVAREVA }; static void SmoothDelay_setProcMode(SmoothDelay *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = SmoothDelay_process_ii; break; case 1: self->proc_func_ptr = SmoothDelay_process_ai; break; case 10: self->proc_func_ptr = SmoothDelay_process_ia; break; case 11: self->proc_func_ptr = SmoothDelay_process_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = SmoothDelay_postprocessing_ii; break; case 1: self->muladd_func_ptr = SmoothDelay_postprocessing_ai; break; case 2: self->muladd_func_ptr = SmoothDelay_postprocessing_revai; break; case 10: self->muladd_func_ptr = SmoothDelay_postprocessing_ia; break; case 11: self->muladd_func_ptr = SmoothDelay_postprocessing_aa; break; case 12: self->muladd_func_ptr = SmoothDelay_postprocessing_revaa; break; case 20: self->muladd_func_ptr = SmoothDelay_postprocessing_ireva; break; case 21: self->muladd_func_ptr = SmoothDelay_postprocessing_areva; break; case 22: self->muladd_func_ptr = SmoothDelay_postprocessing_revareva; break; } } static void SmoothDelay_compute_next_data_frame(SmoothDelay *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int SmoothDelay_traverse(SmoothDelay *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->delay); Py_VISIT(self->delay_stream); Py_VISIT(self->feedback); Py_VISIT(self->feedback_stream); return 0; } static int SmoothDelay_clear(SmoothDelay *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->delay); Py_CLEAR(self->delay_stream); Py_CLEAR(self->feedback); Py_CLEAR(self->feedback_stream); return 0; } static void SmoothDelay_dealloc(SmoothDelay* self) { pyo_DEALLOC free(self->buffer); SmoothDelay_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SmoothDelay_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *delaytmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL; SmoothDelay *self; self = (SmoothDelay *)type->tp_alloc(type, 0); self->delay = PyFloat_FromDouble(0.25); self->feedback = PyFloat_FromDouble(0); self->crossfade = 0.05; self->maxdelay = 1; self->in_count = 0; self->current = 1; self->timer = 0; self->amp1 = 0.0; self->amp2 = 1.0; self->inc1 = self->inc2 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON self->oneOverSr = self->sampdel1 = self->sampdel2 = 1.0 / self->sr; Stream_setFunctionPtr(self->stream, SmoothDelay_compute_next_data_frame); self->mode_func_ptr = SmoothDelay_setProcMode; static char *kwlist[] = {"input", "delay", "feedback", "crossfade", "maxdelay", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOFFOO, kwlist, &inputtmp, &delaytmp, &feedbacktmp, &self->crossfade, &self->maxdelay, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (delaytmp) { PyObject_CallMethod((PyObject *)self, "setDelay", "O", delaytmp); } if (feedbacktmp) { PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->size = (long)(self->maxdelay * self->sr + 0.5); self->buffer = (MYFLT *)realloc(self->buffer, (self->size+1) * sizeof(MYFLT)); for (i=0; i<(self->size+1); i++) { self->buffer[i] = 0.; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * SmoothDelay_getServer(SmoothDelay* self) { GET_SERVER }; static PyObject * SmoothDelay_getStream(SmoothDelay* self) { GET_STREAM }; static PyObject * SmoothDelay_setMul(SmoothDelay *self, PyObject *arg) { SET_MUL }; static PyObject * SmoothDelay_setAdd(SmoothDelay *self, PyObject *arg) { SET_ADD }; static PyObject * SmoothDelay_setSub(SmoothDelay *self, PyObject *arg) { SET_SUB }; static PyObject * SmoothDelay_setDiv(SmoothDelay *self, PyObject *arg) { SET_DIV }; static PyObject * SmoothDelay_play(SmoothDelay *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SmoothDelay_out(SmoothDelay *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * SmoothDelay_stop(SmoothDelay *self) { STOP }; static PyObject * SmoothDelay_multiply(SmoothDelay *self, PyObject *arg) { MULTIPLY }; static PyObject * SmoothDelay_inplace_multiply(SmoothDelay *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * SmoothDelay_add(SmoothDelay *self, PyObject *arg) { ADD }; static PyObject * SmoothDelay_inplace_add(SmoothDelay *self, PyObject *arg) { INPLACE_ADD }; static PyObject * SmoothDelay_sub(SmoothDelay *self, PyObject *arg) { SUB }; static PyObject * SmoothDelay_inplace_sub(SmoothDelay *self, PyObject *arg) { INPLACE_SUB }; static PyObject * SmoothDelay_div(SmoothDelay *self, PyObject *arg) { DIV }; static PyObject * SmoothDelay_inplace_div(SmoothDelay *self, PyObject *arg) { INPLACE_DIV }; static PyObject * SmoothDelay_setDelay(SmoothDelay *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->delay); if (isNumber == 1) { self->delay = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->delay = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->delay, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->delay_stream); self->delay_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SmoothDelay_setFeedback(SmoothDelay *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->feedback); if (isNumber == 1) { self->feedback = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->feedback = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->feedback_stream); self->feedback_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SmoothDelay_setCrossfade(SmoothDelay *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->crossfade = PyFloat_AsDouble(arg); } Py_RETURN_NONE; } static PyObject * SmoothDelay_reset(SmoothDelay *self) { int i; for (i=0; i<(self->size+1); i++) { self->buffer[i] = 0.; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef SmoothDelay_members[] = { {"server", T_OBJECT_EX, offsetof(SmoothDelay, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SmoothDelay, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(SmoothDelay, input), 0, "Input sound object."}, {"delay", T_OBJECT_EX, offsetof(SmoothDelay, delay), 0, "SmoothDelay time in seconds."}, {"feedback", T_OBJECT_EX, offsetof(SmoothDelay, feedback), 0, "Feedback value."}, {"mul", T_OBJECT_EX, offsetof(SmoothDelay, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(SmoothDelay, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef SmoothDelay_methods[] = { {"getServer", (PyCFunction)SmoothDelay_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SmoothDelay_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SmoothDelay_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)SmoothDelay_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)SmoothDelay_stop, METH_NOARGS, "Stops computing."}, {"setDelay", (PyCFunction)SmoothDelay_setDelay, METH_O, "Sets delay time in seconds."}, {"setFeedback", (PyCFunction)SmoothDelay_setFeedback, METH_O, "Sets feedback value between 0 -> 1."}, {"setCrossfade", (PyCFunction)SmoothDelay_setCrossfade, METH_O, "Sets crossfade time."}, {"reset", (PyCFunction)SmoothDelay_reset, METH_NOARGS, "Resets the memory buffer to zeros."}, {"setMul", (PyCFunction)SmoothDelay_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)SmoothDelay_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)SmoothDelay_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)SmoothDelay_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods SmoothDelay_as_number = { (binaryfunc)SmoothDelay_add, /*nb_add*/ (binaryfunc)SmoothDelay_sub, /*nb_subtract*/ (binaryfunc)SmoothDelay_multiply, /*nb_multiply*/ (binaryfunc)SmoothDelay_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)SmoothDelay_inplace_add, /*inplace_add*/ (binaryfunc)SmoothDelay_inplace_sub, /*inplace_subtract*/ (binaryfunc)SmoothDelay_inplace_multiply, /*inplace_multiply*/ (binaryfunc)SmoothDelay_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SmoothDelayType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SmoothDelay_base", /*tp_name*/ sizeof(SmoothDelay), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SmoothDelay_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &SmoothDelay_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SmoothDelay objects. Delay signal by x samples.", /* tp_doc */ (traverseproc)SmoothDelay_traverse, /* tp_traverse */ (inquiry)SmoothDelay_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SmoothDelay_methods, /* tp_methods */ SmoothDelay_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SmoothDelay_new, /* tp_new */ };pyo/src/objects/noisemodule.c0000644000175000017500000007732712652732202015605 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD int modebuffer[2]; int seed; int type; } Noise; static void Noise_generate(Noise *self) { int i; for (i=0; ibufsize; i++) { self->data[i] = rand()/((MYFLT)(RAND_MAX)+1)*1.98-0.99; } } static void Noise_generate_cheap(Noise *self) { int i; for (i=0; ibufsize; i++) { self->seed = (self->seed * 15625 + 1) & 0xFFFF; self->data[i] = (self->seed - 0x8000) * 3.0517578125e-05; } } static void Noise_postprocessing_ii(Noise *self) { POST_PROCESSING_II }; static void Noise_postprocessing_ai(Noise *self) { POST_PROCESSING_AI }; static void Noise_postprocessing_ia(Noise *self) { POST_PROCESSING_IA }; static void Noise_postprocessing_aa(Noise *self) { POST_PROCESSING_AA }; static void Noise_postprocessing_ireva(Noise *self) { POST_PROCESSING_IREVA }; static void Noise_postprocessing_areva(Noise *self) { POST_PROCESSING_AREVA }; static void Noise_postprocessing_revai(Noise *self) { POST_PROCESSING_REVAI }; static void Noise_postprocessing_revaa(Noise *self) { POST_PROCESSING_REVAA }; static void Noise_postprocessing_revareva(Noise *self) { POST_PROCESSING_REVAREVA }; static void Noise_setProcMode(Noise *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (self->type) { case 0: self->proc_func_ptr = Noise_generate; break; case 1: self->proc_func_ptr = Noise_generate_cheap; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Noise_postprocessing_ii; break; case 1: self->muladd_func_ptr = Noise_postprocessing_ai; break; case 2: self->muladd_func_ptr = Noise_postprocessing_revai; break; case 10: self->muladd_func_ptr = Noise_postprocessing_ia; break; case 11: self->muladd_func_ptr = Noise_postprocessing_aa; break; case 12: self->muladd_func_ptr = Noise_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Noise_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Noise_postprocessing_areva; break; case 22: self->muladd_func_ptr = Noise_postprocessing_revareva; break; } } static void Noise_compute_next_data_frame(Noise *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Noise_traverse(Noise *self, visitproc visit, void *arg) { pyo_VISIT return 0; } static int Noise_clear(Noise *self) { pyo_CLEAR return 0; } static void Noise_dealloc(Noise* self) { pyo_DEALLOC Noise_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Noise_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *multmp=NULL, *addtmp=NULL; Noise *self; self = (Noise *)type->tp_alloc(type, 0); self->type = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Noise_compute_next_data_frame); self->mode_func_ptr = Noise_setProcMode; static char *kwlist[] = {"mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &multmp, &addtmp)) Py_RETURN_NONE; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Server_generateSeed((Server *)self->server, NOISE_ID); self->seed = rand(); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Noise_getServer(Noise* self) { GET_SERVER }; static PyObject * Noise_getStream(Noise* self) { GET_STREAM }; static PyObject * Noise_setMul(Noise *self, PyObject *arg) { SET_MUL }; static PyObject * Noise_setAdd(Noise *self, PyObject *arg) { SET_ADD }; static PyObject * Noise_setSub(Noise *self, PyObject *arg) { SET_SUB }; static PyObject * Noise_setDiv(Noise *self, PyObject *arg) { SET_DIV }; static PyObject * Noise_play(Noise *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Noise_out(Noise *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Noise_stop(Noise *self) { STOP }; static PyObject * Noise_multiply(Noise *self, PyObject *arg) { MULTIPLY }; static PyObject * Noise_inplace_multiply(Noise *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Noise_add(Noise *self, PyObject *arg) { ADD }; static PyObject * Noise_inplace_add(Noise *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Noise_sub(Noise *self, PyObject *arg) { SUB }; static PyObject * Noise_inplace_sub(Noise *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Noise_div(Noise *self, PyObject *arg) { DIV }; static PyObject * Noise_inplace_div(Noise *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Noise_setType(Noise *self, PyObject *arg) { ASSERT_ARG_NOT_NULL if (PyInt_AS_LONG(arg) == 0) self->type = 0; else if (PyInt_AS_LONG(arg) == 1) self->type = 1; (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Noise_members[] = { {"server", T_OBJECT_EX, offsetof(Noise, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Noise, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Noise, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Noise, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Noise_methods[] = { {"getServer", (PyCFunction)Noise_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Noise_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Noise_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Noise_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Noise_stop, METH_NOARGS, "Stops computing."}, {"setType", (PyCFunction)Noise_setType, METH_O, "Sets Noise generation algorithm."}, {"setMul", (PyCFunction)Noise_setMul, METH_O, "Sets Noise mul factor."}, {"setAdd", (PyCFunction)Noise_setAdd, METH_O, "Sets Noise add factor."}, {"setSub", (PyCFunction)Noise_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Noise_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Noise_as_number = { (binaryfunc)Noise_add, /*nb_add*/ (binaryfunc)Noise_sub, /*nb_subtract*/ (binaryfunc)Noise_multiply, /*nb_multiply*/ (binaryfunc)Noise_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Noise_inplace_add, /*inplace_add*/ (binaryfunc)Noise_inplace_sub, /*inplace_subtract*/ (binaryfunc)Noise_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Noise_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject NoiseType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Noise_base", /*tp_name*/ sizeof(Noise), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Noise_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Noise_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Noise objects. White noise generator.", /* tp_doc */ (traverseproc)Noise_traverse, /* tp_traverse */ (inquiry)Noise_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Noise_methods, /* tp_methods */ Noise_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Noise_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD int modebuffer[2]; MYFLT c0; MYFLT c1; MYFLT c2; MYFLT c3; MYFLT c4; MYFLT c5; MYFLT c6; } PinkNoise; static void PinkNoise_generate(PinkNoise *self) { MYFLT in, val; int i; for (i=0; ibufsize; i++) { in = rand()/((MYFLT)(RAND_MAX)+1)*1.98-0.99; self->c0 = self->c0 * 0.99886 + in * 0.0555179; self->c1 = self->c1 * 0.99332 + in * 0.0750759; self->c2 = self->c2 * 0.96900 + in * 0.1538520; self->c3 = self->c3 * 0.86650 + in * 0.3104856; self->c4 = self->c4 * 0.55000 + in * 0.5329522; self->c5 = self->c5 * -0.7616 - in * 0.0168980; val = self->c0 + self->c1 + self->c2 + self->c3 + self->c4 + self->c5 + self->c6 + in * 0.5362; self->data[i] = val * 0.2; self->c6 = in * 0.115926; } } static void PinkNoise_postprocessing_ii(PinkNoise *self) { POST_PROCESSING_II }; static void PinkNoise_postprocessing_ai(PinkNoise *self) { POST_PROCESSING_AI }; static void PinkNoise_postprocessing_ia(PinkNoise *self) { POST_PROCESSING_IA }; static void PinkNoise_postprocessing_aa(PinkNoise *self) { POST_PROCESSING_AA }; static void PinkNoise_postprocessing_ireva(PinkNoise *self) { POST_PROCESSING_IREVA }; static void PinkNoise_postprocessing_areva(PinkNoise *self) { POST_PROCESSING_AREVA }; static void PinkNoise_postprocessing_revai(PinkNoise *self) { POST_PROCESSING_REVAI }; static void PinkNoise_postprocessing_revaa(PinkNoise *self) { POST_PROCESSING_REVAA }; static void PinkNoise_postprocessing_revareva(PinkNoise *self) { POST_PROCESSING_REVAREVA }; static void PinkNoise_setProcMode(PinkNoise *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = PinkNoise_postprocessing_ii; break; case 1: self->muladd_func_ptr = PinkNoise_postprocessing_ai; break; case 2: self->muladd_func_ptr = PinkNoise_postprocessing_revai; break; case 10: self->muladd_func_ptr = PinkNoise_postprocessing_ia; break; case 11: self->muladd_func_ptr = PinkNoise_postprocessing_aa; break; case 12: self->muladd_func_ptr = PinkNoise_postprocessing_revaa; break; case 20: self->muladd_func_ptr = PinkNoise_postprocessing_ireva; break; case 21: self->muladd_func_ptr = PinkNoise_postprocessing_areva; break; case 22: self->muladd_func_ptr = PinkNoise_postprocessing_revareva; break; } } static void PinkNoise_compute_next_data_frame(PinkNoise *self) { PinkNoise_generate(self); (*self->muladd_func_ptr)(self); } static int PinkNoise_traverse(PinkNoise *self, visitproc visit, void *arg) { pyo_VISIT return 0; } static int PinkNoise_clear(PinkNoise *self) { pyo_CLEAR return 0; } static void PinkNoise_dealloc(PinkNoise* self) { pyo_DEALLOC PinkNoise_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PinkNoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *multmp=NULL, *addtmp=NULL; PinkNoise *self; self = (PinkNoise *)type->tp_alloc(type, 0); self->c0 = self->c1 = self->c2 = self->c3 = self->c4 = self->c5 = self->c6 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PinkNoise_compute_next_data_frame); self->mode_func_ptr = PinkNoise_setProcMode; static char *kwlist[] = {"mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &multmp, &addtmp)) Py_RETURN_NONE; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); Server_generateSeed((Server *)self->server, PINKNOISE_ID); return (PyObject *)self; } static PyObject * PinkNoise_getServer(PinkNoise* self) { GET_SERVER }; static PyObject * PinkNoise_getStream(PinkNoise* self) { GET_STREAM }; static PyObject * PinkNoise_setMul(PinkNoise *self, PyObject *arg) { SET_MUL }; static PyObject * PinkNoise_setAdd(PinkNoise *self, PyObject *arg) { SET_ADD }; static PyObject * PinkNoise_setSub(PinkNoise *self, PyObject *arg) { SET_SUB }; static PyObject * PinkNoise_setDiv(PinkNoise *self, PyObject *arg) { SET_DIV }; static PyObject * PinkNoise_play(PinkNoise *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PinkNoise_out(PinkNoise *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * PinkNoise_stop(PinkNoise *self) { STOP }; static PyObject * PinkNoise_multiply(PinkNoise *self, PyObject *arg) { MULTIPLY }; static PyObject * PinkNoise_inplace_multiply(PinkNoise *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * PinkNoise_add(PinkNoise *self, PyObject *arg) { ADD }; static PyObject * PinkNoise_inplace_add(PinkNoise *self, PyObject *arg) { INPLACE_ADD }; static PyObject * PinkNoise_sub(PinkNoise *self, PyObject *arg) { SUB }; static PyObject * PinkNoise_inplace_sub(PinkNoise *self, PyObject *arg) { INPLACE_SUB }; static PyObject * PinkNoise_div(PinkNoise *self, PyObject *arg) { DIV }; static PyObject * PinkNoise_inplace_div(PinkNoise *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef PinkNoise_members[] = { {"server", T_OBJECT_EX, offsetof(PinkNoise, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PinkNoise, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(PinkNoise, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(PinkNoise, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef PinkNoise_methods[] = { {"getServer", (PyCFunction)PinkNoise_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PinkNoise_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)PinkNoise_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)PinkNoise_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)PinkNoise_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)PinkNoise_setMul, METH_O, "Sets PinkNoise mul factor."}, {"setAdd", (PyCFunction)PinkNoise_setAdd, METH_O, "Sets PinkNoise add factor."}, {"setSub", (PyCFunction)PinkNoise_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)PinkNoise_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods PinkNoise_as_number = { (binaryfunc)PinkNoise_add, /*nb_add*/ (binaryfunc)PinkNoise_sub, /*nb_subtract*/ (binaryfunc)PinkNoise_multiply, /*nb_multiply*/ (binaryfunc)PinkNoise_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)PinkNoise_inplace_add, /*inplace_add*/ (binaryfunc)PinkNoise_inplace_sub, /*inplace_subtract*/ (binaryfunc)PinkNoise_inplace_multiply, /*inplace_multiply*/ (binaryfunc)PinkNoise_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject PinkNoiseType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PinkNoise_base", /*tp_name*/ sizeof(PinkNoise), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PinkNoise_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &PinkNoise_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PinkNoise objects. Pink noise generator.", /* tp_doc */ (traverseproc)PinkNoise_traverse, /* tp_traverse */ (inquiry)PinkNoise_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PinkNoise_methods, /* tp_methods */ PinkNoise_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PinkNoise_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD int modebuffer[2]; MYFLT y1; MYFLT c1; MYFLT c2; } BrownNoise; static void BrownNoise_generate(BrownNoise *self) { MYFLT rnd, val; int i; for (i=0; ibufsize; i++) { rnd = rand()/((MYFLT)(RAND_MAX)+1)*1.98-0.99; val = self->c1 * rnd + self->c2 * self->y1; self->y1 = val; self->data[i] = val * 20.0; /* gain compensation */ } } static void BrownNoise_postprocessing_ii(BrownNoise *self) { POST_PROCESSING_II }; static void BrownNoise_postprocessing_ai(BrownNoise *self) { POST_PROCESSING_AI }; static void BrownNoise_postprocessing_ia(BrownNoise *self) { POST_PROCESSING_IA }; static void BrownNoise_postprocessing_aa(BrownNoise *self) { POST_PROCESSING_AA }; static void BrownNoise_postprocessing_ireva(BrownNoise *self) { POST_PROCESSING_IREVA }; static void BrownNoise_postprocessing_areva(BrownNoise *self) { POST_PROCESSING_AREVA }; static void BrownNoise_postprocessing_revai(BrownNoise *self) { POST_PROCESSING_REVAI }; static void BrownNoise_postprocessing_revaa(BrownNoise *self) { POST_PROCESSING_REVAA }; static void BrownNoise_postprocessing_revareva(BrownNoise *self) { POST_PROCESSING_REVAREVA }; static void BrownNoise_setProcMode(BrownNoise *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = BrownNoise_postprocessing_ii; break; case 1: self->muladd_func_ptr = BrownNoise_postprocessing_ai; break; case 2: self->muladd_func_ptr = BrownNoise_postprocessing_revai; break; case 10: self->muladd_func_ptr = BrownNoise_postprocessing_ia; break; case 11: self->muladd_func_ptr = BrownNoise_postprocessing_aa; break; case 12: self->muladd_func_ptr = BrownNoise_postprocessing_revaa; break; case 20: self->muladd_func_ptr = BrownNoise_postprocessing_ireva; break; case 21: self->muladd_func_ptr = BrownNoise_postprocessing_areva; break; case 22: self->muladd_func_ptr = BrownNoise_postprocessing_revareva; break; } } static void BrownNoise_compute_next_data_frame(BrownNoise *self) { BrownNoise_generate(self); (*self->muladd_func_ptr)(self); } static int BrownNoise_traverse(BrownNoise *self, visitproc visit, void *arg) { pyo_VISIT return 0; } static int BrownNoise_clear(BrownNoise *self) { pyo_CLEAR return 0; } static void BrownNoise_dealloc(BrownNoise* self) { pyo_DEALLOC BrownNoise_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * BrownNoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT b; PyObject *multmp=NULL, *addtmp=NULL; BrownNoise *self; self = (BrownNoise *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->y1 = self->c1 = self->c2 = 0.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, BrownNoise_compute_next_data_frame); self->mode_func_ptr = BrownNoise_setProcMode; static char *kwlist[] = {"mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &multmp, &addtmp)) Py_RETURN_NONE; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); b = 2.0 - MYCOS(TWOPI * 20.0 / self->sr); self->c2 = (b - MYSQRT(b * b - 1.0)); self->c1 = 1.0 - self->c2; (*self->mode_func_ptr)(self); Server_generateSeed((Server *)self->server, BROWNNOISE_ID); return (PyObject *)self; } static PyObject * BrownNoise_getServer(BrownNoise* self) { GET_SERVER }; static PyObject * BrownNoise_getStream(BrownNoise* self) { GET_STREAM }; static PyObject * BrownNoise_setMul(BrownNoise *self, PyObject *arg) { SET_MUL }; static PyObject * BrownNoise_setAdd(BrownNoise *self, PyObject *arg) { SET_ADD }; static PyObject * BrownNoise_setSub(BrownNoise *self, PyObject *arg) { SET_SUB }; static PyObject * BrownNoise_setDiv(BrownNoise *self, PyObject *arg) { SET_DIV }; static PyObject * BrownNoise_play(BrownNoise *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * BrownNoise_out(BrownNoise *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * BrownNoise_stop(BrownNoise *self) { STOP }; static PyObject * BrownNoise_multiply(BrownNoise *self, PyObject *arg) { MULTIPLY }; static PyObject * BrownNoise_inplace_multiply(BrownNoise *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * BrownNoise_add(BrownNoise *self, PyObject *arg) { ADD }; static PyObject * BrownNoise_inplace_add(BrownNoise *self, PyObject *arg) { INPLACE_ADD }; static PyObject * BrownNoise_sub(BrownNoise *self, PyObject *arg) { SUB }; static PyObject * BrownNoise_inplace_sub(BrownNoise *self, PyObject *arg) { INPLACE_SUB }; static PyObject * BrownNoise_div(BrownNoise *self, PyObject *arg) { DIV }; static PyObject * BrownNoise_inplace_div(BrownNoise *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef BrownNoise_members[] = { {"server", T_OBJECT_EX, offsetof(BrownNoise, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(BrownNoise, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(BrownNoise, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(BrownNoise, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef BrownNoise_methods[] = { {"getServer", (PyCFunction)BrownNoise_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)BrownNoise_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)BrownNoise_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)BrownNoise_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)BrownNoise_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)BrownNoise_setMul, METH_O, "Sets BrownNoise mul factor."}, {"setAdd", (PyCFunction)BrownNoise_setAdd, METH_O, "Sets BrownNoise add factor."}, {"setSub", (PyCFunction)BrownNoise_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)BrownNoise_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods BrownNoise_as_number = { (binaryfunc)BrownNoise_add, /*nb_add*/ (binaryfunc)BrownNoise_sub, /*nb_subtract*/ (binaryfunc)BrownNoise_multiply, /*nb_multiply*/ (binaryfunc)BrownNoise_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)BrownNoise_inplace_add, /*inplace_add*/ (binaryfunc)BrownNoise_inplace_sub, /*inplace_subtract*/ (binaryfunc)BrownNoise_inplace_multiply, /*inplace_multiply*/ (binaryfunc)BrownNoise_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject BrownNoiseType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.BrownNoise_base", /*tp_name*/ sizeof(BrownNoise), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)BrownNoise_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &BrownNoise_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "BrownNoise objects. Brown noise generator (-6dB/octave rolloff).", /* tp_doc */ (traverseproc)BrownNoise_traverse, /* tp_traverse */ (inquiry)BrownNoise_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ BrownNoise_methods, /* tp_methods */ BrownNoise_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ BrownNoise_new, /* tp_new */ }; pyo/src/objects/harmonizermodule.c0000644000175000017500000060250312652732202016634 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" static MYFLT ENVELOPE[8193] = {1.4706855888668713e-07, 5.882741490603749e-07, 1.323616510895409e-06, 2.3530952119044102e-06, 3.6767096464052074e-06, 5.2944590357983934e-06, 7.2063424284007915e-06, 9.4123586994454556e-06, 1.1912506551192692e-05, 1.470678451293006e-05, 1.779519094086135e-05, 2.117772401805107e-05, 2.4854381754757515e-05, 2.882516198804419e-05, 3.309006238200185e-05, 3.7649080427748505e-05, 4.2502213443262882e-05, 4.7649458573606474e-05, 5.3090812790757003e-05, 5.8826272893719445e-05, 6.4855835508526027e-05, 7.1179497088069699e-05, 7.7797253912381681e-05, 8.4709102088298405e-05, 9.1915037549794576e-05, 9.9415056057872153e-05, 0.00010720915320039381, 0.00011529732439236051, 0.00012367956487557841, 0.00013235586971915847, 0.00014132623381890586, 0.00015059065189787502, 0.00016014911850603664, 0.00017000162802038865, 0.00018014817464490074, 0.00019058875241068085, 0.00020132335517580868, 0.00021235197662539118, 0.00022367461027150704, 0.00023529124945342872, 0.00024720188733734494, 0.00025940651691652716, 0.00027190513101132963, 0.00028469772226913381, 0.00029778428316434846, 0.0003111648059985761, 0.00032483928290027997, 0.00033880770582522812, 0.00035307006655616036, 0.0003676263567027882, 0.0003824765677020725, 0.00039762069081805684, 0.00041305871714181208, 0.00042879063759154734, 0.00044481644291255451, 0.00046113612367731927, 0.00047774967028535453, 0.00049465707296331152, 0.00051185832176509072, 0.00052935340657156438, 0.00054714231709085404, 0.00056522504285821951, 0.00058360157323600337, 0.0006022718974137975, 0.00062123600440833204, 0.00064049388306353094, 0.00066004552205045641, 0.00067989090986741996, 0.00070003003483981585, 0.00072046288512034318, 0.00074118944868895031, 0.00076220971335261289, 0.00078352366674577789, 0.00080513129632991953, 0.00082703258939381685, 0.0008492275330535537, 0.00087171611425240769, 0.00089449831976090577, 0.00091757413617687966, 0.00094094354992541041, 0.00096460654725882833, 0.00098856311425687959, 0.0010128132368265041, 0.0010373569007020023, 0.0010621940914449235, 0.0010873247944441777, 0.0011127489949160907, 0.0011384666779041819, 0.0011644778282794976, 0.0011907824307402226, 0.0012173804698121238, 0.001244271929848273, 0.0012714567950290467, 0.0012989350493623486, 0.0013267066766834423, 0.0013547716606548965, 0.0013831299847668621, 0.0014117816323369614, 0.0014407265865100105, 0.0014699648302585189, 0.0014994963463823563, 0.0015293211175089194, 0.0015594391260930762, 0.001589850354417166, 0.0016205547845909996, 0.0016515523985519698, 0.0016828431780650521, 0.0017144271047225823, 0.0017463041599445894, 0.001778474324978685, 0.0018109375808998962, 0.0018436939086109994, 0.001876743288842242, 0.0019100857021515094, 0.001943721128924436, 0.0019776495493740165, 0.0020118709435411053, 0.0020463852912941394, 0.0020811925723291935, 0.0021162927661700914, 0.0021516858521682392, 0.0021873718095028472, 0.0022233506171807638, 0.0022596222540365307, 0.0022961866987325497, 0.0023330439297588601, 0.0023701939254333615, 0.0024076366639015911, 0.0024453721231369463, 0.0024834002809406841, 0.0025217211149418106, 0.0025603346025971918, 0.0025992407211914426, 0.0026384394478371487, 0.0026779307594746449, 0.0027177146328722923, 0.0027577910446262011, 0.0027981599711604521, 0.0028388213887270974, 0.0028797752734060489, 0.0029210216011051338, 0.0029625603475603168, 0.0030043914883353118, 0.0030465149988219697, 0.0030889308542401683, 0.0031316390296377006, 0.0031746394998904415, 0.003217932239702348, 0.0032615172236054035, 0.0033053944259596735, 0.0033495638209533607, 0.00339402538260275, 0.0034387790847522082, 0.003483824901074295, 0.0035291628050697632, 0.0035747927700674476, 0.0036207147692244313, 0.0036669287755259905, 0.0037134347617855945, 0.0037602327006450165, 0.0038073225645741671, 0.003854704325871372, 0.003902377956663039, 0.0039503434289041017, 0.0039986007143777424, 0.0040471497846953364, 0.0040959906112967848, 0.0041451231654502374, 0.0041945474182523146, 0.0042442633406280517, 0.0042942709033307325, 0.0043445700769422779, 0.004395160831873024, 0.0044460431383615551, 0.0044972169664753148, 0.0045486822861099951, 0.0046004390669898143, 0.004652487278667683, 0.0047048268905249269, 0.0047574578717714533, 0.0048103801914459177, 0.0048635938184154459, 0.0049170987213758011, 0.0049708948688514942, 0.0050249822291955071, 0.0050793607705897359, 0.0051340304610447141, 0.005188991268399612, 0.0052442431603224038, 0.0052997861043098116, 0.0053556200676874166, 0.0054117450176094928, 0.0054681609210592286, 0.0055248677448485051, 0.0055818654556182845, 0.0056391540198381107, 0.0056967334038067752, 0.0057546035736517065, 0.0058127644953293589, 0.0058712161346252678, 0.0059299584571537167, 0.0059889914283582368, 0.0060483150135111075, 0.0061079291777139111, 0.0061678338858971449, 0.0062280291028203871, 0.0062885147930722973, 0.0063492909210707826, 0.0064103574510628314, 0.0064717143471245131, 0.006533361573161145, 0.0065952990929072364, 0.0066575268699266554, 0.0067200448676122959, 0.0067828530491864658, 0.0068459513777007208, 0.0069093398160359198, 0.0069730183269022805, 0.0070369868728394347, 0.0071012454162163174, 0.0071657939192312226, 0.0072306323439119691, 0.0072957606521157903, 0.0073611788055293892, 0.0074268867656689386, 0.0074928844938800809, 0.0075591719513381506, 0.007625749099047896, 0.007692615897843702, 0.0077597723083895342, 0.00782721829117905, 0.0078949538065354874, 0.0079629788146117764, 0.0080312932753905386, 0.0080998971486841986, 0.0081687903941348727, 0.008237972971214369, 0.0083074448392244093, 0.008377205957296463, 0.008447256284391802, 0.0085175957793017787, 0.0085882244006473818, 0.0086591421068795693, 0.0087303488562793796, 0.0088018446069576539, 0.0088736293168553138, 0.00894570294374325, 0.0090180654452223785, 0.0090907167787237508, 0.0091636569015084435, 0.0092368857706676133, 0.0093104033431227196, 0.0093842095756251909, 0.0094583044247567027, 0.0095326878469291776, 0.0096073597983847847, 0.0096823202351959403, 0.0097575691132653075, 0.0098331063883260184, 0.0099089320159413408, 0.0099850459515050116, 0.010061448150241181, 0.010138138567204413, 0.010215117157279741, 0.010292383875182609, 0.01036993867545899, 0.010447781512485432, 0.010525912340468901, 0.010604331113447163, 0.010683037785288452, 0.010762032309691583, 0.010841314640186228, 0.010920884730132474, 0.01100074253272143, 0.011080888000974787, 0.011161321087745035, 0.011242041745715414, 0.01132304992740002, 0.01140434558514386, 0.011485928671122803, 0.011567799137343682, 0.011649956935644135, 0.011732402017692822, 0.01181513433498943, 0.011898153838864722, 0.011981460480480488, 0.012065054210829484, 0.01214893498073577, 0.012233102740854374, 0.012317557441671512, 0.012402299033504816, 0.01248732746650294, 0.012572642690645786, 0.012658244655744666, 0.012744133311442085, 0.012830308607212071, 0.012916770492359841, 0.013003518916022083, 0.013090553827166951, 0.013177875174594067, 0.013265482906934467, 0.013353376972650877, 0.013441557320037434, 0.013530023897219967, 0.013618776652155773, 0.013707815532633894, 0.013797140486275117, 0.013886751460531865, 0.013976648402688308, 0.014066831259860357, 0.014157299978995785, 0.014248054506874108, 0.014339094790106921, 0.014430420775137454, 0.014522032408241015, 0.01461392963552488, 0.014706112402928184, 0.014798580656222249, 0.01489133434101042, 0.014984373402728013, 0.015077697786642585, 0.015171307437853832, 0.015265202301293468, 0.015359382321725734, 0.015453847443746949, 0.015548597611785564, 0.015643632770102667, 0.015738952862791311, 0.015834557833777407, 0.015930447626818833, 0.016026622185506101, 0.0161230814532623, 0.016219825373342822, 0.016316853888835747, 0.016414166942661734, 0.016511764477573965, 0.016609646436158365, 0.016707812760833496, 0.016806263393850551, 0.016904998277293748, 0.017004017353079715, 0.017103320562958213, 0.017202907848511639, 0.017302779151155356, 0.017402934412137638, 0.017503373572539838, 0.017604096573276107, 0.017705103355093676, 0.017806393858572911, 0.017907968024127086, 0.018009825792002943, 0.01811196710228008, 0.018214391894871396, 0.018317100109523032, 0.018420091685814322, 0.018523366563158061, 0.018626924680800294, 0.018730765977820418, 0.018834890393131298, 0.01893929786547921, 0.019043988333443895, 0.01914896173543873, 0.0192542180097105, 0.01935975709433968, 0.019465578927240379, 0.019571683446160226, 0.019678070588680707, 0.019784740292217107, 0.019891692494018287, 0.019998927131167077, 0.020106444140580049, 0.020214243459007741, 0.020322325023034604, 0.020430688769079053, 0.020539334633393469, 0.020648262552064256, 0.02075747246101195, 0.020866964295991164, 0.020976737992590755, 0.021086793486233546, 0.021197130712176881, 0.021307749605512072, 0.021418650101164893, 0.021529832133895588, 0.021641295638298474, 0.021753040548802505, 0.021865066799670985, 0.021977374325001797, 0.022089963058727291, 0.022202832934614447, 0.022315983886264878, 0.022429415847114664, 0.022543128750434793, 0.022657122529330831, 0.022771397116743253, 0.022885952445447222, 0.023000788448052756, 0.023115905057004893, 0.023231302204583415, 0.023346979822903069, 0.0234629378439139, 0.023579176199400698, 0.023695694820983382, 0.023812493640117116, 0.023929572588092085, 0.024046931596033827, 0.024164570594903068, 0.024282489515495831, 0.024400688288443384, 0.024519166844212514, 0.024637925113105197, 0.024756963025259149, 0.024876280510647386, 0.0249958774990785, 0.025115753920196715, 0.025235909703481663, 0.02535634477824894, 0.025477059073649722, 0.025598052518670811, 0.025719325042134866, 0.025840876572700511, 0.025962707038861887, 0.026084816368949493, 0.026207204491129454, 0.026329871333404031, 0.026452816823611447, 0.026576040889425945, 0.026699543458358233, 0.026823324457754705, 0.026947383814798331, 0.027071721456508102, 0.02719633730973936, 0.027321231301183857, 0.027446403357369697, 0.027571853404661395, 0.027697581369259927, 0.02782358717720268, 0.02794987075436367, 0.028076432026453657, 0.028203270919019807, 0.028330387357446141, 0.028457781266953308, 0.028585452572598702, 0.028713401199276567, 0.028841627071718112, 0.028970130114491344, 0.029098910252001176, 0.029227967408489652, 0.029357301508035616, 0.029486912474555371, 0.029616800231801965, 0.029746964703365852, 0.029877405812674618, 0.030008123482993088, 0.030139117637423329, 0.030270388198905041, 0.030401935090215049, 0.030533758233967756, 0.030665857552614972, 0.030798232968445916, 0.030930884403587822, 0.031063811780005113, 0.031197015019500007, 0.031330494043712576, 0.031464248774120462, 0.031598279132039164, 0.031732585038622252, 0.03186716641486087, 0.032002023181584349, 0.032137155259459871, 0.032272562568992635, 0.032408245030526195, 0.032544202564241953, 0.032680435090159665, 0.032816942528137105, 0.03295372479787062, 0.033090781818894521, 0.033228113510581914, 0.033365719792143977, 0.033503600582630577, 0.033641755800929929, 0.033780185365768767, 0.033918889195712787, 0.034057867209165926, 0.034197119324371084, 0.034336645459409842, 0.034476445532202415, 0.034616519460508144, 0.034756867161925165, 0.034897488553890521, 0.035038383553680219, 0.035179552078409393, 0.035320994045032195, 0.035462709370342127, 0.035604697970971544, 0.035746959763392261, 0.035889494663915333, 0.036032302588691112, 0.036175383453709409, 0.036318737174799443, 0.036462363667629949, 0.036606262847709126, 0.036750434630384798, 0.03689487893084431, 0.037039595664114966, 0.037184584745063642, 0.037329846088396901, 0.037475379608661263, 0.037621185220243103, 0.037767262837368643, 0.037913612374104455, 0.038060233744356631, 0.038207126861871721, 0.038354291640236238, 0.038501727992876822, 0.038649435833060686, 0.038797415073895059, 0.038945665628327464, 0.039094187409145997, 0.039242980328979105, 0.039392044300295637, 0.039541379235405294, 0.039690985046458072, 0.039840861645444758, 0.039991008944196771, 0.04014142685438632, 0.040292115287526464, 0.040443074154971115, 0.04059430336791503, 0.04074580283739393, 0.040897572474284605, 0.041049612189304752, 0.041201921893013582, 0.041354501495811047, 0.041507350907938556, 0.041660470039478703, 0.04181385880035543, 0.04196751710033414, 0.042121444849021639, 0.042275641955866139, 0.042430108330157423, 0.042584843881027012, 0.042739848517447721, 0.042895122148234655, 0.043050664682044215, 0.043206476027374596, 0.043362556092566173, 0.043518904785800894, 0.043675522015103052, 0.043832407688338626, 0.043989561713215886, 0.044146983997285116, 0.044304674447938897, 0.04446263297241182, 0.044620859477781216, 0.044779353870966432, 0.044938116058729216, 0.045097145947673944, 0.045256443444247285, 0.04541600845473881, 0.045575840885280494, 0.045735940641846939, 0.045896307630255706, 0.04605694175616698, 0.046217842925083685, 0.046379011042352092, 0.046540446013160985, 0.046702147742542333, 0.046864116135371225, 0.04702635109636577, 0.047188852530087366, 0.047351620340940648, 0.047514654433173376, 0.047677954710876935, 0.047841521077985893, 0.048005353438278331, 0.048169451695376009, 0.048333815752744091, 0.048498445513691479, 0.048663340881370643, 0.048828501758777842, 0.04899392804875341, 0.049159619653981135, 0.049325576476989041, 0.049491798420148891, 0.049658285385676626, 0.049825037275632145, 0.04999205399191986, 0.050159335436288033, 0.050326881510329269, 0.050494692115480522, 0.050662767153023036, 0.050831106524082847, 0.050999710129630116, 0.051168577870479626, 0.051337709647290897, 0.051507105360568073, 0.051676764910659867, 0.051846688197760227, 0.052016875121907447, 0.052187325582985, 0.052358039480721263, 0.052529016714689625, 0.052700257184308652, 0.052871760788841982, 0.053043527427398374, 0.053215556998932045, 0.053387849402242393, 0.053560404535974104, 0.053733222298617711, 0.053906302588508759, 0.054079645303828694, 0.054253250342604364, 0.054427117602708353, 0.054601246981859253, 0.054775638377621061, 0.054950291687403896, 0.055125206808463667, 0.055300383637902295, 0.055475822072667713, 0.0556515220095542, 0.055827483345201878, 0.056003705976097273, 0.056180189798573088, 0.056356934708808371, 0.056533940602828903, 0.056711207376506478, 0.056888734925559736, 0.05706652314555366, 0.057244571931900079, 0.057422881179857443, 0.057601450784531105, 0.05778028064087315, 0.057959370643682562, 0.058138720687605283, 0.058318330667134155, 0.058498200476609585, 0.058678330010218605, 0.058858719161995698, 0.059039367825822531, 0.059220275895428165, 0.059401443264388953, 0.059582869826129037, 0.059764555473919623, 0.059946500100879874, 0.060128703599976352, 0.060311165864023353, 0.060493886785683237, 0.060676866257465933, 0.060860104171729268, 0.061043600420679134, 0.061227354896369435, 0.061411367490701974, 0.061595638095427174, 0.061780166602143194, 0.061964952902296755, 0.062149996887182757, 0.062335298447944554, 0.062520857475574176, 0.062706673860911943, 0.062892747494646906, 0.063079078267316624, 0.063265666069307613, 0.063452510790854899, 0.063639612322042849, 0.063826970552804285, 0.064014585372921151, 0.06420245667202451, 0.064390584339594492, 0.064578968264960568, 0.064767608337301219, 0.064956504445644325, 0.06514565647886722, 0.06533506432569669, 0.065524727874708755, 0.065714647014329552, 0.065904821632834398, 0.066095251618348394, 0.066285936858846595, 0.066476877242153676, 0.066668072655944433, 0.066859522987743503, 0.067051228124925588, 0.067243187954715511, 0.067435402364188213, 0.067627871240268811, 0.067820594469732987, 0.068013571939206652, 0.068206803535166005, 0.068400289143937976, 0.068594028651699779, 0.068788021944479749, 0.068982268908156397, 0.06917676942845935, 0.06937152339096897, 0.069566530681116401, 0.069761791184183908, 0.06995730478530493, 0.070153071369463693, 0.070349090821495874, 0.070545363026088159, 0.070741887867778575, 0.070938665230956932, 0.071135694999863941, 0.071332977058592206, 0.071530511291085674, 0.071728297581140077, 0.071926335812402709, 0.072124625868373093, 0.072323167632401986, 0.072521960987692591, 0.072721005817299789, 0.072920302004130577, 0.073119849430944295, 0.073319647980352287, 0.073519697534818185, 0.073719997976658014, 0.073920549188040141, 0.074121351050985385, 0.074322403447367402, 0.074523706258912137, 0.074725259367198316, 0.07492706265365745, 0.075129115999573726, 0.075331419286084611, 0.075533972394180193, 0.075736775204703677, 0.075939827598351439, 0.07614312945567292, 0.076346680657070787, 0.07655048108280138, 0.076754530612973992, 0.076958829127551587, 0.077163376506350523, 0.077368172629040832, 0.077573217375146442, 0.077778510624044672, 0.077984052254966796, 0.078189842146997979, 0.078395880179077337, 0.078602166229997883, 0.078808700178407076, 0.079015481902806162, 0.079222511281550834, 0.079429788192851014, 0.079637312514770908, 0.079845084125229615, 0.080053102902000239, 0.08026136872271078, 0.080469881464843684, 0.080678641005736407, 0.080887647222580961, 0.081096899992424532, 0.081306399192169088, 0.081516144698571547, 0.081726136388244053, 0.081936374137653867, 0.082146857823123698, 0.082357587320831316, 0.082568562506809995, 0.082779783256948458, 0.082991249446990989, 0.083202960952537375, 0.083414917649043407, 0.083627119411820272, 0.083839566116035213, 0.084052257636711258, 0.084265193848727327, 0.084478374626818842, 0.084691799845576843, 0.084905469379448872, 0.085119383102738533, 0.085333540889605985, 0.085547942614067507, 0.085762588149996433, 0.085977477371122157, 0.086192610151030857, 0.08640798636316549, 0.086623605880825794, 0.086839468577168233, 0.087055574325206608, 0.08727192299781128, 0.087488514467709944, 0.087705348607487466, 0.087922425289585715, 0.088139744386304286, 0.088357305769799943, 0.088575109312086897, 0.088793154885036862, 0.089011442360379278, 0.089229971609701197, 0.089448742504447676, 0.089667754915921272, 0.089887008715282712, 0.090106503773550561, 0.090326239961601495, 0.090546217150170527, 0.090766435209850671, 0.090986894011093278, 0.0912075934242082, 0.091428533319363625, 0.091649713566586077, 0.091871134035761304, 0.09209279459663311, 0.092314695118804413, 0.0925368354717368, 0.092759215524750638, 0.092981835147025793, 0.093204694207600802, 0.093427792575373259, 0.093651130119100312, 0.09387470670739817, 0.094098522208742263, 0.094322576491468135, 0.094546869423770163, 0.094771400873702671, 0.094996170709179539, 0.095221178797974315, 0.095446425007720881, 0.095671909205912509, 0.095897631259902694, 0.096123591036904876, 0.096349788403992886, 0.096576223228100333, 0.096802895376021825, 0.09702980471441186, 0.097256951109785494, 0.097484334428518282, 0.097711954536846446, 0.097939811300867152, 0.098167904586537957, 0.098396234259677584, 0.098624800185965478, 0.098853602230942195, 0.099082640260009347, 0.09931191413842988, 0.099541423731327849, 0.099771168903688645, 0.1000011495203591, 0.10023136544604749, 0.10046181654532382, 0.10069250268261959, 0.10092342372222812, 0.10115457952830453, 0.10138596996486571, 0.10161759489579059, 0.10184945418482044, 0.10208154769555827, 0.1023138752914694, 0.1025464368358816, 0.1027792321919847, 0.10301226122283141, 0.10324552379133672, 0.10347901976027818, 0.10371274899229621, 0.10394671134989392, 0.10418090669543706, 0.10441533489115495, 0.10464999579913919, 0.10488488928134504, 0.10512001519959058, 0.10535537341555712, 0.10559096379078986, 0.10582678618669689, 0.10606284046454995, 0.10629912648548434, 0.10653564411049921, 0.10677239320045712, 0.10700937361608492, 0.10724658521797303, 0.10748402786657602, 0.10772170142221243, 0.10795960574506497, 0.10819774069518084, 0.10843610613247134, 0.10867470191671219, 0.10891352790754361, 0.10915258396447036, 0.10939186994686195, 0.10963138571395276, 0.1098711311248417, 0.11011110603849283, 0.11035131031373496, 0.11059174380926196, 0.1108324063836334, 0.11107329789527348, 0.1113144182024719, 0.11155576716338383, 0.11179734463602992, 0.11203915047829616, 0.11228118454793473, 0.11252344670256309, 0.11276593679966462, 0.11300865469658872, 0.11325160025055042, 0.1134947733186315, 0.11373817375777939, 0.11398180142480779, 0.11422565617639691, 0.1144697378690932, 0.1147140463593096, 0.11495858150332605, 0.11520334315728853, 0.11544833117721021, 0.11569354541897092, 0.11593898573831729, 0.11618465199086331, 0.11643054403208986, 0.11667666171734481, 0.1169230049018436, 0.11716957344066886, 0.11741636718877052, 0.11766338600096643, 0.11791062973194166, 0.11815809823624912, 0.11840579136830942, 0.11865370898241101, 0.11890185093271055, 0.11915021707323237, 0.11939880725786911, 0.11964762134038159, 0.1198966591743989, 0.12014592061341828, 0.12039540551080602, 0.12064511371979636, 0.12089504509349241, 0.12114519948486602, 0.12139557674675766, 0.12164617673187716, 0.12189699929280273, 0.12214804428198212, 0.12239931155173178, 0.12265080095423786, 0.12290251234155541, 0.12315444556560934, 0.1234066004781938, 0.12365897693097239, 0.12391157477547871, 0.12416439386311573, 0.12441743404515682, 0.12467069517274471, 0.12492417709689252, 0.12517787966848332, 0.12543180273827048, 0.12568594615687734, 0.1259403097747982, 0.12619489344239743, 0.12644969700990999, 0.12670472032744146, 0.12695996324496805, 0.12721542561233729, 0.12747110727926703, 0.12772700809534637, 0.12798312791003541, 0.12823946657266555, 0.12849602393243914, 0.12875279983843035, 0.12900979413958452, 0.12926700668471841, 0.12952443732252056, 0.12978208590155094, 0.1300399522702419, 0.13029803627689718, 0.13055633776969244, 0.1308148565966758, 0.13107359260576712, 0.13133254564475855, 0.1315917155613151, 0.13185110220297347, 0.13211070541714331, 0.13237052505110669, 0.13263056095201819, 0.13289081296690586, 0.13315128094266987, 0.13341196472608363, 0.13367286416379365, 0.13393397910231941, 0.13419530938805369, 0.13445685486726289, 0.1347186153860862, 0.13498059079053693, 0.13524278092650155, 0.13550518563974023, 0.1357678047758874, 0.13603063818045069, 0.13629368569881217, 0.13655694717622757, 0.13682042245782711, 0.13708411138861482, 0.13734801381346962, 0.13761212957714442, 0.13787645852426655, 0.13814100049933831, 0.13840575534673627, 0.13867072291071214, 0.13893590303539238, 0.13920129556477817, 0.139466900342746, 0.13973271721304747, 0.13999874601930917, 0.1402649866050335, 0.14053143881359781, 0.14079810248825519, 0.1410649774721342, 0.14133206360823913, 0.14159936073945023, 0.1418668687085235, 0.1421345873580907, 0.14240251653066005, 0.14267065606861556, 0.14293900581421759, 0.14320756560960324, 0.14347633529678538, 0.14374531471765384, 0.14401450371397506, 0.14428390212739173, 0.14455350979942416, 0.14482332657146885, 0.14509335228479958, 0.14536358678056727, 0.14563402989979979, 0.1459046814834023, 0.14617554137215782, 0.14644660940672627, 0.1467178854276453, 0.14698936927533024, 0.14726106079007389, 0.14753295981204756, 0.14780506618129985, 0.14807737973775759, 0.14834990032122575, 0.14862262777138746, 0.14889556192780407, 0.14916870262991577, 0.14944204971704073, 0.14971560302837589, 0.14998936240299693, 0.15026332767985806, 0.15053749869779293, 0.1508118752955136, 0.15108645731161141, 0.1513612445845568, 0.15163623695269957, 0.15191143425426851, 0.15218683632737257, 0.15246244300999962, 0.15273825414001729, 0.15301426955517311, 0.15329048909309406, 0.15356691259128769, 0.15384353988714095, 0.15412037081792118, 0.15439740522077589, 0.15467464293273281, 0.15495208379070002, 0.15522972763146659, 0.15550757429170148, 0.15578562360795484, 0.15606387541665734, 0.15634232955412042, 0.15662098585653705, 0.15689984415998071, 0.15717890430040632, 0.15745816611364988, 0.15773762943542896, 0.15801729410134224, 0.15829715994687066, 0.15857722680737601, 0.15885749451810227, 0.1591379629141752, 0.15941863183060229, 0.15969950110227349, 0.15998057056396053, 0.16026184005031752, 0.16054330939588085, 0.16082497843506938, 0.16110684700218425, 0.16138891493140983, 0.16167118205681258, 0.16195364821234209, 0.1622363132318308, 0.16251917694899398, 0.16280223919743048, 0.16308549981062198, 0.16336895862193357, 0.16365261546461363, 0.16393647017179425, 0.16422052257649078, 0.16450477251160289, 0.16478921980991351, 0.16507386430408955, 0.16535870582668211, 0.16564374421012595, 0.16592897928674077, 0.1662144108887299, 0.16650003884818132, 0.16678586299706744, 0.16707188316724531, 0.16735809919045641, 0.1676445108983276, 0.16793111812237005, 0.16821792069398017, 0.16850491844443938, 0.16879211120491411, 0.16907949880645656, 0.16936708108000392, 0.1696548578563789, 0.16994282896628987, 0.17023099424033078, 0.17051935350898134, 0.17080790660260747, 0.17109665335146074, 0.17138559358567879, 0.17167472713528559, 0.17196405383019114, 0.17225357350019233, 0.17254328597497198, 0.17283319108409978, 0.17312328865703203, 0.17341357852311173, 0.17370406051156873, 0.17399473445152025, 0.17428560017197015, 0.17457665750180962, 0.17486790626981713, 0.17515934630465835, 0.17545097743488702, 0.17574279948894378, 0.17603481229515738, 0.17632701568174403, 0.17661940947680815, 0.1769119935083418, 0.17720476760422565, 0.17749773159222804, 0.17779088530000592, 0.17808422855510436, 0.17837776118495707, 0.17867148301688657, 0.17896539387810378, 0.17925949359570847, 0.17955378199668942, 0.17984825890792427, 0.18014292415617972, 0.18043777756811213, 0.18073281897026666, 0.18102804818907803, 0.18132346505087055, 0.18161906938185784, 0.18191486100814391, 0.18221083975572194, 0.18250700545047532, 0.18280335791817737, 0.18309989698449153, 0.18339662247497135, 0.18369353421506124, 0.18399063203009552, 0.18428791574529918, 0.18458538518578782, 0.18488304017656776, 0.18518088054253651, 0.18547890610848206, 0.1857771166990837, 0.18607551213891182, 0.18637409225242807, 0.18667285686398527, 0.18697180579782824, 0.18727093887809287, 0.18757025592880688, 0.18786975677388978, 0.18816944123715268, 0.18846930914229937, 0.18876936031292502, 0.18906959457251737, 0.18937001174445628, 0.1896706116520141, 0.1899713941183554, 0.19027235896653799, 0.1905735060195119, 0.19087483510011999, 0.19117634603109812, 0.19147803863507507, 0.19177991273457318, 0.19208196815200751, 0.19238420470968665, 0.19268662222981259, 0.19298922053448092, 0.19329199944568065, 0.19359495878529515, 0.19389809837510102, 0.1942014180367691, 0.19450491759186422, 0.19480859686184526, 0.19511245566806579, 0.19541649383177345, 0.19572071117411033, 0.19602510751611324, 0.1963296826787137, 0.19663443648273771, 0.19693936874890694, 0.19724447929783728, 0.19754976795004014, 0.19785523452592207, 0.19816087884578476, 0.19846670072982592, 0.19877269999813812, 0.19907887647071004, 0.1993852299674258, 0.19969176030806568, 0.19999846731230547, 0.20030535079971773, 0.2006124105897707, 0.20091964650182892, 0.20122705835515348, 0.20153464596890175, 0.20184240916212814, 0.20215034775378338, 0.20245846156271508, 0.20276675040766784, 0.20307521410728335, 0.20338385248010005, 0.20369266534455444, 0.20400165251897956, 0.20431081382160632, 0.20462014907056297, 0.20492965808387553, 0.20523934067946803, 0.20554919667516214, 0.20585922588867739, 0.20616942813763173, 0.20647980323954113, 0.2067903510118197, 0.20710107127178057, 0.20741196383663485, 0.20772302852349245, 0.20803426514936196, 0.2083456735311508, 0.20865725348566577, 0.20896900482961228, 0.20928092737959492, 0.20959302095211785, 0.20990528536358433, 0.21021772043029713, 0.21053032596845911, 0.21084310179417226, 0.21115604772343871, 0.21146916357216033, 0.21178244915613909, 0.21209590429107733, 0.21240952879257746, 0.21272332247614217, 0.21303728515717474, 0.21335141665097901, 0.21366571677275936, 0.21398018533762148, 0.21429482216057139, 0.21460962705651643, 0.21492459984026496, 0.21523974032652637, 0.21555504832991207, 0.21587052366493426, 0.21618616614600694, 0.21650197558744577, 0.21681795180346819, 0.21713409460819338, 0.21745040381564301, 0.21776687923974031, 0.21808352069431103, 0.21840032799308307, 0.21871730094968672, 0.21903443937765527, 0.21935174309042427, 0.21966921190133204, 0.21998684562361992, 0.2203046440704321, 0.22062260705481579, 0.22094073438972195, 0.22125902588800428, 0.22157748136242006, 0.22189610062563014, 0.22221488349019902, 0.22253382976859482, 0.22285293927319, 0.2231722118162604, 0.22349164720998632, 0.22381124526645213, 0.22413100579764628, 0.22445092861546229, 0.22477101353169765, 0.2250912603580546, 0.22541166890614023, 0.22573223898746647, 0.22605297041344991, 0.22637386299541296, 0.22669491654458263, 0.22701613087209133, 0.22733750578897693, 0.22765904110618268, 0.22798073663455809, 0.22830259218485766, 0.22862460756774211, 0.22894678259377815, 0.22926911707343839, 0.22959161081710167, 0.22991426363505357, 0.23023707533748561, 0.2305600457344959, 0.23088317463608932, 0.23120646185217725, 0.23152990719257854, 0.23185351046701846, 0.23217727148512957, 0.23250119005645153, 0.23282526599043141, 0.23314949909642352, 0.23347388918369028, 0.2337984360614011, 0.23412313953863345, 0.23444799942437267, 0.23477301552751179, 0.2350981876568527, 0.2354235156211047, 0.23574899922888587, 0.23607463828872244, 0.23640043260904947, 0.23672638199821028, 0.23705248626445768, 0.2373787452159527, 0.23770515866076564, 0.23803172640687587, 0.23835844826217178, 0.2386853240344517, 0.23901235353142286, 0.23933953656070228, 0.23966687292981653, 0.23999436244620215, 0.24032200491720518, 0.24064980015008253, 0.24097774795200039, 0.24130584813003558, 0.24163410049117517, 0.24196250484231663, 0.24229106099026854, 0.24261976874174945, 0.24294862790338922, 0.24327763828172838, 0.24360679968321863, 0.24393611191422265, 0.24426557478101485, 0.24459518808978054, 0.24492495164661671, 0.24525486525753198, 0.24558492872844645, 0.2459151418651927, 0.24624550447351462, 0.2465760163590684, 0.24690667732742244, 0.24723748718405741, 0.2475684457343662, 0.24789955278365483, 0.24823080813714127, 0.24856221159995662, 0.24889376297714472, 0.24922546207366231, 0.24955730869437964, 0.24988930264407971, 0.25022144372745914, 0.25055373174912776, 0.25088616651360923, 0.25121874782534043, 0.25155147548867274, 0.25188434930787096, 0.25221736908711384, 0.25255053463049454, 0.25288384574202011, 0.25321730222561262, 0.25355090388510804, 0.25388465052425702, 0.25421854194672511, 0.2545525779560926, 0.25488675835585439, 0.25522108294942125, 0.25555555154011844, 0.25589016393118669, 0.25622491992578211, 0.25655981932697625, 0.25689486193775679, 0.25723004756102658, 0.2575653759996045, 0.25790084705622562, 0.25823646053354077, 0.25857221623411719, 0.25890811396043867, 0.25924415351490515, 0.2595803346998331, 0.25991665731745595, 0.2602531211699235, 0.26058972605930303, 0.2609264717875785, 0.26126335815665103, 0.26160038496833904, 0.2619375520243783, 0.26227485912642201, 0.26261230607604147, 0.26294989267472502, 0.26328761872387929, 0.26362548402482872, 0.26396348837881561, 0.26430163158700115, 0.26463991345046423, 0.26497833377020225, 0.26531689234713129, 0.26565558898208619, 0.26599442347582003, 0.26633339562900576, 0.26667250524223457, 0.26701175211601702, 0.26735113605078281, 0.26769065684688104, 0.26803031430458069, 0.26837010822406993, 0.26871003840545665, 0.26905010464876872, 0.26939030675395392, 0.26973064452087991, 0.27007111774933523, 0.27041172623902798, 0.27075246978958695, 0.27109334820056152, 0.27143436127142145, 0.27177550880155799, 0.27211679059028271, 0.27245820643682817, 0.27279975614034824, 0.2731414394999182, 0.27348325631453418, 0.27382520638311458, 0.27416728950449876, 0.27450950547744812, 0.27485185410064578, 0.27519433517269665, 0.27553694849212834, 0.27587969385739008, 0.27622257106685355, 0.27656557991881303, 0.2769087202114851, 0.27725199174300907, 0.27759539431144753, 0.27793892771478546, 0.27828259175093084, 0.27862638621771507, 0.27897031091289259, 0.27931436563414164, 0.27965855017906355, 0.2800028643451834, 0.28034730792995011, 0.28069188073073631, 0.28103658254483854, 0.28138141316947796, 0.28172637240179943, 0.28207146003887229, 0.28241667587769048, 0.28276201971517212, 0.28310749134816071, 0.28345309057342405, 0.28379881718765498, 0.28414467098747143, 0.28449065176941657, 0.28483675932995867, 0.28518299346549181, 0.28552935397233525, 0.2858758406467341, 0.28622245328485907, 0.2865691916828067, 0.28691605563660016, 0.28726304494218813, 0.28761015939544565, 0.2879573987921743, 0.28830476292810214, 0.28865225159888347, 0.28899986460010019, 0.28934760172726021, 0.28969546277579883, 0.29004344754107825, 0.29039155581838794, 0.29073978740294515, 0.29108814208989386, 0.29143661967430612, 0.29178521995118151, 0.29213394271544735, 0.29248278776195924, 0.29283175488550045, 0.29318084388078275, 0.29353005454244607, 0.29387938666505853, 0.29422884004311745, 0.2945784144710481, 0.29492810974320488, 0.29527792565387123, 0.29562786199725932, 0.29597791856751066, 0.29632809515869607, 0.29667839156481546, 0.29702880757979877, 0.29737934299750513, 0.29772999761172347, 0.29808077121617299, 0.29843166360450246, 0.29878267457029078, 0.29913380390704758, 0.29948505140821213, 0.29983641686715501, 0.30018790007717666, 0.30053950083150854, 0.30089121892331322, 0.30124305414568386, 0.30159500629164482, 0.30194707515415187, 0.30229926052609191, 0.30265156220028322, 0.30300397996947603, 0.30335651362635174, 0.30370916296352424, 0.30406192777353891, 0.30441480784887309, 0.30476780298193673, 0.30512091296507182, 0.30547413759055281, 0.3058274766505869, 0.30618092993731372, 0.30653449724280568, 0.30688817835906856, 0.30724197307804058, 0.30759588119159359, 0.30794990249153253, 0.30830403676959567, 0.30865828381745514, 0.30901264342671642, 0.30936711538891881, 0.30972169949553574, 0.3100763955379745, 0.31043120330757634, 0.31078612259561722, 0.31114115319330715, 0.31149629489179087, 0.31185154748214766, 0.31220691075539142, 0.3125623845024712, 0.31291796851427106, 0.31327366258160982, 0.31362946649524215, 0.31398538004585758, 0.3143414030240812, 0.31469753522047422, 0.31505377642553289, 0.31541012642969002, 0.31576658502331389, 0.31612315199670904, 0.31647982714011647, 0.31683661024371323, 0.31719350109761307, 0.31755049949186637, 0.31790760521646011, 0.31826481806131812, 0.31862213781630144, 0.31897956427120788, 0.31933709721577286, 0.31969473643966895, 0.32005248173250589, 0.32041033288383181, 0.32076828968313176, 0.32112635191982908, 0.32148451938328504, 0.32184279186279885, 0.3222011691476081, 0.32255965102688866, 0.32291823728975477, 0.32327692772525962, 0.32363572212239466, 0.32399462027009041, 0.32435362195721651, 0.32471272697258124, 0.32507193510493254, 0.32543124614295754, 0.32579065987528277, 0.32615017609047431, 0.32650979457703821, 0.32686951512342, 0.32722933751800548, 0.32758926154912038, 0.32794928700503057, 0.32830941367394251, 0.32866964134400289, 0.32902996980329891, 0.32939039883985888, 0.32975092824165153, 0.33011155779658657, 0.33047228729251521, 0.33083311651722941, 0.33119404525846274, 0.33155507330389, 0.33191620044112768, 0.33227742645773423, 0.33263875114120944, 0.33300017427899531, 0.33336169565847606, 0.33372331506697794, 0.33408503229176945, 0.33444684712006184, 0.33480875933900855, 0.33517076873570628, 0.33553287509719398, 0.33589507821045372, 0.33625737786241106, 0.33661977383993413, 0.33698226592983488, 0.33734485391886859, 0.33770753759373395, 0.33807031674107357, 0.33843319114747389, 0.33879616059946505, 0.33915922488352174, 0.33952238378606248, 0.33988563709345004, 0.34024898459199215, 0.34061242606794084, 0.34097596130749253, 0.34133959009678916, 0.34170331222191713, 0.34206712746890799, 0.34243103562373883, 0.34279503647233167, 0.3431591298005543, 0.34352331539421999, 0.34388759303908756, 0.3442519625208621, 0.34461642362519429, 0.34498097613768108, 0.34534561984386569, 0.34571035452923754, 0.34607517997923254, 0.34644009597923353, 0.34680510231456951, 0.34717019877051691, 0.34753538513229887, 0.34790066118508545, 0.34826602671399437, 0.34863148150409051, 0.34899702534038596, 0.34936265800784105, 0.34972837929136336, 0.35009418897580835, 0.35046008684597985, 0.35082607268662924, 0.35119214628245687, 0.35155830741811089, 0.35192455587818805, 0.35229089144723402, 0.35265731390974286, 0.35302382305015767, 0.35339041865287069, 0.35375710050222314, 0.35412386838250537, 0.35449072207795751, 0.35485766137276886, 0.35522468605107849, 0.35559179589697532, 0.35595899069449788, 0.3563262702276353, 0.35669363428032619, 0.35706108263645969, 0.35742861507987567, 0.35779623139436412, 0.35816393136366576, 0.35853171477147239, 0.3588995814014263, 0.35926753103712106, 0.35963556346210146, 0.36000367845986336, 0.36037187581385444, 0.3607401553074735, 0.36110851672407118, 0.36147695984695005, 0.36184548445936454, 0.3622140903445209, 0.36258277728557808, 0.36295154506564686, 0.36332039346779066, 0.36368932227502559, 0.36405833127032011, 0.36442742023659602, 0.36479658895672762, 0.36516583721354245, 0.3655351647898214, 0.36590457146829847, 0.36627405703166116, 0.36664362126255085, 0.36701326394356226, 0.36738298485724408, 0.36775278378609921, 0.3681226605125843, 0.36849261481911055, 0.36886264648804323, 0.36923275530170224, 0.36960294104236224, 0.36997320349225249, 0.37034354243355688, 0.37071395764841486, 0.37108444891892056, 0.37145501602712344, 0.3718256587550286, 0.37219637688459628, 0.37256717019774277, 0.37293803847633977, 0.37330898150221492, 0.37367999905715227, 0.37405109092289157, 0.37442225688112907, 0.37479349671351742, 0.37516481020166581, 0.37553619712713993, 0.37590765727146269, 0.37627919041611335, 0.37665079634252879, 0.37702247483210277, 0.37739422566618619, 0.37776604862608798, 0.378137943493074, 0.37850991004836809, 0.37888194807315201, 0.37925405734856543, 0.3796262376557058, 0.37999848877562931, 0.38037081048935001, 0.38074320257784078, 0.38111566482203296, 0.38148819700281639, 0.38186079890104024, 0.38223347029751231, 0.38260621097299952, 0.38297902070822831, 0.38335189928388425, 0.38372484648061239, 0.38409786207901764, 0.3844709458596644, 0.38484409760307731, 0.38521731708974061, 0.38559060410009888, 0.38596395841455716, 0.38633737981348065, 0.38671086807719501, 0.38708442298598694, 0.38745804432010367, 0.38783173185975323, 0.38820548538510502, 0.38857930467628943, 0.38895318951339825, 0.38932713967648463, 0.38970115494556323, 0.39007523510061071, 0.39044937992156514, 0.39082358918832683, 0.39119786268075823, 0.39157220017868377, 0.39194660146189025, 0.39232106631012731, 0.39269559450310659, 0.39307018582050313, 0.39344484004195435, 0.39381955694706078, 0.39419433631538625, 0.39456917792645763, 0.39494408155976518, 0.39531904699476295, 0.39569407401086831, 0.39606916238746248, 0.39644431190389079, 0.39681952233946222, 0.39719479347345038, 0.39757012508509282, 0.39794551695359154, 0.39832096885811336, 0.3986964805777895, 0.39907205189171596, 0.39944768257895408, 0.39982337241852983, 0.40019912118943451, 0.400574928670625, 0.40095079464102318, 0.40132671887951704, 0.40170270116495993, 0.40207874127617105, 0.4024548389919359, 0.40283099409100576, 0.40320720635209817, 0.4035834755538974, 0.40395980147505384, 0.40433618389418458, 0.40471262258987367, 0.40508911734067177, 0.40546566792509692, 0.40584227412163398, 0.40621893570873518, 0.40659565246482038, 0.40697242416827673, 0.40734925059745908, 0.40772613153069026, 0.40810306674626085, 0.40848005602242954, 0.40885709913742341, 0.40923419586943749, 0.40961134599663573, 0.40998854929715028, 0.41036580554908209, 0.41074311453050127, 0.41112047601944646, 0.41149788979392565, 0.41187535563191607, 0.4122528733113644, 0.41263044261018639, 0.41300806330626816, 0.4133857351774648, 0.41376345800160202, 0.41414123155647509, 0.41451905561984936, 0.41489692996946098, 0.41527485438301609, 0.41565282863819131, 0.41603085251263444, 0.4164089257839636, 0.41678704822976798, 0.417165219627608, 0.41754343975501501, 0.41792170838949211, 0.41830002530851346, 0.4186783902895248, 0.41905680310994409, 0.41943526354716065, 0.41981377137853587, 0.42019232638140352, 0.42057092833306936, 0.42094957701081148, 0.4213282721918809, 0.42170701365350077, 0.42208580117286743, 0.42246463452714977, 0.42284351349348992, 0.42322243784900332, 0.42360140737077834, 0.42398042183587697, 0.42435948102133492, 0.42473858470416137, 0.42511773266133923, 0.4254969246698258, 0.42587616050655197, 0.42625543994842324, 0.42663476277231915, 0.42701412875509387, 0.4273935376735763, 0.42777298930456986, 0.42815248342485279, 0.42853201981117872, 0.42891159824027603, 0.42929121848884849, 0.42967088033357542, 0.43005058355111137, 0.43043032791808689, 0.43081011321110813, 0.43118993920675697, 0.43156980568159187, 0.43194971241214697, 0.43232965917493288, 0.43270964574643694, 0.4330896719031227, 0.43346973742143047, 0.43384984207777771, 0.43422998564855841, 0.43461016791014417, 0.4349903886388834, 0.43537064761110189, 0.43575094460310343, 0.43613127939116891, 0.43651165175155704, 0.43689206146050485, 0.43727250829422692, 0.43765299202891617, 0.43803351244074396, 0.43841406930585974, 0.43879466240039189, 0.43917529150044732, 0.43955595638211142, 0.43993665682144928, 0.44031739259450436, 0.44069816347729962, 0.44107896924583756, 0.44145980967609977, 0.44184068454404762, 0.44222159362562241, 0.44260253669674493, 0.44298351353331644, 0.44336452391121789, 0.44374556760631062, 0.44412664439443672, 0.44450775405141835, 0.44488889635305845, 0.44527007107514105, 0.44565127799343074, 0.44603251688367318, 0.44641378752159561, 0.44679508968290615, 0.4471764231432947, 0.44755778767843257, 0.44793918306397268, 0.44832060907555021, 0.44870206548878194, 0.44908355207926676, 0.44946506862258612, 0.44984661489430366, 0.45022819066996533, 0.45060979572510024, 0.45099142983521967, 0.45137309277581839, 0.45175478432237376, 0.4521365042503464, 0.4525182523351805, 0.45290002835230347, 0.45328183207712608, 0.45366366328504337, 0.4540455217514337, 0.45442740725165948, 0.45480931956106757, 0.45519125845498859, 0.45557322370873771, 0.45595521509761483, 0.45633723239690394, 0.45671927538187446, 0.45710134382778012, 0.45748343750985987, 0.45786555620333802, 0.45824769968342383, 0.45862986772531217, 0.45901206010418349, 0.45939427659520388, 0.45977651697352501, 0.46015878101428498, 0.46054106849260751, 0.46092337918360293, 0.46130571286236755, 0.46168806930398426, 0.46207044828352284, 0.46245284957603944, 0.46283527295657712, 0.46321771820016633, 0.46360018508182427, 0.46398267337655535, 0.46436518285935185, 0.46474771330519304, 0.46513026448904637, 0.4655128361858667, 0.46589542817059681, 0.46627804021816799, 0.46666067210349926, 0.46704332360149808, 0.46742599448706063, 0.46780868453507135, 0.46819139352040345, 0.46857412121791936, 0.46895686740246995, 0.46933963184889571, 0.46972241433202616, 0.47010521462668003, 0.47048803250766608, 0.47087086774978221, 0.47125372012781624, 0.47163658941654618, 0.4720194753907398, 0.47240237782515504, 0.47278529649454049, 0.47316823117363471, 0.47355118163716736, 0.47393414765985842, 0.4743171290164187, 0.47470012548155038, 0.47508313682994641, 0.47546616283629101, 0.47584920327525998, 0.47623225792152041, 0.4766153265497311, 0.47699840893454276, 0.47738150485059772, 0.47776461407253068, 0.47814773637496832, 0.4785308715325296, 0.47891401931982608, 0.47929717951146172, 0.47968035188203312, 0.48006353620613013, 0.48044673225833512, 0.48082993981322364, 0.48121315864536479, 0.48159638852932057, 0.48197962923964693, 0.4823628805508931, 0.48274614223760209, 0.48312941407431126, 0.4835126958355514, 0.48389598729584771, 0.48427928822971988, 0.48466259841168174, 0.48504591761624172, 0.48542924561790318, 0.48581258219116391, 0.48619592711051718, 0.48657928015045082, 0.48696264108544807, 0.48734600968998776, 0.48772938573854391, 0.4881127690055862, 0.48849615926558038, 0.48887955629298763, 0.48926295986226526, 0.48964636974786713, 0.49002978572424277, 0.49041320756583873, 0.49079663504709764, 0.49118006794245894, 0.49156350602635918, 0.49194694907323144, 0.49233039685750596, 0.49271384915361049, 0.49309730573596988, 0.49348076637900634, 0.4938642308571401, 0.49424769894478865, 0.49463117041636778, 0.49501464504629106, 0.49539812260897009, 0.49578160287881512, 0.49616508563023454, 0.49654857063763513, 0.49693205767542281, 0.49731554651800192, 0.49769903693977574, 0.49808252871514691, 0.498466021618517, 0.49884951542428713, 0.49923300990685771, 0.49961650484062864, 0.5, 0.50038349515937142, 0.50076699009314241, 0.50115048457571298, 0.50153397838148306, 0.50191747128485309, 0.50230096306022431, 0.50268445348199819, 0.5030679423245773, 0.50345142936236498, 0.50383491436976557, 0.50421839712118488, 0.50460187739103002, 0.504985354953709, 0.50536882958363227, 0.50575230105521141, 0.50613576914285996, 0.50651923362099371, 0.50690269426403023, 0.50728615084638951, 0.5076696031424941, 0.50805305092676867, 0.50843649397364088, 0.50881993205754106, 0.50920336495290242, 0.50958679243416138, 0.50997021427575728, 0.51035363025213298, 0.5107370401377348, 0.51112044370701248, 0.51150384073441968, 0.5118872309944138, 0.51227061426145615, 0.51265399031001235, 0.51303735891455204, 0.51342071984954929, 0.51380407288948293, 0.51418741780883614, 0.51457075438209687, 0.51495408238375828, 0.51533740158831831, 0.51572071177028023, 0.5161040127041524, 0.51648730416444866, 0.5168705859256888, 0.51725385776239796, 0.51763711944910695, 0.51802037076035312, 0.51840361147067948, 0.51878684135463526, 0.51917006018677636, 0.51955326774166488, 0.51993646379386993, 0.52031964811796694, 0.52070282048853833, 0.52108598068017398, 0.52146912846747051, 0.52185226362503168, 0.52223538592746932, 0.5226184951494024, 0.52300159106545729, 0.52338467345026896, 0.52376774207847965, 0.52415079672474008, 0.52453383716370905, 0.52491686317005359, 0.52529987451844962, 0.52568287098358135, 0.52606585234014169, 0.52644881836283275, 0.52683176882636529, 0.52721470350545963, 0.52759762217484507, 0.52798052460926026, 0.52836341058345393, 0.52874627987218381, 0.52912913225021785, 0.52951196749233398, 0.52989478537332002, 0.53027758566797389, 0.53066036815110429, 0.53104313259753011, 0.5314258787820807, 0.5318086064795966, 0.5321913154649287, 0.53257400551293943, 0.53295667639850197, 0.53333932789650074, 0.53372195978183201, 0.53410457182940319, 0.53448716381413341, 0.53486973551095374, 0.53525228669480696, 0.5356348171406482, 0.5360173266234447, 0.53639981491817579, 0.53678228179983378, 0.53716472704342288, 0.53754715042396062, 0.53792955171647727, 0.53831193069601579, 0.53869428713763257, 0.53907662081639718, 0.53945893150739255, 0.53984121898571502, 0.54022348302647505, 0.54060572340479618, 0.54098793989581651, 0.54137013227468789, 0.54175230031657617, 0.54213444379666209, 0.54251656249014024, 0.54289865617222, 0.5432807246181256, 0.54366276760309606, 0.54404478490238528, 0.54442677629126235, 0.54480874154501147, 0.54519068043893248, 0.54557259274834058, 0.54595447824856635, 0.54633633671495663, 0.54671816792287398, 0.54709997164769664, 0.5474817476648195, 0.54786349574965365, 0.5482452156776263, 0.54862690722418173, 0.54900857016478044, 0.54939020427489982, 0.54977180933003467, 0.55015338510569645, 0.55053493137741394, 0.55091644792073335, 0.55129793451121811, 0.55167939092444984, 0.55206081693602738, 0.55244221232156754, 0.55282357685670536, 0.55320491031709396, 0.55358621247840445, 0.55396748311632693, 0.55434872200656937, 0.55472992892485906, 0.55511110364694161, 0.55549224594858171, 0.55587335560556328, 0.55625443239368944, 0.55663547608878217, 0.55701648646668367, 0.55739746330325513, 0.55777840637437759, 0.55815931545595243, 0.55854019032390023, 0.55892103075416255, 0.55930183652270038, 0.55968260740549569, 0.56006334317855078, 0.56044404361788858, 0.56082470849955279, 0.56120533759960811, 0.56158593069414031, 0.56196648755925604, 0.56234700797108383, 0.56272749170577308, 0.56310793853949526, 0.56348834824844296, 0.56386872060883109, 0.56424905539689663, 0.56462935238889811, 0.56500961136111671, 0.56538983208985594, 0.56577001435144159, 0.56615015792222234, 0.56653026257856953, 0.56691032809687736, 0.56729035425356311, 0.56767034082506718, 0.56805028758785303, 0.56843019431840824, 0.56881006079324314, 0.56918988678889193, 0.56956967208191311, 0.56994941644888863, 0.57032911966642463, 0.57070878151115156, 0.57108840175972397, 0.57146798018882139, 0.57184751657514732, 0.57222701069543025, 0.57260646232642376, 0.57298587124490619, 0.57336523722768085, 0.57374456005157681, 0.57412383949344814, 0.5745030753301742, 0.57488226733866077, 0.57526141529583863, 0.57564051897866508, 0.57601957816412308, 0.57639859262922166, 0.57677756215099674, 0.57715648650651008, 0.57753536547285023, 0.57791419882713269, 0.57829298634649928, 0.57867172780811915, 0.57905042298918852, 0.5794290716669307, 0.57980767361859653, 0.58018622862146418, 0.58056473645283935, 0.58094319689005591, 0.5813216097104752, 0.5816999746914866, 0.58207829161050795, 0.58245656024498504, 0.58283478037239211, 0.58321295177023214, 0.5835910742160364, 0.58396914748736561, 0.58434717136180869, 0.58472514561698397, 0.58510307003053907, 0.58548094438015064, 0.58585876844352502, 0.58623654199839803, 0.5866142648225352, 0.58699193669373195, 0.58736955738981367, 0.58774712668863571, 0.58812464436808398, 0.58850211020607446, 0.58887952398055354, 0.58925688546949884, 0.58963419445091791, 0.59001145070284977, 0.59038865400336438, 0.59076580413056257, 0.5911429008625767, 0.59151994397757046, 0.59189693325373915, 0.59227386846930985, 0.59265074940254103, 0.59302757583172327, 0.59340434753517968, 0.59378106429126487, 0.59415772587836602, 0.59453433207490314, 0.59491088265932834, 0.59528737741012638, 0.59566381610581554, 0.59604019852494616, 0.5964165244461026, 0.59679279364790183, 0.59716900590899424, 0.59754516100806421, 0.59792125872382895, 0.59829729883504013, 0.59867328112048301, 0.59904920535897688, 0.59942507132937506, 0.59980087881056554, 0.60017662758147017, 0.60055231742104598, 0.60092794810828409, 0.6013035194222105, 0.6016790311418867, 0.60205448304640852, 0.60242987491490718, 0.60280520652654968, 0.60318047766053784, 0.60355568809610927, 0.60393083761253763, 0.60430592598913169, 0.60468095300523705, 0.60505591844023487, 0.60543082207354237, 0.60580566368461386, 0.60618044305293928, 0.60655515995804565, 0.60692981417949687, 0.60730440549689346, 0.6076789336898728, 0.6080533985381098, 0.60842779982131634, 0.60880213731924182, 0.60917641081167317, 0.60955062007843486, 0.6099247648993894, 0.61029884505443688, 0.61067286032351542, 0.61104681048660181, 0.61142069532371068, 0.61179451461489498, 0.61216826814024683, 0.61254195567989633, 0.61291557701401311, 0.6132891319228051, 0.6136626201865194, 0.61403604158544289, 0.61440939589990118, 0.61478268291025939, 0.61515590239692275, 0.61552905414033565, 0.61590213792098236, 0.61627515351938766, 0.61664810071611575, 0.61702097929177169, 0.61739378902700048, 0.61776652970248769, 0.61813920109895981, 0.61851180299718367, 0.61888433517796715, 0.61925679742215922, 0.61962918951065005, 0.62000151122437075, 0.6203737623442942, 0.62074594265143468, 0.62111805192684799, 0.62149008995163202, 0.62186205650692605, 0.62223395137391213, 0.62260577433381381, 0.62297752516789728, 0.62334920365747126, 0.62372080958388676, 0.62409234272853742, 0.62446380287286019, 0.6248351897983343, 0.62520650328648264, 0.62557774311887104, 0.62594890907710843, 0.62632000094284779, 0.62669101849778519, 0.62706196152366034, 0.62743282980225734, 0.62780362311540383, 0.6281743412449714, 0.62854498397287661, 0.62891555108107944, 0.62928604235158514, 0.62965645756644317, 0.63002679650774751, 0.63039705895763776, 0.63076724469829781, 0.63113735351195677, 0.63150738518088956, 0.63187733948741576, 0.63224721621390079, 0.63261701514275592, 0.63298673605643774, 0.63335637873744921, 0.63372594296833884, 0.63409542853170153, 0.63446483521017871, 0.63483416278645755, 0.63520341104327238, 0.63557257976340398, 0.63594166872967994, 0.63631067772497452, 0.63667960653220934, 0.63704845493435314, 0.63741722271442192, 0.6377859096554791, 0.63815451554063551, 0.63852304015304995, 0.63889148327592893, 0.6392598446925265, 0.63962812418614567, 0.63999632154013675, 0.64036443653789865, 0.64073246896287905, 0.64110041859857381, 0.64146828522852772, 0.64183606863633424, 0.64220376860563588, 0.64257138492012433, 0.64293891736354036, 0.64330636571967392, 0.64367372977236481, 0.64404100930550212, 0.6444082041030248, 0.64477531394892162, 0.64514233862723114, 0.6455092779220426, 0.64587613161749469, 0.64624289949777691, 0.64660958134712931, 0.64697617694984233, 0.64734268609025714, 0.64770910855276598, 0.64807544412181195, 0.64844169258188911, 0.64880785371754313, 0.64917392731337076, 0.64953991315402027, 0.64990581102419176, 0.65027162070863676, 0.65063734199215895, 0.6510029746596141, 0.6513685184959096, 0.65173397328600569, 0.65209933881491466, 0.65246461486770113, 0.65282980122948309, 0.65319489768543049, 0.65355990402076658, 0.65392482002076746, 0.65428964547076252, 0.65465438015613442, 0.65501902386231903, 0.65538357637480571, 0.65574803747913801, 0.65611240696091255, 0.65647668460578013, 0.6568408701994457, 0.65720496352766844, 0.65756896437626122, 0.65793287253109201, 0.65829668777808292, 0.65866040990321095, 0.65902403869250747, 0.65938757393205927, 0.65975101540800785, 0.66011436290655001, 0.66047761621393763, 0.66084077511647832, 0.66120383940053495, 0.66156680885252617, 0.66192968325892654, 0.66229246240626605, 0.66265514608113152, 0.66301773407016518, 0.66338022616006587, 0.66374262213758906, 0.66410492178954628, 0.66446712490280613, 0.66482923126429383, 0.66519124066099145, 0.66555315287993821, 0.66591496770823055, 0.66627668493302206, 0.66663830434152394, 0.6669998257210048, 0.66736124885879056, 0.66772257354226583, 0.66808379955887232, 0.66844492669611, 0.66880595474153737, 0.66916688348277065, 0.66952771270748479, 0.66988844220341348, 0.67024907175834858, 0.67060960116014123, 0.67097003019670121, 0.67133035865599722, 0.6716905863260576, 0.67205071299496955, 0.67241073845087962, 0.67277066248199457, 0.67313048487658, 0.6734902054229619, 0.67384982390952575, 0.67420934012471723, 0.67456875385704251, 0.67492806489506751, 0.67528727302741876, 0.6756463780427836, 0.67600537972990959, 0.67636427787760534, 0.67672307227474038, 0.67708176271024523, 0.67744034897311134, 0.67779883085239201, 0.67815720813720115, 0.67851548061671507, 0.67887364808017092, 0.67923171031686824, 0.67958966711616831, 0.67994751826749411, 0.68030526356033116, 0.68066290278422714, 0.68102043572879212, 0.68137786218369856, 0.68173518193868188, 0.68209239478353989, 0.68244950050813369, 0.68280649890238698, 0.68316338975628677, 0.68352017285988365, 0.68387684800329107, 0.68423341497668622, 0.68458987357030998, 0.68494622357446711, 0.68530246477952583, 0.6856585969759188, 0.68601461995414248, 0.68637053350475785, 0.68672633741839018, 0.68708203148572899, 0.6874376154975288, 0.68779308924460869, 0.68814845251785239, 0.68850370510820913, 0.68885884680669296, 0.68921387740438278, 0.68956879669242377, 0.68992360446202561, 0.69027830050446426, 0.69063288461108119, 0.69098735657328358, 0.69134171618254492, 0.69169596323040439, 0.69205009750846758, 0.69240411880840647, 0.69275802692195954, 0.69311182164093155, 0.69346550275719432, 0.69381907006268628, 0.69417252334941315, 0.69452586240944725, 0.69487908703492818, 0.69523219701806327, 0.69558519215112702, 0.6959380722264612, 0.69629083703647576, 0.69664348637364826, 0.69699602003052408, 0.69734843779971678, 0.69770073947390809, 0.69805292484584813, 0.69840499370835518, 0.69875694585431614, 0.69910878107668684, 0.69946049916849151, 0.69981209992282345, 0.7001635831328451, 0.70051494859178787, 0.70086619609295253, 0.70121732542970927, 0.70156833639549765, 0.70191922878382706, 0.70227000238827653, 0.70262065700249487, 0.70297119242020123, 0.70332160843518454, 0.70367190484130404, 0.70402208143248934, 0.70437213800274079, 0.70472207434612877, 0.70507189025679518, 0.70542158552895196, 0.70577115995688267, 0.70612061333494147, 0.70646994545755404, 0.70681915611921731, 0.70716824511449961, 0.70751721223804087, 0.70786605728455276, 0.70821478004881866, 0.70856338032569388, 0.70891185791010614, 0.70926021259705485, 0.70960844418161195, 0.70995655245892186, 0.71030453722420128, 0.71065239827273985, 0.71100013539989992, 0.71134774840111648, 0.71169523707189808, 0.71204260120782581, 0.71238984060455435, 0.71273695505781198, 0.71308394436339984, 0.71343080831719319, 0.71377754671514104, 0.7141241593532659, 0.71447064602766475, 0.7148170065345083, 0.71516324067004133, 0.71550934823058354, 0.71585532901252868, 0.71620118281234513, 0.71654690942657595, 0.71689250865183929, 0.71723798028482788, 0.71758332412230974, 0.71792853996112771, 0.71827362759820068, 0.71861858683052215, 0.71896341745516146, 0.71930811926926386, 0.71965269207005, 0.7199971356548166, 0.72034144982093651, 0.72068563436585831, 0.72102968908710741, 0.72137361378228504, 0.72171740824906916, 0.72206107228521466, 0.72240460568855247, 0.72274800825699081, 0.72309127978851506, 0.72343442008118719, 0.72377742893314645, 0.72412030614261003, 0.7244630515078716, 0.72480566482730335, 0.72514814589935439, 0.72549049452255188, 0.72583271049550124, 0.72617479361688553, 0.72651674368546582, 0.72685856050008191, 0.72720024385965187, 0.72754179356317195, 0.7278832094097174, 0.7282244911984419, 0.72856563872857849, 0.7289066517994387, 0.72924753021041311, 0.72958827376097202, 0.72992888225066477, 0.73026935547911997, 0.73060969324604619, 0.73094989535123145, 0.7312899615945434, 0.73162989177593007, 0.7319696856954192, 0.73230934315311891, 0.73264886394921735, 0.73298824788398309, 0.73332749475776549, 0.73366660437099429, 0.73400557652417997, 0.73434441101791403, 0.73468310765286882, 0.73502166622979781, 0.73536008654953589, 0.73569836841299896, 0.73603651162118433, 0.73637451597517145, 0.73671238127612071, 0.73705010732527498, 0.73738769392395864, 0.73772514087357788, 0.73806244797562182, 0.73839961503166118, 0.73873664184334897, 0.73907352821242156, 0.73941027394069703, 0.7397468788300765, 0.74008334268254428, 0.74041966530016701, 0.74075584648509496, 0.74109188603956144, 0.74142778376588281, 0.74176353946645945, 0.7420991529437746, 0.74243462400039562, 0.74276995243897348, 0.74310513806224332, 0.74344018067302375, 0.743775080074218, 0.74410983606881342, 0.74444444845988156, 0.74477891705057875, 0.74511324164414561, 0.74544742204390757, 0.74578145805327511, 0.74611534947574309, 0.74644909611489207, 0.74678269777438744, 0.74711615425797984, 0.74744946536950563, 0.74778263091288633, 0.74811565069212915, 0.74844852451132737, 0.74878125217465952, 0.74911383348639093, 0.74944626825087246, 0.74977855627254097, 0.7501106973559204, 0.75044269130562047, 0.75077453792633775, 0.75110623702285539, 0.75143778840004349, 0.75176919186285884, 0.75210044721634528, 0.7524315542656338, 0.75276251281594275, 0.75309332267257778, 0.75342398364093166, 0.75375449552648544, 0.75408485813480741, 0.75441507127155361, 0.75474513474246829, 0.75507504835338346, 0.75540481191021958, 0.75573442521898526, 0.75606388808577729, 0.75639320031678148, 0.75672236171827179, 0.75705137209661089, 0.7573802312582506, 0.75770893900973157, 0.75803749515768337, 0.75836589950882494, 0.75869415186996458, 0.75902225204799967, 0.75935019984991758, 0.75967799508279477, 0.76000563755379802, 0.76033312707018363, 0.76066046343929783, 0.76098764646857719, 0.76131467596554847, 0.76164155173782822, 0.76196827359312436, 0.76229484133923453, 0.76262125478404741, 0.76294751373554237, 0.76327361800178972, 0.7635995673909507, 0.76392536171127778, 0.7642510007711143, 0.76457648437889536, 0.76490181234314747, 0.76522698447248816, 0.76555200057562756, 0.7658768604613666, 0.76620156393859906, 0.76652611081630984, 0.76685050090357643, 0.76717473400956882, 0.76749880994354869, 0.76782272851487054, 0.76814648953298159, 0.76847009280742151, 0.76879353814782281, 0.76911682536391091, 0.76943995426550416, 0.7697629246625145, 0.77008573636494648, 0.77040838918289833, 0.77073088292656178, 0.77105321740622201, 0.77137539243225794, 0.7716974078151424, 0.77201926336544191, 0.77234095889381726, 0.77266249421102329, 0.77298386912790884, 0.77330508345541749, 0.77362613700458704, 0.77394702958655015, 0.7742677610125337, 0.77458833109385994, 0.77490873964194551, 0.77522898646830241, 0.77554907138453777, 0.77586899420235378, 0.77618875473354809, 0.77650835279001384, 0.77682778818373965, 0.77714706072681006, 0.77746617023140518, 0.77778511650980109, 0.77810389937437008, 0.77842251863758016, 0.77874097411199583, 0.77905926561027816, 0.77937739294518416, 0.77969535592956807, 0.78001315437638019, 0.78033078809866807, 0.78064825690957584, 0.78096556062234468, 0.78128269905031322, 0.78159967200691716, 0.78191647930568919, 0.78223312076025975, 0.78254959618435704, 0.78286590539180656, 0.78318204819653192, 0.78349802441255434, 0.78381383385399317, 0.7841294763350658, 0.78444495167008799, 0.78476025967347363, 0.7850754001597352, 0.78539037294348368, 0.78570517783942861, 0.78601981466237858, 0.78633428322724064, 0.7866485833490211, 0.78696271484282543, 0.78727667752385799, 0.78759047120742265, 0.78790409570892272, 0.78821755084386091, 0.78853083642783983, 0.78884395227656146, 0.78915689820582791, 0.789469674031541, 0.78978227956970293, 0.7900947146364159, 0.79040697904788226, 0.79071907262040519, 0.79103099517038777, 0.79134274651433423, 0.79165432646884915, 0.79196573485063815, 0.79227697147650766, 0.79258803616336526, 0.79289892872821943, 0.79320964898818036, 0.79352019676045904, 0.79383057186236838, 0.79414077411132267, 0.79445080332483786, 0.79476065932053197, 0.79507034191612447, 0.79537985092943719, 0.7956891861783939, 0.7959983474810205, 0.79630733465544568, 0.79661614751989995, 0.79692478589271687, 0.79723324959233222, 0.79754153843728504, 0.79784965224621673, 0.79815759083787197, 0.7984653540310982, 0.79877294164484658, 0.79908035349817119, 0.79938758941022936, 0.79969464920028233, 0.80000153268769458, 0.80030823969193454, 0.80061477003257431, 0.80092112352929012, 0.80122730000186193, 0.80153329927017414, 0.8018391211542153, 0.80214476547407809, 0.80245023204996002, 0.80275552070216283, 0.80306063125109306, 0.80336556351726229, 0.80367031732128646, 0.80397489248388687, 0.80427928882588973, 0.80458350616822671, 0.80488754433193421, 0.80519140313815474, 0.80549508240813594, 0.80579858196323095, 0.80610190162489903, 0.80640504121470491, 0.80670800055431935, 0.80701077946551925, 0.80731337777018752, 0.80761579529031347, 0.8079180318479926, 0.80822008726542682, 0.80852196136492493, 0.80882365396890199, 0.80912516489988007, 0.80942649398048827, 0.80972764103346195, 0.8100286058816446, 0.81032938834798607, 0.81062998825554389, 0.81093040542748263, 0.81123063968707498, 0.81153069085770069, 0.81183055876284738, 0.81213024322611038, 0.81242974407119317, 0.81272906112190713, 0.81302819420217176, 0.81332714313601473, 0.81362590774757204, 0.81392448786108829, 0.81422288330091641, 0.81452109389151806, 0.81481911945746355, 0.81511695982343224, 0.81541461481421229, 0.81571208425470099, 0.81600936796990453, 0.81630646578493882, 0.81660337752502865, 0.81690010301550864, 0.81719664208182285, 0.81749299454952484, 0.81778916024427817, 0.8180851389918562, 0.81838093061814221, 0.81867653494912962, 0.81897195181092208, 0.81926718102973339, 0.81956222243188792, 0.81985707584382028, 0.82015174109207589, 0.82044621800331075, 0.82074050640429164, 0.82103460612189627, 0.82132851698311349, 0.82162223881504293, 0.82191577144489569, 0.82220911469999425, 0.82250226840777207, 0.82279523239577435, 0.82308800649165814, 0.82338059052319201, 0.82367298431825609, 0.82396518770484273, 0.82425720051105622, 0.82454902256511309, 0.82484065369534165, 0.82513209373018293, 0.82542334249819049, 0.82571439982802997, 0.82600526554847975, 0.82629593948843127, 0.82658642147688843, 0.82687671134296803, 0.82716680891590033, 0.82745671402502807, 0.82774642649980779, 0.8280359461698088, 0.82832527286471458, 0.82861440641432127, 0.82890334664853937, 0.82919209339739264, 0.82948064649101871, 0.82976900575966939, 0.83005717103371035, 0.83034514214362121, 0.83063291891999613, 0.83092050119354344, 0.83120788879508589, 0.83149508155556073, 0.83178207930601999, 0.83206888187763006, 0.83235548910167245, 0.83264190080954359, 0.83292811683275492, 0.83321413700293268, 0.83349996115181879, 0.83378558911127021, 0.83407102071325934, 0.83435625578987405, 0.83464129417331812, 0.83492613569591057, 0.83521078019008654, 0.83549522748839711, 0.83577947742350922, 0.83606352982820598, 0.83634738453538648, 0.83663104137806654, 0.83691450018937807, 0.83719776080256958, 0.83748082305100602, 0.83776368676816926, 0.83804635178765796, 0.83832881794318748, 0.83861108506859017, 0.83889315299781586, 0.83917502156493073, 0.8394566906041192, 0.83973815994968248, 0.84001942943603947, 0.84030049889772651, 0.84058136816939766, 0.84086203708582485, 0.84114250548189784, 0.84142277319262404, 0.84170284005312945, 0.84198270589865776, 0.84226237056457121, 0.84254183388635018, 0.84282109569959385, 0.84310015584001929, 0.84337901414346295, 0.84365767044587958, 0.84393612458334277, 0.84421437639204533, 0.84449242570829863, 0.84477027236853353, 0.84504791620930009, 0.84532535706726741, 0.84560259477922428, 0.84587962918207893, 0.84615646011285917, 0.84643308740871237, 0.84670951090690594, 0.84698573044482695, 0.84726174585998282, 0.84753755699000044, 0.84781316367262749, 0.84808856574573155, 0.84836376304730066, 0.84863875541544331, 0.8489135426883887, 0.84918812470448646, 0.84946250130220713, 0.84973667232014194, 0.85001063759700313, 0.85028439697162428, 0.85055795028295944, 0.85083129737008423, 0.85110443807219593, 0.85137737222861265, 0.85165009967877436, 0.85192262026224252, 0.85219493381870026, 0.8524670401879525, 0.85273893920992605, 0.85301063072466987, 0.85328211457235481, 0.85355339059327373, 0.85382445862784218, 0.8540953185165977, 0.85436597010020032, 0.85463641321943284, 0.85490664771520042, 0.85517667342853121, 0.85544649020057584, 0.85571609787260816, 0.85598549628602505, 0.85625468528234616, 0.85652366470321462, 0.85679243439039676, 0.85706099418578241, 0.85732934393138449, 0.85759748346934006, 0.8578654126419093, 0.85813313129147661, 0.85840063926054977, 0.85866793639176087, 0.8589350225278658, 0.85920189751174492, 0.85946856118640225, 0.8597350133949665, 0.86000125398069083, 0.86026728278695264, 0.860533099657254, 0.86079870443522188, 0.86106409696460773, 0.86132927708928786, 0.86159424465326373, 0.86185899950066169, 0.86212354147573356, 0.86238787042285558, 0.86265198618653038, 0.86291588861138524, 0.863179577542173, 0.86344305282377243, 0.86370631430118783, 0.86396936181954931, 0.86423219522411254, 0.86449481436025966, 0.86475721907349845, 0.86501940920946307, 0.8652813846139138, 0.86554314513273711, 0.86580469061194631, 0.8660660208976807, 0.86632713583620635, 0.86658803527391637, 0.86684871905733019, 0.86710918703309414, 0.86736943904798169, 0.86762947494889342, 0.8678892945828568, 0.86814889779702653, 0.8684082844386849, 0.86866745435524151, 0.86892640739423299, 0.86918514340332431, 0.86944366223030756, 0.86970196372310293, 0.8699600477297581, 0.87021791409844895, 0.87047556267747961, 0.87073299331528164, 0.87099020586041553, 0.87124720016156965, 0.87150397606756091, 0.87176053342733462, 0.87201687208996459, 0.87227299190465368, 0.87252889272073297, 0.87278457438766277, 0.87304003675503195, 0.8732952796725586, 0.87355030299009007, 0.87380510655760257, 0.8740596902252018, 0.87431405384312266, 0.87456819726172963, 0.87482212033151674, 0.87507582290310748, 0.87532930482725535, 0.87558256595484318, 0.87583560613688416, 0.87608842522452135, 0.87634102306902761, 0.87659339952180626, 0.87684555443439072, 0.87709748765844453, 0.87734919904576225, 0.87760068844826833, 0.877851955718018, 0.87810300070719727, 0.87835382326812284, 0.87860442325324228, 0.87885480051513409, 0.87910495490650764, 0.87935488628020364, 0.87960459448919392, 0.87985407938658167, 0.88010334082560115, 0.88035237865961846, 0.88060119274213089, 0.88084978292676763, 0.88109814906728945, 0.88134629101758899, 0.88159420863169069, 0.88184190176375088, 0.88208937026805834, 0.88233661399903363, 0.88258363281122953, 0.88283042655933119, 0.88307699509815651, 0.88332333828265519, 0.88356945596791014, 0.88381534800913664, 0.88406101426168271, 0.88430645458102919, 0.8845516688227899, 0.88479665684271147, 0.88504141849667395, 0.8852859536406904, 0.88553026213090691, 0.88577434382360321, 0.88601819857519226, 0.88626182624222061, 0.88650522668136844, 0.88674839974944952, 0.8869913453034115, 0.88723406320033549, 0.88747655329743691, 0.88771881545206521, 0.88796084952170384, 0.88820265536397014, 0.88844423283661622, 0.8886855817975281, 0.88892670210472657, 0.88916759361636655, 0.88940825619073793, 0.8896486896862652, 0.88988889396150728, 0.8901288688751583, 0.89036861428604719, 0.8906081300531381, 0.89084741603552975, 0.89108647209245651, 0.89132529808328786, 0.89156389386752866, 0.89180225930481916, 0.89204039425493498, 0.89227829857778762, 0.89251597213342404, 0.89275341478202697, 0.89299062638391513, 0.89322760679954283, 0.89346435588950091, 0.89370087351451566, 0.89393715953545017, 0.89417321381330317, 0.89440903620921008, 0.89464462658444277, 0.89487998480040953, 0.89511511071865502, 0.89535000420086086, 0.89558466510884505, 0.89581909330456289, 0.89605328865010625, 0.89628725100770379, 0.89652098023972182, 0.89675447620866333, 0.89698773877716853, 0.8972207678080153, 0.89745356316411851, 0.8976861247085306, 0.89791845230444178, 0.8981505458151795, 0.89838240510420941, 0.8986140300351344, 0.89884542047169558, 0.89907657627777193, 0.89930749731738047, 0.89953818345467618, 0.89976863455395251, 0.89999885047964101, 0.90022883109631135, 0.9004585762686721, 0.90068808586157012, 0.90091735973999065, 0.90114639776905792, 0.90137519981403458, 0.90160376574032242, 0.90183209541346199, 0.90206018869913285, 0.90228804546315355, 0.90251566557148188, 0.90274304889021462, 0.9029701952855882, 0.90319710462397818, 0.90342377677189967, 0.90365021159600722, 0.90387640896309518, 0.90410236874009742, 0.90432809079408749, 0.90455357499227906, 0.90477882120202557, 0.90500382929082057, 0.90522859912629738, 0.90545313057622989, 0.90567742350853186, 0.90590147779125774, 0.90612529329260194, 0.9063488698808998, 0.90657220742462674, 0.9067953057923992, 0.90701816485297426, 0.90724078447524925, 0.90746316452826337, 0.9076853048811957, 0.90790720540336689, 0.9081288659642387, 0.90835028643341387, 0.90857146668063649, 0.90879240657579186, 0.90901310598890672, 0.90923356479014927, 0.90945378284982947, 0.9096737600383985, 0.90989349622644955, 0.91011299128471734, 0.91033224508407873, 0.91055125749555232, 0.91077002839029886, 0.91098855763962083, 0.91120684511496319, 0.91142489068791321, 0.91164269423020006, 0.91186025561369566, 0.91207757471041428, 0.91229465139251265, 0.91251148553229011, 0.91272807700218883, 0.91294442567479339, 0.91316053142283171, 0.91337639411917426, 0.91359201363683451, 0.91380738984896914, 0.91402252262887784, 0.91423741185000362, 0.91445205738593249, 0.91466645911039413, 0.91488061689726152, 0.91509453062055113, 0.91530820015442316, 0.91552162537318116, 0.91573480615127267, 0.9159477423632888, 0.91616043388396484, 0.91637288058817967, 0.91658508235095659, 0.91679703904746257, 0.91700875055300912, 0.91722021674305165, 0.91743143749319001, 0.91764241267916868, 0.9178531421768763, 0.91806362586234613, 0.918273863611756, 0.91848385530142851, 0.91869360080783102, 0.91890310000757547, 0.91911235277741898, 0.9193213589942637, 0.91953011853515632, 0.91973863127728928, 0.91994689709799982, 0.92015491587477038, 0.92036268748522909, 0.92057021180714904, 0.92077748871844922, 0.92098451809719384, 0.92119129982159298, 0.92139783377000206, 0.92160411982092272, 0.92181015785300202, 0.92201594774503315, 0.92222148937595527, 0.92242678262485356, 0.92263182737095906, 0.92283662349364959, 0.92304117087244852, 0.92324546938702601, 0.92344951891719862, 0.92365331934292916, 0.92385687054432719, 0.92406017240164862, 0.92426322479529632, 0.92446602760581986, 0.92466858071391544, 0.92487088400042627, 0.92507293734634266, 0.92527474063280168, 0.92547629374108786, 0.9256775965526326, 0.9258786489490145, 0.92607945081195986, 0.92628000202334204, 0.92648030246518176, 0.92668035201964771, 0.92688015056905571, 0.92707969799586942, 0.92727899418270021, 0.92747803901230741, 0.92767683236759801, 0.92787537413162691, 0.92807366418759729, 0.92827170241886003, 0.92846948870891444, 0.92866702294140779, 0.92886430500013606, 0.92906133476904307, 0.92925811213222143, 0.92945463697391195, 0.92965090917850424, 0.92984692863053631, 0.93004269521469507, 0.93023820881581609, 0.9304334693188836, 0.93062847660903114, 0.93082323057154071, 0.9310177310918436, 0.93121197805552025, 0.93140597134830017, 0.93159971085606208, 0.93179319646483405, 0.93198642806079335, 0.93217940553026701, 0.93237212875973119, 0.9325645976358119, 0.93275681204528449, 0.93294877187507441, 0.93314047701225644, 0.93333192734405557, 0.93352312275784632, 0.93371406314115346, 0.93390474838165161, 0.9340951783671656, 0.9342853529856705, 0.93447527212529113, 0.93466493567430342, 0.93485434352113284, 0.93504349555435573, 0.93523239166269878, 0.93542103173503943, 0.93560941566040556, 0.93579754332797549, 0.93598541462707896, 0.93617302944719571, 0.93636038767795715, 0.93654748920914499, 0.93673433393069239, 0.93692092173268349, 0.93710725250535321, 0.93729332613908811, 0.93747914252442577, 0.93766470155205539, 0.9378500031128173, 0.93803504709770325, 0.93821983339785686, 0.93840436190457277, 0.93858863250929803, 0.93877264510363068, 0.93895639957932087, 0.93913989582827084, 0.93932313374253407, 0.93950611321431676, 0.93968883413597659, 0.93987129640002376, 0.94005349989912013, 0.94023544452608032, 0.94041713017387096, 0.94059855673561099, 0.94077972410457189, 0.94096063217417747, 0.94114128083800441, 0.9413216699897814, 0.94150179952339041, 0.94168166933286579, 0.94186127931239483, 0.94204062935631749, 0.94221971935912685, 0.94239854921546895, 0.94257711882014261, 0.94275542806809998, 0.9429334768544464, 0.94311126507444032, 0.94328879262349352, 0.9434660593971711, 0.94364306529119157, 0.94381981020142702, 0.94399629402390284, 0.94417251665479818, 0.94434847799044586, 0.94452417792733234, 0.94469961636209776, 0.94487479319153644, 0.94504970831259616, 0.94522436162237899, 0.94539875301814069, 0.94557288239729154, 0.94574674965739569, 0.94592035469617142, 0.9460936974114913, 0.94626677770138223, 0.9464395954640259, 0.94661215059775761, 0.9467844430010679, 0.94695647257260163, 0.94712823921115807, 0.94729974281569129, 0.94747098328531032, 0.94764196051927874, 0.947812674417015, 0.94798312487809255, 0.94815331180223983, 0.94832323508934013, 0.94849289463943198, 0.9486622903527091, 0.94883142212952043, 0.94900028987037, 0.94916889347591715, 0.94933723284697691, 0.94950530788451948, 0.94967311848967073, 0.94984066456371197, 0.95000794600808014, 0.95017496272436786, 0.95034171461432349, 0.95050820157985116, 0.95067442352301101, 0.95084038034601881, 0.95100607195124653, 0.95117149824122205, 0.95133665911862941, 0.95150155448630858, 0.95166618424725591, 0.95183054830462399, 0.95199464656172172, 0.95215847892201411, 0.95232204528912312, 0.95248534556682662, 0.95264837965905946, 0.95281114746991258, 0.95297364890363423, 0.95313588386462889, 0.95329785225745767, 0.95345955398683913, 0.95362098895764791, 0.95378215707491631, 0.95394305824383308, 0.95410369236974435, 0.95426405935815306, 0.95442415911471956, 0.95458399154526119, 0.95474355655575271, 0.95490285405232611, 0.95506188394127078, 0.95522064612903357, 0.95537914052221873, 0.95553736702758818, 0.95569532555206127, 0.95585301600271499, 0.95601043828678423, 0.95616759231166137, 0.95632447798489695, 0.95648109521419911, 0.95663744390743388, 0.9567935239726254, 0.9569493353179559, 0.95710487785176535, 0.95726015148255228, 0.9574151561189731, 0.95756989166984263, 0.95772435804413392, 0.95787855515097831, 0.9580324828996658, 0.95818614119964463, 0.9583395299605213, 0.95849264909206155, 0.95864549850418901, 0.95879807810698647, 0.9589503878106953, 0.95910242752571551, 0.95925419716260607, 0.95940569663208497, 0.95955692584502894, 0.95970788471247359, 0.95985857314561374, 0.96000899105580328, 0.96015913835455535, 0.96030901495354193, 0.96045862076459476, 0.96060795569970436, 0.9607570196710209, 0.96090581259085406, 0.96105433437167254, 0.961202584926105, 0.96135056416693931, 0.96149827200712312, 0.96164570835976382, 0.96179287313812833, 0.96193976625564337, 0.9620863876258956, 0.96223273716263136, 0.96237881477975695, 0.96252462039133879, 0.96267015391160315, 0.96281541525493641, 0.96296040433588503, 0.96310512106915569, 0.96324956536961526, 0.96339373715229093, 0.96353763633237, 0.9636812628252005, 0.96382461654629059, 0.96396769741130894, 0.96411050533608478, 0.96425304023660785, 0.96439530202902857, 0.96453729062965787, 0.96467900595496769, 0.96482044792159061, 0.96496161644631984, 0.96510251144610959, 0.96524313283807484, 0.96538348053949186, 0.96552355446779758, 0.96566335454059016, 0.96580288067562892, 0.96594213279083407, 0.96608111080428727, 0.96621981463423112, 0.96635824419907013, 0.96649639941736942, 0.96663428020785602, 0.96677188648941814, 0.96690921818110542, 0.96704627520212949, 0.96718305747186295, 0.96731956490984039, 0.96745579743575805, 0.96759175496947381, 0.96772743743100731, 0.96786284474054018, 0.96799797681841571, 0.96813283358513913, 0.96826741496137769, 0.96840172086796072, 0.96853575122587965, 0.96866950595628754, 0.96880298498049999, 0.96893618821999494, 0.96906911559641218, 0.96920176703155403, 0.96933414244738514, 0.96946624176603224, 0.96959806490978495, 0.96972961180109496, 0.96986088236257673, 0.96999187651700702, 0.97012259418732549, 0.97025303529663409, 0.97038319976819798, 0.97051308752544463, 0.97064269849196427, 0.97077203259151035, 0.97090108974799882, 0.97102986988550866, 0.97115837292828189, 0.97128659880072343, 0.97141454742740141, 0.97154221873304669, 0.97166961264255391, 0.97179672908098014, 0.97192356797354629, 0.97205012924563627, 0.97217641282279743, 0.97230241863074007, 0.9724281465953386, 0.9725535966426303, 0.97267876869881609, 0.97280366269026064, 0.97292827854349195, 0.97305261618520178, 0.9731766755422453, 0.97330045654164177, 0.973423959110574, 0.97354718317638866, 0.97367012866659608, 0.97379279550887055, 0.97391518363105045, 0.97403729296113806, 0.9741591234272996, 0.97428067495786519, 0.97440194748132924, 0.97452294092635028, 0.974643655221751, 0.97476409029651834, 0.97488424607980328, 0.9750041225009215, 0.97512371948935261, 0.97524303697474091, 0.97536207488689475, 0.9754808331557876, 0.97559931171155667, 0.97571751048450417, 0.97583542940509693, 0.97595306840396612, 0.97607042741190786, 0.97618750635988294, 0.97630430517901667, 0.97642082380059936, 0.97653706215608604, 0.97665302017709688, 0.97676869779541664, 0.97688409494299511, 0.97699921155194724, 0.97711404755455278, 0.97722860288325675, 0.97734287747066917, 0.97745687124956526, 0.97757058415288534, 0.97768401611373523, 0.97779716706538555, 0.97791003694127276, 0.9780226256749982, 0.97813493320032907, 0.97824695945119755, 0.97835870436170147, 0.97847016786610441, 0.97858134989883505, 0.97869225039448793, 0.97880286928782323, 0.97891320651376645, 0.9790232620074093, 0.97913303570400889, 0.97924252753898811, 0.9793517374479358, 0.97946066536660659, 0.97956931123092095, 0.97967767497696534, 0.9797857565409922, 0.97989355585941995, 0.98000107286883298, 0.98010830750598177, 0.98021525970778289, 0.98032192941131924, 0.98042831655383988, 0.98053442107275968, 0.98064024290566032, 0.9807457819902895, 0.98085103826456121, 0.9809560116665561, 0.98106070213452079, 0.98116510960686876, 0.98126923402217958, 0.98137307531919971, 0.98147663343684188, 0.98157990831418562, 0.98168289989047697, 0.9817856081051286, 0.98188803289771998, 0.98199017420799706, 0.98209203197587291, 0.98219360614142714, 0.98229489664490632, 0.982395903426724, 0.98249662642746016, 0.98259706558786242, 0.9826972208488447, 0.98279709215148836, 0.98289667943704184, 0.98299598264692034, 0.98309500172270625, 0.98319373660614939, 0.98329218723916656, 0.98339035356384163, 0.98348823552242604, 0.98358583305733838, 0.98368314611116425, 0.98378017462665723, 0.98387691854673776, 0.9839733778144939, 0.98406955237318128, 0.98416544216622259, 0.98426104713720863, 0.98435636722989739, 0.98445140238821449, 0.98454615255625311, 0.98464061767827427, 0.98473479769870653, 0.98482869256214622, 0.98492230221335741, 0.98501562659727204, 0.98510866565898958, 0.9852014193437777, 0.98529388759707182, 0.98538607036447523, 0.98547796759175899, 0.98556957922486255, 0.98566090520989302, 0.98575194549312584, 0.98584270002100427, 0.9859331687401397, 0.9860233515973118, 0.98611324853946813, 0.98620285951372488, 0.98629218446736611, 0.98638122334784428, 0.98646997610278009, 0.98655844267996251, 0.98664662302734918, 0.98673451709306548, 0.98682212482540599, 0.98690944617283305, 0.98699648108397797, 0.98708322950764016, 0.98716969139278787, 0.9872558666885578, 0.98734175534425539, 0.98742735730935416, 0.98751267253349706, 0.98759770096649513, 0.98768244255832849, 0.98776689725914568, 0.98785106501926423, 0.98793494578917052, 0.98801853951951957, 0.98810184616113528, 0.98818486566501051, 0.98826759798230723, 0.98835004306435592, 0.98843220086265626, 0.98851407132887714, 0.9885956544148562, 0.98867695007260004, 0.9887579582542847, 0.98883867891225496, 0.98891911199902527, 0.98899925746727857, 0.98907911526986747, 0.98915868535981377, 0.98923796769030847, 0.98931696221471155, 0.98939566888655284, 0.98947408765953115, 0.98955221848751462, 0.98963006132454101, 0.98970761612481739, 0.98978488284272026, 0.98986186143279564, 0.98993855184975876, 0.99001495404849504, 0.99009106798405866, 0.99016689361167398, 0.99024243088673469, 0.99031767976480412, 0.99039264020161522, 0.99046731215307082, 0.9905416955752433, 0.99061579042437486, 0.99068959665687728, 0.99076311422933239, 0.99083634309849156, 0.99090928322127625, 0.99098193455477768, 0.99105429705625681, 0.99112637068314469, 0.99119815539304235, 0.99126965114372068, 0.99134085789312043, 0.99141177559935256, 0.99148240422069822, 0.9915527437156082, 0.99162279404270359, 0.99169255516077559, 0.99176202702878569, 0.99183120960586513, 0.9919001028513158, 0.99196870672460946, 0.99203702118538817, 0.99210504619346451, 0.99217278170882095, 0.99224022769161047, 0.99230738410215635, 0.9923742509009521, 0.99244082804866185, 0.99250711550611992, 0.99257311323433117, 0.99263882119447056, 0.99270423934788421, 0.99276936765608803, 0.99283420608076878, 0.99289875458378374, 0.99296301312716051, 0.99302698167309766, 0.99309066018396419, 0.99315404862229939, 0.99321714695081353, 0.99327995513238765, 0.99334247313007329, 0.99340470090709276, 0.99346663842683891, 0.99352828565287554, 0.99358964254893722, 0.99365070907892927, 0.99371148520692776, 0.99377197089717961, 0.99383216611410286, 0.99389207082228603, 0.99395168498648889, 0.99401100857164182, 0.99407004154284628, 0.99412878386537473, 0.99418723550467059, 0.99424539642634824, 0.99430326659619328, 0.99436084598016183, 0.99441813454438177, 0.99447513225515149, 0.99453183907894083, 0.99458825498239056, 0.99464437993231258, 0.99470021389569019, 0.99475575683967765, 0.99481100873160044, 0.99486596953895523, 0.99492063922941032, 0.99497501777080455, 0.99502910513114862, 0.9950829012786242, 0.99513640618158461, 0.99518961980855414, 0.99524254212822849, 0.99529517310947502, 0.99534751272133226, 0.99539956093301019, 0.99545131771388995, 0.99550278303352469, 0.9955539568616385, 0.99560483916812703, 0.99565542992305778, 0.99570572909666932, 0.99575573665937189, 0.99580545258174769, 0.99585487683454976, 0.99590400938870327, 0.99595285021530466, 0.99600139928562226, 0.9960496565710959, 0.99609762204333696, 0.99614529567412868, 0.99619267743542583, 0.99623976729935504, 0.99628656523821446, 0.99633307122447401, 0.99637928523077557, 0.99642520722993255, 0.99647083719493024, 0.99651617509892576, 0.99656122091524779, 0.99660597461739719, 0.99665043617904669, 0.99669460557404033, 0.99673848277639454, 0.99678206776029765, 0.99682536050010961, 0.99686836097036235, 0.99691106914575989, 0.99695348500117809, 0.99699560851166469, 0.99703743965243974, 0.99707897839889492, 0.99712022472659401, 0.99716117861127285, 0.9972018400288396, 0.99724220895537385, 0.99728228536712771, 0.99732206924052536, 0.99736156055216285, 0.99740075927880856, 0.99743966539740281, 0.99747827888505824, 0.99751659971905937, 0.997554627876863, 0.99759236333609846, 0.99762980607456675, 0.99766695607024114, 0.99770381330126745, 0.99774037774596347, 0.99777664938281929, 0.9978126281904971, 0.99784831414783182, 0.99788370723382991, 0.99791880742767081, 0.99795361470870581, 0.99798812905645895, 0.99802235045062604, 0.99805627887107562, 0.99808991429784855, 0.99812325671115776, 0.99815630609138895, 0.9981890624191001, 0.99822152567502132, 0.99825369584005541, 0.99828557289527742, 0.99831715682193489, 0.99834844760144803, 0.998379445215409, 0.99841014964558283, 0.99844056087390687, 0.99847067888249108, 0.99850050365361764, 0.99853003516974148, 0.99855927341349005, 0.99858821836766309, 0.99861687001523314, 0.9986452283393451, 0.99867329332331667, 0.9987010649506376, 0.99872854320497095, 0.99875572807015178, 0.99878261953018788, 0.99880921756925978, 0.99883552217172045, 0.99886153332209582, 0.99888725100508391, 0.99891267520555582, 0.99893780590855508, 0.99896264309929794, 0.99898718676317344, 0.99901143688574312, 0.99903539345274117, 0.99905905645007453, 0.99908242586382312, 0.99910550168023904, 0.99912828388574759, 0.99915077246694639, 0.99917296741060624, 0.99919486870367002, 0.99921647633325428, 0.99923779028664739, 0.99925881055131116, 0.99927953711487971, 0.99929996996516013, 0.99932010909013269, 0.99933995447794954, 0.99935950611693647, 0.99937876399559167, 0.9993977281025862, 0.999416398426764, 0.99943477495714172, 0.99945285768290915, 0.99947064659342844, 0.99948814167823485, 0.99950534292703663, 0.99952225032971465, 0.99953886387632274, 0.9995551835570875, 0.99957120936240851, 0.99958694128285819, 0.99960237930918194, 0.99961752343229793, 0.99963237364329727, 0.99964692993344384, 0.99966119229417472, 0.99967516071709972, 0.99968883519400142, 0.9997022157168356, 0.99971530227773087, 0.99972809486898861, 0.99974059348308342, 0.9997527981126626, 0.99976470875054657, 0.99977632538972849, 0.99978764802337461, 0.99979867664482414, 0.99980941124758926, 0.99981985182535515, 0.99982999837197961, 0.99983985088149396, 0.99984940934810207, 0.99985867376618109, 0.99986764413028084, 0.99987632043512442, 0.99988470267560769, 0.99989279084679961, 0.99990058494394218, 0.99990808496245021, 0.99991529089791165, 0.99992220274608767, 0.99992882050291199, 0.99993514416449147, 0.99994117372710623, 0.9999469091872093, 0.9999523505414265, 0.99995749778655674, 0.99996235091957231, 0.99996690993761805, 0.99997117483801201, 0.9999751456182453, 0.999978822275982, 0.99998220480905919, 0.99998529321548713, 0.99998808749344881, 0.99999058764130055, 0.99999279365757165, 0.99999470554096415, 0.99999632329035359, 0.9999976469047881, 0.99999867638348916, 0.99999941172585094, 0.99999985293144111, 1.0, 0.99999985293144111, 0.99999941172585094, 0.99999867638348916, 0.9999976469047881, 0.99999632329035359, 0.99999470554096415, 0.99999279365757165, 0.99999058764130055, 0.99998808749344881, 0.99998529321548713, 0.99998220480905919, 0.999978822275982, 0.9999751456182453, 0.99997117483801201, 0.99996690993761805, 0.99996235091957231, 0.99995749778655674, 0.9999523505414265, 0.9999469091872093, 0.99994117372710623, 0.99993514416449147, 0.99992882050291199, 0.99992220274608767, 0.99991529089791165, 0.99990808496245021, 0.99990058494394218, 0.99989279084679961, 0.99988470267560769, 0.99987632043512442, 0.99986764413028084, 0.99985867376618109, 0.99984940934810207, 0.99983985088149396, 0.99982999837197961, 0.99981985182535515, 0.99980941124758926, 0.99979867664482414, 0.99978764802337461, 0.99977632538972849, 0.99976470875054657, 0.9997527981126626, 0.99974059348308342, 0.99972809486898861, 0.99971530227773087, 0.9997022157168356, 0.99968883519400142, 0.99967516071709972, 0.99966119229417472, 0.99964692993344384, 0.99963237364329727, 0.99961752343229793, 0.99960237930918194, 0.99958694128285819, 0.99957120936240851, 0.9995551835570875, 0.99953886387632274, 0.99952225032971465, 0.99950534292703663, 0.99948814167823485, 0.99947064659342844, 0.99945285768290915, 0.99943477495714172, 0.999416398426764, 0.9993977281025862, 0.99937876399559167, 0.99935950611693647, 0.99933995447794954, 0.99932010909013269, 0.99929996996516013, 0.99927953711487971, 0.99925881055131116, 0.99923779028664739, 0.99921647633325428, 0.99919486870367002, 0.99917296741060624, 0.99915077246694639, 0.99912828388574759, 0.99910550168023904, 0.99908242586382312, 0.99905905645007453, 0.99903539345274117, 0.99901143688574312, 0.99898718676317344, 0.99896264309929794, 0.99893780590855508, 0.99891267520555582, 0.99888725100508391, 0.99886153332209582, 0.99883552217172045, 0.99880921756925978, 0.99878261953018788, 0.99875572807015178, 0.99872854320497095, 0.9987010649506376, 0.99867329332331667, 0.9986452283393451, 0.99861687001523314, 0.99858821836766309, 0.99855927341349005, 0.99853003516974148, 0.99850050365361764, 0.99847067888249108, 0.99844056087390687, 0.99841014964558283, 0.998379445215409, 0.99834844760144803, 0.99831715682193489, 0.99828557289527742, 0.99825369584005541, 0.99822152567502132, 0.9981890624191001, 0.99815630609138895, 0.99812325671115776, 0.99808991429784855, 0.99805627887107562, 0.99802235045062604, 0.99798812905645895, 0.99795361470870581, 0.99791880742767081, 0.99788370723382991, 0.99784831414783182, 0.9978126281904971, 0.99777664938281929, 0.99774037774596347, 0.99770381330126745, 0.99766695607024114, 0.99762980607456675, 0.99759236333609846, 0.997554627876863, 0.99751659971905937, 0.99747827888505824, 0.99743966539740281, 0.99740075927880856, 0.99736156055216285, 0.99732206924052536, 0.99728228536712771, 0.99724220895537385, 0.9972018400288396, 0.99716117861127285, 0.99712022472659401, 0.99707897839889492, 0.99703743965243974, 0.99699560851166469, 0.99695348500117809, 0.99691106914575989, 0.99686836097036235, 0.99682536050010961, 0.99678206776029765, 0.99673848277639454, 0.99669460557404033, 0.99665043617904669, 0.99660597461739719, 0.99656122091524779, 0.99651617509892576, 0.99647083719493024, 0.99642520722993255, 0.99637928523077557, 0.99633307122447401, 0.99628656523821446, 0.99623976729935504, 0.99619267743542583, 0.99614529567412868, 0.99609762204333696, 0.9960496565710959, 0.99600139928562226, 0.99595285021530466, 0.99590400938870327, 0.99585487683454976, 0.99580545258174769, 0.99575573665937189, 0.99570572909666932, 0.99565542992305778, 0.99560483916812703, 0.9955539568616385, 0.99550278303352469, 0.99545131771388995, 0.99539956093301019, 0.99534751272133226, 0.99529517310947502, 0.99524254212822849, 0.99518961980855414, 0.99513640618158461, 0.9950829012786242, 0.99502910513114862, 0.99497501777080455, 0.99492063922941032, 0.99486596953895523, 0.99481100873160044, 0.99475575683967765, 0.99470021389569019, 0.99464437993231258, 0.99458825498239056, 0.99453183907894083, 0.99447513225515149, 0.99441813454438177, 0.99436084598016183, 0.99430326659619328, 0.99424539642634824, 0.99418723550467059, 0.99412878386537473, 0.99407004154284628, 0.99401100857164182, 0.99395168498648889, 0.99389207082228603, 0.99383216611410286, 0.99377197089717961, 0.99371148520692776, 0.99365070907892927, 0.99358964254893722, 0.99352828565287554, 0.99346663842683891, 0.99340470090709276, 0.99334247313007329, 0.99327995513238765, 0.99321714695081353, 0.99315404862229939, 0.99309066018396419, 0.99302698167309766, 0.99296301312716051, 0.99289875458378374, 0.99283420608076878, 0.99276936765608803, 0.99270423934788421, 0.99263882119447056, 0.99257311323433117, 0.99250711550611992, 0.99244082804866185, 0.9923742509009521, 0.99230738410215635, 0.99224022769161047, 0.99217278170882095, 0.99210504619346451, 0.99203702118538817, 0.99196870672460946, 0.9919001028513158, 0.99183120960586513, 0.99176202702878569, 0.99169255516077559, 0.99162279404270359, 0.9915527437156082, 0.99148240422069822, 0.99141177559935256, 0.99134085789312043, 0.99126965114372068, 0.99119815539304235, 0.99112637068314469, 0.99105429705625681, 0.99098193455477768, 0.99090928322127625, 0.99083634309849156, 0.99076311422933239, 0.99068959665687728, 0.99061579042437486, 0.9905416955752433, 0.99046731215307082, 0.99039264020161522, 0.99031767976480412, 0.99024243088673469, 0.99016689361167398, 0.99009106798405866, 0.99001495404849504, 0.98993855184975876, 0.98986186143279564, 0.98978488284272026, 0.98970761612481739, 0.98963006132454101, 0.98955221848751462, 0.98947408765953115, 0.98939566888655284, 0.98931696221471155, 0.98923796769030847, 0.98915868535981377, 0.98907911526986747, 0.98899925746727857, 0.98891911199902527, 0.98883867891225496, 0.9887579582542847, 0.98867695007260004, 0.9885956544148562, 0.98851407132887714, 0.98843220086265626, 0.98835004306435592, 0.98826759798230723, 0.98818486566501051, 0.98810184616113528, 0.98801853951951957, 0.98793494578917052, 0.98785106501926423, 0.98776689725914568, 0.98768244255832849, 0.98759770096649513, 0.98751267253349706, 0.98742735730935416, 0.98734175534425539, 0.9872558666885578, 0.98716969139278787, 0.98708322950764016, 0.98699648108397797, 0.98690944617283305, 0.98682212482540599, 0.98673451709306548, 0.98664662302734918, 0.98655844267996251, 0.98646997610278009, 0.98638122334784428, 0.98629218446736611, 0.98620285951372488, 0.98611324853946813, 0.9860233515973118, 0.9859331687401397, 0.98584270002100427, 0.98575194549312584, 0.98566090520989302, 0.98556957922486255, 0.98547796759175899, 0.98538607036447523, 0.98529388759707182, 0.9852014193437777, 0.98510866565898958, 0.98501562659727204, 0.98492230221335741, 0.98482869256214622, 0.98473479769870653, 0.98464061767827427, 0.98454615255625311, 0.98445140238821449, 0.98435636722989739, 0.98426104713720863, 0.98416544216622259, 0.98406955237318128, 0.9839733778144939, 0.98387691854673776, 0.98378017462665723, 0.98368314611116425, 0.98358583305733838, 0.98348823552242604, 0.98339035356384163, 0.98329218723916656, 0.98319373660614939, 0.98309500172270625, 0.98299598264692034, 0.98289667943704184, 0.98279709215148836, 0.9826972208488447, 0.98259706558786242, 0.98249662642746016, 0.982395903426724, 0.98229489664490632, 0.98219360614142714, 0.98209203197587291, 0.98199017420799706, 0.98188803289771998, 0.9817856081051286, 0.98168289989047697, 0.98157990831418562, 0.98147663343684188, 0.98137307531919971, 0.98126923402217958, 0.98116510960686876, 0.98106070213452079, 0.9809560116665561, 0.98085103826456121, 0.9807457819902895, 0.98064024290566032, 0.98053442107275968, 0.98042831655383988, 0.98032192941131924, 0.98021525970778289, 0.98010830750598177, 0.98000107286883298, 0.97989355585941995, 0.9797857565409922, 0.97967767497696534, 0.97956931123092095, 0.97946066536660659, 0.9793517374479358, 0.97924252753898811, 0.97913303570400889, 0.9790232620074093, 0.97891320651376645, 0.97880286928782323, 0.97869225039448793, 0.97858134989883505, 0.97847016786610441, 0.97835870436170147, 0.97824695945119755, 0.97813493320032907, 0.9780226256749982, 0.97791003694127276, 0.97779716706538555, 0.97768401611373523, 0.97757058415288534, 0.97745687124956526, 0.97734287747066917, 0.97722860288325675, 0.97711404755455278, 0.97699921155194724, 0.97688409494299511, 0.97676869779541664, 0.97665302017709688, 0.97653706215608604, 0.97642082380059936, 0.97630430517901667, 0.97618750635988294, 0.97607042741190786, 0.97595306840396612, 0.97583542940509693, 0.97571751048450417, 0.97559931171155667, 0.9754808331557876, 0.97536207488689475, 0.97524303697474091, 0.97512371948935261, 0.9750041225009215, 0.97488424607980328, 0.97476409029651834, 0.974643655221751, 0.97452294092635028, 0.97440194748132924, 0.97428067495786519, 0.9741591234272996, 0.97403729296113806, 0.97391518363105045, 0.97379279550887055, 0.97367012866659608, 0.97354718317638866, 0.973423959110574, 0.97330045654164177, 0.9731766755422453, 0.97305261618520178, 0.97292827854349195, 0.97280366269026064, 0.97267876869881609, 0.9725535966426303, 0.9724281465953386, 0.97230241863074007, 0.97217641282279743, 0.97205012924563627, 0.97192356797354629, 0.97179672908098014, 0.97166961264255391, 0.97154221873304669, 0.97141454742740141, 0.97128659880072343, 0.97115837292828189, 0.97102986988550866, 0.97090108974799882, 0.97077203259151035, 0.97064269849196427, 0.97051308752544463, 0.97038319976819798, 0.97025303529663409, 0.97012259418732549, 0.96999187651700702, 0.96986088236257673, 0.96972961180109496, 0.96959806490978495, 0.96946624176603224, 0.96933414244738514, 0.96920176703155403, 0.96906911559641218, 0.96893618821999494, 0.96880298498049999, 0.96866950595628754, 0.96853575122587965, 0.96840172086796072, 0.96826741496137769, 0.96813283358513913, 0.96799797681841571, 0.96786284474054018, 0.96772743743100731, 0.96759175496947381, 0.96745579743575805, 0.96731956490984039, 0.96718305747186295, 0.96704627520212949, 0.96690921818110542, 0.96677188648941814, 0.96663428020785602, 0.96649639941736942, 0.96635824419907013, 0.96621981463423112, 0.96608111080428727, 0.96594213279083407, 0.96580288067562892, 0.96566335454059016, 0.96552355446779758, 0.96538348053949186, 0.96524313283807484, 0.96510251144610959, 0.96496161644631984, 0.96482044792159061, 0.96467900595496769, 0.96453729062965787, 0.96439530202902857, 0.96425304023660785, 0.96411050533608478, 0.96396769741130894, 0.96382461654629059, 0.9636812628252005, 0.96353763633237, 0.96339373715229093, 0.96324956536961526, 0.96310512106915569, 0.96296040433588503, 0.96281541525493641, 0.96267015391160315, 0.96252462039133879, 0.96237881477975695, 0.96223273716263136, 0.9620863876258956, 0.96193976625564337, 0.96179287313812833, 0.96164570835976382, 0.96149827200712312, 0.96135056416693931, 0.961202584926105, 0.96105433437167254, 0.96090581259085406, 0.9607570196710209, 0.96060795569970436, 0.96045862076459476, 0.96030901495354193, 0.96015913835455535, 0.96000899105580328, 0.95985857314561374, 0.95970788471247359, 0.95955692584502894, 0.95940569663208497, 0.95925419716260607, 0.95910242752571551, 0.9589503878106953, 0.95879807810698647, 0.95864549850418901, 0.95849264909206155, 0.9583395299605213, 0.95818614119964463, 0.9580324828996658, 0.95787855515097831, 0.95772435804413392, 0.95756989166984263, 0.9574151561189731, 0.95726015148255228, 0.95710487785176535, 0.9569493353179559, 0.9567935239726254, 0.95663744390743388, 0.95648109521419911, 0.95632447798489695, 0.95616759231166137, 0.95601043828678423, 0.95585301600271499, 0.95569532555206127, 0.95553736702758818, 0.95537914052221873, 0.95522064612903357, 0.95506188394127078, 0.95490285405232611, 0.95474355655575271, 0.95458399154526119, 0.95442415911471956, 0.95426405935815306, 0.95410369236974435, 0.95394305824383308, 0.95378215707491631, 0.95362098895764791, 0.95345955398683913, 0.95329785225745767, 0.95313588386462889, 0.95297364890363423, 0.95281114746991258, 0.95264837965905946, 0.95248534556682662, 0.95232204528912312, 0.95215847892201411, 0.95199464656172172, 0.95183054830462399, 0.95166618424725591, 0.95150155448630858, 0.95133665911862941, 0.95117149824122205, 0.95100607195124653, 0.95084038034601881, 0.95067442352301101, 0.95050820157985116, 0.95034171461432349, 0.95017496272436786, 0.95000794600808014, 0.94984066456371197, 0.94967311848967073, 0.94950530788451948, 0.94933723284697691, 0.94916889347591715, 0.94900028987037, 0.94883142212952043, 0.9486622903527091, 0.94849289463943198, 0.94832323508934013, 0.94815331180223983, 0.94798312487809255, 0.947812674417015, 0.94764196051927874, 0.94747098328531032, 0.94729974281569129, 0.94712823921115807, 0.94695647257260163, 0.9467844430010679, 0.94661215059775761, 0.9464395954640259, 0.94626677770138223, 0.9460936974114913, 0.94592035469617142, 0.94574674965739569, 0.94557288239729154, 0.94539875301814069, 0.94522436162237899, 0.94504970831259616, 0.94487479319153644, 0.94469961636209776, 0.94452417792733234, 0.94434847799044586, 0.94417251665479818, 0.94399629402390284, 0.94381981020142702, 0.94364306529119157, 0.9434660593971711, 0.94328879262349352, 0.94311126507444032, 0.9429334768544464, 0.94275542806809998, 0.94257711882014261, 0.94239854921546895, 0.94221971935912685, 0.94204062935631749, 0.94186127931239483, 0.94168166933286579, 0.94150179952339041, 0.9413216699897814, 0.94114128083800441, 0.94096063217417747, 0.94077972410457189, 0.94059855673561099, 0.94041713017387096, 0.94023544452608032, 0.94005349989912013, 0.93987129640002376, 0.93968883413597659, 0.93950611321431676, 0.93932313374253407, 0.93913989582827084, 0.93895639957932087, 0.93877264510363068, 0.93858863250929803, 0.93840436190457277, 0.93821983339785686, 0.93803504709770325, 0.9378500031128173, 0.93766470155205539, 0.93747914252442577, 0.93729332613908811, 0.93710725250535321, 0.93692092173268349, 0.93673433393069239, 0.93654748920914499, 0.93636038767795715, 0.93617302944719571, 0.93598541462707896, 0.93579754332797549, 0.93560941566040556, 0.93542103173503943, 0.93523239166269878, 0.93504349555435573, 0.93485434352113284, 0.93466493567430342, 0.93447527212529113, 0.9342853529856705, 0.9340951783671656, 0.93390474838165161, 0.93371406314115346, 0.93352312275784632, 0.93333192734405557, 0.93314047701225644, 0.93294877187507441, 0.93275681204528449, 0.9325645976358119, 0.93237212875973119, 0.93217940553026701, 0.93198642806079335, 0.93179319646483405, 0.93159971085606208, 0.93140597134830017, 0.93121197805552025, 0.9310177310918436, 0.93082323057154071, 0.93062847660903114, 0.9304334693188836, 0.93023820881581609, 0.93004269521469507, 0.92984692863053631, 0.92965090917850424, 0.92945463697391195, 0.92925811213222143, 0.92906133476904307, 0.92886430500013606, 0.92866702294140779, 0.92846948870891444, 0.92827170241886003, 0.92807366418759729, 0.92787537413162691, 0.92767683236759801, 0.92747803901230741, 0.92727899418270021, 0.92707969799586942, 0.92688015056905571, 0.92668035201964771, 0.92648030246518176, 0.92628000202334204, 0.92607945081195986, 0.9258786489490145, 0.9256775965526326, 0.92547629374108786, 0.92527474063280168, 0.92507293734634266, 0.92487088400042627, 0.92466858071391544, 0.92446602760581986, 0.92426322479529632, 0.92406017240164862, 0.92385687054432719, 0.92365331934292916, 0.92344951891719862, 0.92324546938702601, 0.92304117087244852, 0.92283662349364959, 0.92263182737095906, 0.92242678262485356, 0.92222148937595527, 0.92201594774503315, 0.92181015785300202, 0.92160411982092272, 0.92139783377000206, 0.92119129982159298, 0.92098451809719384, 0.92077748871844922, 0.92057021180714904, 0.92036268748522909, 0.92015491587477038, 0.91994689709799982, 0.91973863127728928, 0.91953011853515632, 0.9193213589942637, 0.91911235277741898, 0.91890310000757547, 0.91869360080783102, 0.91848385530142851, 0.918273863611756, 0.91806362586234613, 0.9178531421768763, 0.91764241267916868, 0.91743143749319001, 0.91722021674305165, 0.91700875055300912, 0.91679703904746257, 0.91658508235095659, 0.91637288058817967, 0.91616043388396484, 0.9159477423632888, 0.91573480615127267, 0.91552162537318116, 0.91530820015442316, 0.91509453062055113, 0.91488061689726152, 0.91466645911039413, 0.91445205738593249, 0.91423741185000362, 0.91402252262887784, 0.91380738984896914, 0.91359201363683451, 0.91337639411917426, 0.91316053142283171, 0.91294442567479339, 0.91272807700218883, 0.91251148553229011, 0.91229465139251265, 0.91207757471041428, 0.91186025561369566, 0.91164269423020006, 0.91142489068791321, 0.91120684511496319, 0.91098855763962083, 0.91077002839029886, 0.91055125749555232, 0.91033224508407873, 0.91011299128471734, 0.90989349622644955, 0.9096737600383985, 0.90945378284982947, 0.90923356479014927, 0.90901310598890672, 0.90879240657579186, 0.90857146668063649, 0.90835028643341387, 0.9081288659642387, 0.90790720540336689, 0.9076853048811957, 0.90746316452826337, 0.90724078447524925, 0.90701816485297426, 0.9067953057923992, 0.90657220742462674, 0.9063488698808998, 0.90612529329260194, 0.90590147779125774, 0.90567742350853186, 0.90545313057622989, 0.90522859912629738, 0.90500382929082057, 0.90477882120202557, 0.90455357499227906, 0.90432809079408749, 0.90410236874009742, 0.90387640896309518, 0.90365021159600722, 0.90342377677189967, 0.90319710462397818, 0.9029701952855882, 0.90274304889021462, 0.90251566557148188, 0.90228804546315355, 0.90206018869913285, 0.90183209541346199, 0.90160376574032242, 0.90137519981403458, 0.90114639776905792, 0.90091735973999065, 0.90068808586157012, 0.9004585762686721, 0.90022883109631135, 0.89999885047964101, 0.89976863455395251, 0.89953818345467618, 0.89930749731738047, 0.89907657627777193, 0.89884542047169558, 0.8986140300351344, 0.89838240510420941, 0.8981505458151795, 0.89791845230444178, 0.8976861247085306, 0.89745356316411851, 0.8972207678080153, 0.89698773877716853, 0.89675447620866333, 0.89652098023972182, 0.89628725100770379, 0.89605328865010625, 0.89581909330456289, 0.89558466510884505, 0.89535000420086086, 0.89511511071865502, 0.89487998480040953, 0.89464462658444277, 0.89440903620921008, 0.89417321381330317, 0.89393715953545017, 0.89370087351451566, 0.89346435588950091, 0.89322760679954283, 0.89299062638391513, 0.89275341478202697, 0.89251597213342404, 0.89227829857778762, 0.89204039425493498, 0.89180225930481916, 0.89156389386752866, 0.89132529808328786, 0.89108647209245651, 0.89084741603552975, 0.8906081300531381, 0.89036861428604719, 0.8901288688751583, 0.88988889396150728, 0.8896486896862652, 0.88940825619073793, 0.88916759361636655, 0.88892670210472657, 0.8886855817975281, 0.88844423283661622, 0.88820265536397014, 0.88796084952170384, 0.88771881545206521, 0.88747655329743691, 0.88723406320033549, 0.8869913453034115, 0.88674839974944952, 0.88650522668136844, 0.88626182624222061, 0.88601819857519226, 0.88577434382360321, 0.88553026213090691, 0.8852859536406904, 0.88504141849667395, 0.88479665684271147, 0.8845516688227899, 0.88430645458102919, 0.88406101426168271, 0.88381534800913664, 0.88356945596791014, 0.88332333828265519, 0.88307699509815651, 0.88283042655933119, 0.88258363281122953, 0.88233661399903363, 0.88208937026805834, 0.88184190176375088, 0.88159420863169069, 0.88134629101758899, 0.88109814906728945, 0.88084978292676763, 0.88060119274213089, 0.88035237865961846, 0.88010334082560115, 0.87985407938658167, 0.87960459448919392, 0.87935488628020364, 0.87910495490650764, 0.87885480051513409, 0.87860442325324228, 0.87835382326812284, 0.87810300070719727, 0.877851955718018, 0.87760068844826833, 0.87734919904576225, 0.87709748765844453, 0.87684555443439072, 0.87659339952180626, 0.87634102306902761, 0.87608842522452135, 0.87583560613688416, 0.87558256595484318, 0.87532930482725535, 0.87507582290310748, 0.87482212033151674, 0.87456819726172963, 0.87431405384312266, 0.8740596902252018, 0.87380510655760257, 0.87355030299009007, 0.8732952796725586, 0.87304003675503195, 0.87278457438766277, 0.87252889272073297, 0.87227299190465368, 0.87201687208996459, 0.87176053342733462, 0.87150397606756091, 0.87124720016156965, 0.87099020586041553, 0.87073299331528164, 0.87047556267747961, 0.87021791409844895, 0.8699600477297581, 0.86970196372310293, 0.86944366223030756, 0.86918514340332431, 0.86892640739423299, 0.86866745435524151, 0.8684082844386849, 0.86814889779702653, 0.8678892945828568, 0.86762947494889342, 0.86736943904798169, 0.86710918703309414, 0.86684871905733019, 0.86658803527391637, 0.86632713583620635, 0.8660660208976807, 0.86580469061194631, 0.86554314513273711, 0.8652813846139138, 0.86501940920946307, 0.86475721907349845, 0.86449481436025966, 0.86423219522411254, 0.86396936181954931, 0.86370631430118783, 0.86344305282377243, 0.863179577542173, 0.86291588861138524, 0.86265198618653038, 0.86238787042285558, 0.86212354147573356, 0.86185899950066169, 0.86159424465326373, 0.86132927708928786, 0.86106409696460773, 0.86079870443522188, 0.860533099657254, 0.86026728278695264, 0.86000125398069083, 0.8597350133949665, 0.85946856118640225, 0.85920189751174492, 0.8589350225278658, 0.85866793639176087, 0.85840063926054977, 0.85813313129147661, 0.8578654126419093, 0.85759748346934006, 0.85732934393138449, 0.85706099418578241, 0.85679243439039676, 0.85652366470321462, 0.85625468528234616, 0.85598549628602505, 0.85571609787260816, 0.85544649020057584, 0.85517667342853121, 0.85490664771520042, 0.85463641321943284, 0.85436597010020032, 0.8540953185165977, 0.85382445862784218, 0.85355339059327373, 0.85328211457235481, 0.85301063072466987, 0.85273893920992605, 0.8524670401879525, 0.85219493381870026, 0.85192262026224252, 0.85165009967877436, 0.85137737222861265, 0.85110443807219593, 0.85083129737008423, 0.85055795028295944, 0.85028439697162428, 0.85001063759700313, 0.84973667232014194, 0.84946250130220713, 0.84918812470448646, 0.8489135426883887, 0.84863875541544331, 0.84836376304730066, 0.84808856574573155, 0.84781316367262749, 0.84753755699000044, 0.84726174585998282, 0.84698573044482695, 0.84670951090690594, 0.84643308740871237, 0.84615646011285917, 0.84587962918207893, 0.84560259477922428, 0.84532535706726741, 0.84504791620930009, 0.84477027236853353, 0.84449242570829863, 0.84421437639204533, 0.84393612458334277, 0.84365767044587958, 0.84337901414346295, 0.84310015584001929, 0.84282109569959385, 0.84254183388635018, 0.84226237056457121, 0.84198270589865776, 0.84170284005312945, 0.84142277319262404, 0.84114250548189784, 0.84086203708582485, 0.84058136816939766, 0.84030049889772651, 0.84001942943603947, 0.83973815994968248, 0.8394566906041192, 0.83917502156493073, 0.83889315299781586, 0.83861108506859017, 0.83832881794318748, 0.83804635178765796, 0.83776368676816926, 0.83748082305100602, 0.83719776080256958, 0.83691450018937807, 0.83663104137806654, 0.83634738453538648, 0.83606352982820598, 0.83577947742350922, 0.83549522748839711, 0.83521078019008654, 0.83492613569591057, 0.83464129417331812, 0.83435625578987405, 0.83407102071325934, 0.83378558911127021, 0.83349996115181879, 0.83321413700293268, 0.83292811683275492, 0.83264190080954359, 0.83235548910167245, 0.83206888187763006, 0.83178207930601999, 0.83149508155556073, 0.83120788879508589, 0.83092050119354344, 0.83063291891999613, 0.83034514214362121, 0.83005717103371035, 0.82976900575966939, 0.82948064649101871, 0.82919209339739264, 0.82890334664853937, 0.82861440641432127, 0.82832527286471458, 0.8280359461698088, 0.82774642649980779, 0.82745671402502807, 0.82716680891590033, 0.82687671134296803, 0.82658642147688843, 0.82629593948843127, 0.82600526554847975, 0.82571439982802997, 0.82542334249819049, 0.82513209373018293, 0.82484065369534165, 0.82454902256511309, 0.82425720051105622, 0.82396518770484273, 0.82367298431825609, 0.82338059052319201, 0.82308800649165814, 0.82279523239577435, 0.82250226840777207, 0.82220911469999425, 0.82191577144489569, 0.82162223881504293, 0.82132851698311349, 0.82103460612189627, 0.82074050640429164, 0.82044621800331075, 0.82015174109207589, 0.81985707584382028, 0.81956222243188792, 0.81926718102973339, 0.81897195181092208, 0.81867653494912962, 0.81838093061814221, 0.8180851389918562, 0.81778916024427817, 0.81749299454952484, 0.81719664208182285, 0.81690010301550864, 0.81660337752502865, 0.81630646578493882, 0.81600936796990453, 0.81571208425470099, 0.81541461481421229, 0.81511695982343224, 0.81481911945746355, 0.81452109389151806, 0.81422288330091641, 0.81392448786108829, 0.81362590774757204, 0.81332714313601473, 0.81302819420217176, 0.81272906112190713, 0.81242974407119317, 0.81213024322611038, 0.81183055876284738, 0.81153069085770069, 0.81123063968707498, 0.81093040542748263, 0.81062998825554389, 0.81032938834798607, 0.8100286058816446, 0.80972764103346195, 0.80942649398048827, 0.80912516489988007, 0.80882365396890199, 0.80852196136492493, 0.80822008726542682, 0.8079180318479926, 0.80761579529031347, 0.80731337777018752, 0.80701077946551925, 0.80670800055431935, 0.80640504121470491, 0.80610190162489903, 0.80579858196323095, 0.80549508240813594, 0.80519140313815474, 0.80488754433193421, 0.80458350616822671, 0.80427928882588973, 0.80397489248388687, 0.80367031732128646, 0.80336556351726229, 0.80306063125109306, 0.80275552070216283, 0.80245023204996002, 0.80214476547407809, 0.8018391211542153, 0.80153329927017414, 0.80122730000186193, 0.80092112352929012, 0.80061477003257431, 0.80030823969193454, 0.80000153268769458, 0.79969464920028233, 0.79938758941022936, 0.79908035349817119, 0.79877294164484658, 0.7984653540310982, 0.79815759083787197, 0.79784965224621673, 0.79754153843728504, 0.79723324959233222, 0.79692478589271687, 0.79661614751989995, 0.79630733465544568, 0.7959983474810205, 0.7956891861783939, 0.79537985092943719, 0.79507034191612447, 0.79476065932053197, 0.79445080332483786, 0.79414077411132267, 0.79383057186236838, 0.79352019676045904, 0.79320964898818036, 0.79289892872821943, 0.79258803616336526, 0.79227697147650766, 0.79196573485063815, 0.79165432646884915, 0.79134274651433423, 0.79103099517038777, 0.79071907262040519, 0.79040697904788226, 0.7900947146364159, 0.78978227956970293, 0.789469674031541, 0.78915689820582791, 0.78884395227656146, 0.78853083642783983, 0.78821755084386091, 0.78790409570892272, 0.78759047120742265, 0.78727667752385799, 0.78696271484282543, 0.7866485833490211, 0.78633428322724064, 0.78601981466237858, 0.78570517783942861, 0.78539037294348368, 0.7850754001597352, 0.78476025967347363, 0.78444495167008799, 0.7841294763350658, 0.78381383385399317, 0.78349802441255434, 0.78318204819653192, 0.78286590539180656, 0.78254959618435704, 0.78223312076025975, 0.78191647930568919, 0.78159967200691716, 0.78128269905031322, 0.78096556062234468, 0.78064825690957584, 0.78033078809866807, 0.78001315437638019, 0.77969535592956807, 0.77937739294518416, 0.77905926561027816, 0.77874097411199583, 0.77842251863758016, 0.77810389937437008, 0.77778511650980109, 0.77746617023140518, 0.77714706072681006, 0.77682778818373965, 0.77650835279001384, 0.77618875473354809, 0.77586899420235378, 0.77554907138453777, 0.77522898646830241, 0.77490873964194551, 0.77458833109385994, 0.7742677610125337, 0.77394702958655015, 0.77362613700458704, 0.77330508345541749, 0.77298386912790884, 0.77266249421102329, 0.77234095889381726, 0.77201926336544191, 0.7716974078151424, 0.77137539243225794, 0.77105321740622201, 0.77073088292656178, 0.77040838918289833, 0.77008573636494648, 0.7697629246625145, 0.76943995426550416, 0.76911682536391091, 0.76879353814782281, 0.76847009280742151, 0.76814648953298159, 0.76782272851487054, 0.76749880994354869, 0.76717473400956882, 0.76685050090357643, 0.76652611081630984, 0.76620156393859906, 0.7658768604613666, 0.76555200057562756, 0.76522698447248816, 0.76490181234314747, 0.76457648437889536, 0.7642510007711143, 0.76392536171127778, 0.7635995673909507, 0.76327361800178972, 0.76294751373554237, 0.76262125478404741, 0.76229484133923453, 0.76196827359312436, 0.76164155173782822, 0.76131467596554847, 0.76098764646857719, 0.76066046343929783, 0.76033312707018363, 0.76000563755379802, 0.75967799508279477, 0.75935019984991758, 0.75902225204799967, 0.75869415186996458, 0.75836589950882494, 0.75803749515768337, 0.75770893900973157, 0.7573802312582506, 0.75705137209661089, 0.75672236171827179, 0.75639320031678148, 0.75606388808577729, 0.75573442521898526, 0.75540481191021958, 0.75507504835338346, 0.75474513474246829, 0.75441507127155361, 0.75408485813480741, 0.75375449552648544, 0.75342398364093166, 0.75309332267257778, 0.75276251281594275, 0.7524315542656338, 0.75210044721634528, 0.75176919186285884, 0.75143778840004349, 0.75110623702285539, 0.75077453792633775, 0.75044269130562047, 0.7501106973559204, 0.74977855627254097, 0.74944626825087246, 0.74911383348639093, 0.74878125217465952, 0.74844852451132737, 0.74811565069212915, 0.74778263091288633, 0.74744946536950563, 0.74711615425797984, 0.74678269777438744, 0.74644909611489207, 0.74611534947574309, 0.74578145805327511, 0.74544742204390757, 0.74511324164414561, 0.74477891705057875, 0.74444444845988156, 0.74410983606881342, 0.743775080074218, 0.74344018067302375, 0.74310513806224332, 0.74276995243897348, 0.74243462400039562, 0.7420991529437746, 0.74176353946645945, 0.74142778376588281, 0.74109188603956144, 0.74075584648509496, 0.74041966530016701, 0.74008334268254428, 0.7397468788300765, 0.73941027394069703, 0.73907352821242156, 0.73873664184334897, 0.73839961503166118, 0.73806244797562182, 0.73772514087357788, 0.73738769392395864, 0.73705010732527498, 0.73671238127612071, 0.73637451597517145, 0.73603651162118433, 0.73569836841299896, 0.73536008654953589, 0.73502166622979781, 0.73468310765286882, 0.73434441101791403, 0.73400557652417997, 0.73366660437099429, 0.73332749475776549, 0.73298824788398309, 0.73264886394921735, 0.73230934315311891, 0.7319696856954192, 0.73162989177593007, 0.7312899615945434, 0.73094989535123145, 0.73060969324604619, 0.73026935547911997, 0.72992888225066477, 0.72958827376097202, 0.72924753021041311, 0.7289066517994387, 0.72856563872857849, 0.7282244911984419, 0.7278832094097174, 0.72754179356317195, 0.72720024385965187, 0.72685856050008191, 0.72651674368546582, 0.72617479361688553, 0.72583271049550124, 0.72549049452255188, 0.72514814589935439, 0.72480566482730335, 0.7244630515078716, 0.72412030614261003, 0.72377742893314645, 0.72343442008118719, 0.72309127978851506, 0.72274800825699081, 0.72240460568855247, 0.72206107228521466, 0.72171740824906916, 0.72137361378228504, 0.72102968908710741, 0.72068563436585831, 0.72034144982093651, 0.7199971356548166, 0.71965269207005, 0.71930811926926386, 0.71896341745516146, 0.71861858683052215, 0.71827362759820068, 0.71792853996112771, 0.71758332412230974, 0.71723798028482788, 0.71689250865183929, 0.71654690942657595, 0.71620118281234513, 0.71585532901252868, 0.71550934823058354, 0.71516324067004133, 0.7148170065345083, 0.71447064602766475, 0.7141241593532659, 0.71377754671514104, 0.71343080831719319, 0.71308394436339984, 0.71273695505781198, 0.71238984060455435, 0.71204260120782581, 0.71169523707189808, 0.71134774840111648, 0.71100013539989992, 0.71065239827273985, 0.71030453722420128, 0.70995655245892186, 0.70960844418161195, 0.70926021259705485, 0.70891185791010614, 0.70856338032569388, 0.70821478004881866, 0.70786605728455276, 0.70751721223804087, 0.70716824511449961, 0.70681915611921731, 0.70646994545755404, 0.70612061333494147, 0.70577115995688267, 0.70542158552895196, 0.70507189025679518, 0.70472207434612877, 0.70437213800274079, 0.70402208143248934, 0.70367190484130404, 0.70332160843518454, 0.70297119242020123, 0.70262065700249487, 0.70227000238827653, 0.70191922878382706, 0.70156833639549765, 0.70121732542970927, 0.70086619609295253, 0.70051494859178787, 0.7001635831328451, 0.69981209992282345, 0.69946049916849151, 0.69910878107668684, 0.69875694585431614, 0.69840499370835518, 0.69805292484584813, 0.69770073947390809, 0.69734843779971678, 0.69699602003052408, 0.69664348637364826, 0.69629083703647576, 0.6959380722264612, 0.69558519215112702, 0.69523219701806327, 0.69487908703492818, 0.69452586240944725, 0.69417252334941315, 0.69381907006268628, 0.69346550275719432, 0.69311182164093155, 0.69275802692195954, 0.69240411880840647, 0.69205009750846758, 0.69169596323040439, 0.69134171618254492, 0.69098735657328358, 0.69063288461108119, 0.69027830050446426, 0.68992360446202561, 0.68956879669242377, 0.68921387740438278, 0.68885884680669296, 0.68850370510820913, 0.68814845251785239, 0.68779308924460869, 0.6874376154975288, 0.68708203148572899, 0.68672633741839018, 0.68637053350475785, 0.68601461995414248, 0.6856585969759188, 0.68530246477952583, 0.68494622357446711, 0.68458987357030998, 0.68423341497668622, 0.68387684800329107, 0.68352017285988365, 0.68316338975628677, 0.68280649890238698, 0.68244950050813369, 0.68209239478353989, 0.68173518193868188, 0.68137786218369856, 0.68102043572879212, 0.68066290278422714, 0.68030526356033116, 0.67994751826749411, 0.67958966711616831, 0.67923171031686824, 0.67887364808017092, 0.67851548061671507, 0.67815720813720115, 0.67779883085239201, 0.67744034897311134, 0.67708176271024523, 0.67672307227474038, 0.67636427787760534, 0.67600537972990959, 0.6756463780427836, 0.67528727302741876, 0.67492806489506751, 0.67456875385704251, 0.67420934012471723, 0.67384982390952575, 0.6734902054229619, 0.67313048487658, 0.67277066248199457, 0.67241073845087962, 0.67205071299496955, 0.6716905863260576, 0.67133035865599722, 0.67097003019670121, 0.67060960116014123, 0.67024907175834858, 0.66988844220341348, 0.66952771270748479, 0.66916688348277065, 0.66880595474153737, 0.66844492669611, 0.66808379955887232, 0.66772257354226583, 0.66736124885879056, 0.6669998257210048, 0.66663830434152394, 0.66627668493302206, 0.66591496770823055, 0.66555315287993821, 0.66519124066099145, 0.66482923126429383, 0.66446712490280613, 0.66410492178954628, 0.66374262213758906, 0.66338022616006587, 0.66301773407016518, 0.66265514608113152, 0.66229246240626605, 0.66192968325892654, 0.66156680885252617, 0.66120383940053495, 0.66084077511647832, 0.66047761621393763, 0.66011436290655001, 0.65975101540800785, 0.65938757393205927, 0.65902403869250747, 0.65866040990321095, 0.65829668777808292, 0.65793287253109201, 0.65756896437626122, 0.65720496352766844, 0.6568408701994457, 0.65647668460578013, 0.65611240696091255, 0.65574803747913801, 0.65538357637480571, 0.65501902386231903, 0.65465438015613442, 0.65428964547076252, 0.65392482002076746, 0.65355990402076658, 0.65319489768543049, 0.65282980122948309, 0.65246461486770113, 0.65209933881491466, 0.65173397328600569, 0.6513685184959096, 0.6510029746596141, 0.65063734199215895, 0.65027162070863676, 0.64990581102419176, 0.64953991315402027, 0.64917392731337076, 0.64880785371754313, 0.64844169258188911, 0.64807544412181195, 0.64770910855276598, 0.64734268609025714, 0.64697617694984233, 0.64660958134712931, 0.64624289949777691, 0.64587613161749469, 0.6455092779220426, 0.64514233862723114, 0.64477531394892162, 0.6444082041030248, 0.64404100930550212, 0.64367372977236481, 0.64330636571967392, 0.64293891736354036, 0.64257138492012433, 0.64220376860563588, 0.64183606863633424, 0.64146828522852772, 0.64110041859857381, 0.64073246896287905, 0.64036443653789865, 0.63999632154013675, 0.63962812418614567, 0.6392598446925265, 0.63889148327592893, 0.63852304015304995, 0.63815451554063551, 0.6377859096554791, 0.63741722271442192, 0.63704845493435314, 0.63667960653220934, 0.63631067772497452, 0.63594166872967994, 0.63557257976340398, 0.63520341104327238, 0.63483416278645755, 0.63446483521017871, 0.63409542853170153, 0.63372594296833884, 0.63335637873744921, 0.63298673605643774, 0.63261701514275592, 0.63224721621390079, 0.63187733948741576, 0.63150738518088956, 0.63113735351195677, 0.63076724469829781, 0.63039705895763776, 0.63002679650774751, 0.62965645756644317, 0.62928604235158514, 0.62891555108107944, 0.62854498397287661, 0.6281743412449714, 0.62780362311540383, 0.62743282980225734, 0.62706196152366034, 0.62669101849778519, 0.62632000094284779, 0.62594890907710843, 0.62557774311887104, 0.62520650328648264, 0.6248351897983343, 0.62446380287286019, 0.62409234272853742, 0.62372080958388676, 0.62334920365747126, 0.62297752516789728, 0.62260577433381381, 0.62223395137391213, 0.62186205650692605, 0.62149008995163202, 0.62111805192684799, 0.62074594265143468, 0.6203737623442942, 0.62000151122437075, 0.61962918951065005, 0.61925679742215922, 0.61888433517796715, 0.61851180299718367, 0.61813920109895981, 0.61776652970248769, 0.61739378902700048, 0.61702097929177169, 0.61664810071611575, 0.61627515351938766, 0.61590213792098236, 0.61552905414033565, 0.61515590239692275, 0.61478268291025939, 0.61440939589990118, 0.61403604158544289, 0.6136626201865194, 0.6132891319228051, 0.61291557701401311, 0.61254195567989633, 0.61216826814024683, 0.61179451461489498, 0.61142069532371068, 0.61104681048660181, 0.61067286032351542, 0.61029884505443688, 0.6099247648993894, 0.60955062007843486, 0.60917641081167317, 0.60880213731924182, 0.60842779982131634, 0.6080533985381098, 0.6076789336898728, 0.60730440549689346, 0.60692981417949687, 0.60655515995804565, 0.60618044305293928, 0.60580566368461386, 0.60543082207354237, 0.60505591844023487, 0.60468095300523705, 0.60430592598913169, 0.60393083761253763, 0.60355568809610927, 0.60318047766053784, 0.60280520652654968, 0.60242987491490718, 0.60205448304640852, 0.6016790311418867, 0.6013035194222105, 0.60092794810828409, 0.60055231742104598, 0.60017662758147017, 0.59980087881056554, 0.59942507132937506, 0.59904920535897688, 0.59867328112048301, 0.59829729883504013, 0.59792125872382895, 0.59754516100806421, 0.59716900590899424, 0.59679279364790183, 0.5964165244461026, 0.59604019852494616, 0.59566381610581554, 0.59528737741012638, 0.59491088265932834, 0.59453433207490314, 0.59415772587836602, 0.59378106429126487, 0.59340434753517968, 0.59302757583172327, 0.59265074940254103, 0.59227386846930985, 0.59189693325373915, 0.59151994397757046, 0.5911429008625767, 0.59076580413056257, 0.59038865400336438, 0.59001145070284977, 0.58963419445091791, 0.58925688546949884, 0.58887952398055354, 0.58850211020607446, 0.58812464436808398, 0.58774712668863571, 0.58736955738981367, 0.58699193669373195, 0.5866142648225352, 0.58623654199839803, 0.58585876844352502, 0.58548094438015064, 0.58510307003053907, 0.58472514561698397, 0.58434717136180869, 0.58396914748736561, 0.5835910742160364, 0.58321295177023214, 0.58283478037239211, 0.58245656024498504, 0.58207829161050795, 0.5816999746914866, 0.5813216097104752, 0.58094319689005591, 0.58056473645283935, 0.58018622862146418, 0.57980767361859653, 0.5794290716669307, 0.57905042298918852, 0.57867172780811915, 0.57829298634649928, 0.57791419882713269, 0.57753536547285023, 0.57715648650651008, 0.57677756215099674, 0.57639859262922166, 0.57601957816412308, 0.57564051897866508, 0.57526141529583863, 0.57488226733866077, 0.5745030753301742, 0.57412383949344814, 0.57374456005157681, 0.57336523722768085, 0.57298587124490619, 0.57260646232642376, 0.57222701069543025, 0.57184751657514732, 0.57146798018882139, 0.57108840175972397, 0.57070878151115156, 0.57032911966642463, 0.56994941644888863, 0.56956967208191311, 0.56918988678889193, 0.56881006079324314, 0.56843019431840824, 0.56805028758785303, 0.56767034082506718, 0.56729035425356311, 0.56691032809687736, 0.56653026257856953, 0.56615015792222234, 0.56577001435144159, 0.56538983208985594, 0.56500961136111671, 0.56462935238889811, 0.56424905539689663, 0.56386872060883109, 0.56348834824844296, 0.56310793853949526, 0.56272749170577308, 0.56234700797108383, 0.56196648755925604, 0.56158593069414031, 0.56120533759960811, 0.56082470849955279, 0.56044404361788858, 0.56006334317855078, 0.55968260740549569, 0.55930183652270038, 0.55892103075416255, 0.55854019032390023, 0.55815931545595243, 0.55777840637437759, 0.55739746330325513, 0.55701648646668367, 0.55663547608878217, 0.55625443239368944, 0.55587335560556328, 0.55549224594858171, 0.55511110364694161, 0.55472992892485906, 0.55434872200656937, 0.55396748311632693, 0.55358621247840445, 0.55320491031709396, 0.55282357685670536, 0.55244221232156754, 0.55206081693602738, 0.55167939092444984, 0.55129793451121811, 0.55091644792073335, 0.55053493137741394, 0.55015338510569645, 0.54977180933003467, 0.54939020427489982, 0.54900857016478044, 0.54862690722418173, 0.5482452156776263, 0.54786349574965365, 0.5474817476648195, 0.54709997164769664, 0.54671816792287398, 0.54633633671495663, 0.54595447824856635, 0.54557259274834058, 0.54519068043893248, 0.54480874154501147, 0.54442677629126235, 0.54404478490238528, 0.54366276760309606, 0.5432807246181256, 0.54289865617222, 0.54251656249014024, 0.54213444379666209, 0.54175230031657617, 0.54137013227468789, 0.54098793989581651, 0.54060572340479618, 0.54022348302647505, 0.53984121898571502, 0.53945893150739255, 0.53907662081639718, 0.53869428713763257, 0.53831193069601579, 0.53792955171647727, 0.53754715042396062, 0.53716472704342288, 0.53678228179983378, 0.53639981491817579, 0.5360173266234447, 0.5356348171406482, 0.53525228669480696, 0.53486973551095374, 0.53448716381413341, 0.53410457182940319, 0.53372195978183201, 0.53333932789650074, 0.53295667639850197, 0.53257400551293943, 0.5321913154649287, 0.5318086064795966, 0.5314258787820807, 0.53104313259753011, 0.53066036815110429, 0.53027758566797389, 0.52989478537332002, 0.52951196749233398, 0.52912913225021785, 0.52874627987218381, 0.52836341058345393, 0.52798052460926026, 0.52759762217484507, 0.52721470350545963, 0.52683176882636529, 0.52644881836283275, 0.52606585234014169, 0.52568287098358135, 0.52529987451844962, 0.52491686317005359, 0.52453383716370905, 0.52415079672474008, 0.52376774207847965, 0.52338467345026896, 0.52300159106545729, 0.5226184951494024, 0.52223538592746932, 0.52185226362503168, 0.52146912846747051, 0.52108598068017398, 0.52070282048853833, 0.52031964811796694, 0.51993646379386993, 0.51955326774166488, 0.51917006018677636, 0.51878684135463526, 0.51840361147067948, 0.51802037076035312, 0.51763711944910695, 0.51725385776239796, 0.5168705859256888, 0.51648730416444866, 0.5161040127041524, 0.51572071177028023, 0.51533740158831831, 0.51495408238375828, 0.51457075438209687, 0.51418741780883614, 0.51380407288948293, 0.51342071984954929, 0.51303735891455204, 0.51265399031001235, 0.51227061426145615, 0.5118872309944138, 0.51150384073441968, 0.51112044370701248, 0.5107370401377348, 0.51035363025213298, 0.50997021427575728, 0.50958679243416138, 0.50920336495290242, 0.50881993205754106, 0.50843649397364088, 0.50805305092676867, 0.5076696031424941, 0.50728615084638951, 0.50690269426403023, 0.50651923362099371, 0.50613576914285996, 0.50575230105521141, 0.50536882958363227, 0.504985354953709, 0.50460187739103002, 0.50421839712118488, 0.50383491436976557, 0.50345142936236498, 0.5030679423245773, 0.50268445348199819, 0.50230096306022431, 0.50191747128485309, 0.50153397838148306, 0.50115048457571298, 0.50076699009314241, 0.50038349515937142, 0.5, 0.49961650484062864, 0.49923300990685771, 0.49884951542428713, 0.498466021618517, 0.49808252871514691, 0.49769903693977574, 0.49731554651800192, 0.49693205767542281, 0.49654857063763513, 0.49616508563023454, 0.49578160287881512, 0.49539812260897009, 0.49501464504629106, 0.49463117041636778, 0.49424769894478865, 0.4938642308571401, 0.49348076637900634, 0.49309730573596988, 0.49271384915361049, 0.49233039685750596, 0.49194694907323144, 0.49156350602635918, 0.49118006794245894, 0.49079663504709764, 0.49041320756583873, 0.49002978572424277, 0.48964636974786713, 0.48926295986226526, 0.48887955629298763, 0.48849615926558038, 0.4881127690055862, 0.48772938573854391, 0.48734600968998776, 0.48696264108544807, 0.48657928015045082, 0.48619592711051718, 0.48581258219116391, 0.48542924561790318, 0.48504591761624172, 0.48466259841168174, 0.48427928822971988, 0.48389598729584771, 0.4835126958355514, 0.48312941407431126, 0.48274614223760209, 0.4823628805508931, 0.48197962923964693, 0.48159638852932057, 0.48121315864536479, 0.48082993981322364, 0.48044673225833512, 0.48006353620613013, 0.47968035188203312, 0.47929717951146172, 0.47891401931982608, 0.4785308715325296, 0.47814773637496832, 0.47776461407253068, 0.47738150485059772, 0.47699840893454276, 0.4766153265497311, 0.47623225792152041, 0.47584920327525998, 0.47546616283629101, 0.47508313682994641, 0.47470012548155038, 0.4743171290164187, 0.47393414765985842, 0.47355118163716736, 0.47316823117363471, 0.47278529649454049, 0.47240237782515504, 0.4720194753907398, 0.47163658941654618, 0.47125372012781624, 0.47087086774978221, 0.47048803250766608, 0.47010521462668003, 0.46972241433202616, 0.46933963184889571, 0.46895686740246995, 0.46857412121791936, 0.46819139352040345, 0.46780868453507135, 0.46742599448706063, 0.46704332360149808, 0.46666067210349926, 0.46627804021816799, 0.46589542817059681, 0.4655128361858667, 0.46513026448904637, 0.46474771330519304, 0.46436518285935185, 0.46398267337655535, 0.46360018508182427, 0.46321771820016633, 0.46283527295657712, 0.46245284957603944, 0.46207044828352284, 0.46168806930398426, 0.46130571286236755, 0.46092337918360293, 0.46054106849260751, 0.46015878101428498, 0.45977651697352501, 0.45939427659520388, 0.45901206010418349, 0.45862986772531217, 0.45824769968342383, 0.45786555620333802, 0.45748343750985987, 0.45710134382778012, 0.45671927538187446, 0.45633723239690394, 0.45595521509761483, 0.45557322370873771, 0.45519125845498859, 0.45480931956106757, 0.45442740725165948, 0.4540455217514337, 0.45366366328504337, 0.45328183207712608, 0.45290002835230347, 0.4525182523351805, 0.4521365042503464, 0.45175478432237376, 0.45137309277581839, 0.45099142983521967, 0.45060979572510024, 0.45022819066996533, 0.44984661489430366, 0.44946506862258612, 0.44908355207926676, 0.44870206548878194, 0.44832060907555021, 0.44793918306397268, 0.44755778767843257, 0.4471764231432947, 0.44679508968290615, 0.44641378752159561, 0.44603251688367318, 0.44565127799343074, 0.44527007107514105, 0.44488889635305845, 0.44450775405141835, 0.44412664439443672, 0.44374556760631062, 0.44336452391121789, 0.44298351353331644, 0.44260253669674493, 0.44222159362562241, 0.44184068454404762, 0.44145980967609977, 0.44107896924583756, 0.44069816347729962, 0.44031739259450436, 0.43993665682144928, 0.43955595638211142, 0.43917529150044732, 0.43879466240039189, 0.43841406930585974, 0.43803351244074396, 0.43765299202891617, 0.43727250829422692, 0.43689206146050485, 0.43651165175155704, 0.43613127939116891, 0.43575094460310343, 0.43537064761110189, 0.4349903886388834, 0.43461016791014417, 0.43422998564855841, 0.43384984207777771, 0.43346973742143047, 0.4330896719031227, 0.43270964574643694, 0.43232965917493288, 0.43194971241214697, 0.43156980568159187, 0.43118993920675697, 0.43081011321110813, 0.43043032791808689, 0.43005058355111137, 0.42967088033357542, 0.42929121848884849, 0.42891159824027603, 0.42853201981117872, 0.42815248342485279, 0.42777298930456986, 0.4273935376735763, 0.42701412875509387, 0.42663476277231915, 0.42625543994842324, 0.42587616050655197, 0.4254969246698258, 0.42511773266133923, 0.42473858470416137, 0.42435948102133492, 0.42398042183587697, 0.42360140737077834, 0.42322243784900332, 0.42284351349348992, 0.42246463452714977, 0.42208580117286743, 0.42170701365350077, 0.4213282721918809, 0.42094957701081148, 0.42057092833306936, 0.42019232638140352, 0.41981377137853587, 0.41943526354716065, 0.41905680310994409, 0.4186783902895248, 0.41830002530851346, 0.41792170838949211, 0.41754343975501501, 0.417165219627608, 0.41678704822976798, 0.4164089257839636, 0.41603085251263444, 0.41565282863819131, 0.41527485438301609, 0.41489692996946098, 0.41451905561984936, 0.41414123155647509, 0.41376345800160202, 0.4133857351774648, 0.41300806330626816, 0.41263044261018639, 0.4122528733113644, 0.41187535563191607, 0.41149788979392565, 0.41112047601944646, 0.41074311453050127, 0.41036580554908209, 0.40998854929715028, 0.40961134599663573, 0.40923419586943749, 0.40885709913742341, 0.40848005602242954, 0.40810306674626085, 0.40772613153069026, 0.40734925059745908, 0.40697242416827673, 0.40659565246482038, 0.40621893570873518, 0.40584227412163398, 0.40546566792509692, 0.40508911734067177, 0.40471262258987367, 0.40433618389418458, 0.40395980147505384, 0.4035834755538974, 0.40320720635209817, 0.40283099409100576, 0.4024548389919359, 0.40207874127617105, 0.40170270116495993, 0.40132671887951704, 0.40095079464102318, 0.400574928670625, 0.40019912118943451, 0.39982337241852983, 0.39944768257895408, 0.39907205189171596, 0.3986964805777895, 0.39832096885811336, 0.39794551695359154, 0.39757012508509282, 0.39719479347345038, 0.39681952233946222, 0.39644431190389079, 0.39606916238746248, 0.39569407401086831, 0.39531904699476295, 0.39494408155976518, 0.39456917792645763, 0.39419433631538625, 0.39381955694706078, 0.39344484004195435, 0.39307018582050313, 0.39269559450310659, 0.39232106631012731, 0.39194660146189025, 0.39157220017868377, 0.39119786268075823, 0.39082358918832683, 0.39044937992156514, 0.39007523510061071, 0.38970115494556323, 0.38932713967648463, 0.38895318951339825, 0.38857930467628943, 0.38820548538510502, 0.38783173185975323, 0.38745804432010367, 0.38708442298598694, 0.38671086807719501, 0.38633737981348065, 0.38596395841455716, 0.38559060410009888, 0.38521731708974061, 0.38484409760307731, 0.3844709458596644, 0.38409786207901764, 0.38372484648061239, 0.38335189928388425, 0.38297902070822831, 0.38260621097299952, 0.38223347029751231, 0.38186079890104024, 0.38148819700281639, 0.38111566482203296, 0.38074320257784078, 0.38037081048935001, 0.37999848877562931, 0.3796262376557058, 0.37925405734856543, 0.37888194807315201, 0.37850991004836809, 0.378137943493074, 0.37776604862608798, 0.37739422566618619, 0.37702247483210277, 0.37665079634252879, 0.37627919041611335, 0.37590765727146269, 0.37553619712713993, 0.37516481020166581, 0.37479349671351742, 0.37442225688112907, 0.37405109092289157, 0.37367999905715227, 0.37330898150221492, 0.37293803847633977, 0.37256717019774277, 0.37219637688459628, 0.3718256587550286, 0.37145501602712344, 0.37108444891892056, 0.37071395764841486, 0.37034354243355688, 0.36997320349225249, 0.36960294104236224, 0.36923275530170224, 0.36886264648804323, 0.36849261481911055, 0.3681226605125843, 0.36775278378609921, 0.36738298485724408, 0.36701326394356226, 0.36664362126255085, 0.36627405703166116, 0.36590457146829847, 0.3655351647898214, 0.36516583721354245, 0.36479658895672762, 0.36442742023659602, 0.36405833127032011, 0.36368932227502559, 0.36332039346779066, 0.36295154506564686, 0.36258277728557808, 0.3622140903445209, 0.36184548445936454, 0.36147695984695005, 0.36110851672407118, 0.3607401553074735, 0.36037187581385444, 0.36000367845986336, 0.35963556346210146, 0.35926753103712106, 0.3588995814014263, 0.35853171477147239, 0.35816393136366576, 0.35779623139436412, 0.35742861507987567, 0.35706108263645969, 0.35669363428032619, 0.3563262702276353, 0.35595899069449788, 0.35559179589697532, 0.35522468605107849, 0.35485766137276886, 0.35449072207795751, 0.35412386838250537, 0.35375710050222314, 0.35339041865287069, 0.35302382305015767, 0.35265731390974286, 0.35229089144723402, 0.35192455587818805, 0.35155830741811089, 0.35119214628245687, 0.35082607268662924, 0.35046008684597985, 0.35009418897580835, 0.34972837929136336, 0.34936265800784105, 0.34899702534038596, 0.34863148150409051, 0.34826602671399437, 0.34790066118508545, 0.34753538513229887, 0.34717019877051691, 0.34680510231456951, 0.34644009597923353, 0.34607517997923254, 0.34571035452923754, 0.34534561984386569, 0.34498097613768108, 0.34461642362519429, 0.3442519625208621, 0.34388759303908756, 0.34352331539421999, 0.3431591298005543, 0.34279503647233167, 0.34243103562373883, 0.34206712746890799, 0.34170331222191713, 0.34133959009678916, 0.34097596130749253, 0.34061242606794084, 0.34024898459199215, 0.33988563709345004, 0.33952238378606248, 0.33915922488352174, 0.33879616059946505, 0.33843319114747389, 0.33807031674107357, 0.33770753759373395, 0.33734485391886859, 0.33698226592983488, 0.33661977383993413, 0.33625737786241106, 0.33589507821045372, 0.33553287509719398, 0.33517076873570628, 0.33480875933900855, 0.33444684712006184, 0.33408503229176945, 0.33372331506697794, 0.33336169565847606, 0.33300017427899531, 0.33263875114120944, 0.33227742645773423, 0.33191620044112768, 0.33155507330389, 0.33119404525846274, 0.33083311651722941, 0.33047228729251521, 0.33011155779658657, 0.32975092824165153, 0.32939039883985888, 0.32902996980329891, 0.32866964134400289, 0.32830941367394251, 0.32794928700503057, 0.32758926154912038, 0.32722933751800548, 0.32686951512342, 0.32650979457703821, 0.32615017609047431, 0.32579065987528277, 0.32543124614295754, 0.32507193510493254, 0.32471272697258124, 0.32435362195721651, 0.32399462027009041, 0.32363572212239466, 0.32327692772525962, 0.32291823728975477, 0.32255965102688866, 0.3222011691476081, 0.32184279186279885, 0.32148451938328504, 0.32112635191982908, 0.32076828968313176, 0.32041033288383181, 0.32005248173250589, 0.31969473643966895, 0.31933709721577286, 0.31897956427120788, 0.31862213781630144, 0.31826481806131812, 0.31790760521646011, 0.31755049949186637, 0.31719350109761307, 0.31683661024371323, 0.31647982714011647, 0.31612315199670904, 0.31576658502331389, 0.31541012642969002, 0.31505377642553289, 0.31469753522047422, 0.3143414030240812, 0.31398538004585758, 0.31362946649524215, 0.31327366258160982, 0.31291796851427106, 0.3125623845024712, 0.31220691075539142, 0.31185154748214766, 0.31149629489179087, 0.31114115319330715, 0.31078612259561722, 0.31043120330757634, 0.3100763955379745, 0.30972169949553574, 0.30936711538891881, 0.30901264342671642, 0.30865828381745514, 0.30830403676959567, 0.30794990249153253, 0.30759588119159359, 0.30724197307804058, 0.30688817835906856, 0.30653449724280568, 0.30618092993731372, 0.3058274766505869, 0.30547413759055281, 0.30512091296507182, 0.30476780298193673, 0.30441480784887309, 0.30406192777353891, 0.30370916296352424, 0.30335651362635174, 0.30300397996947603, 0.30265156220028322, 0.30229926052609191, 0.30194707515415187, 0.30159500629164482, 0.30124305414568386, 0.30089121892331322, 0.30053950083150854, 0.30018790007717666, 0.29983641686715501, 0.29948505140821213, 0.29913380390704758, 0.29878267457029078, 0.29843166360450246, 0.29808077121617299, 0.29772999761172347, 0.29737934299750513, 0.29702880757979877, 0.29667839156481546, 0.29632809515869607, 0.29597791856751066, 0.29562786199725932, 0.29527792565387123, 0.29492810974320488, 0.2945784144710481, 0.29422884004311745, 0.29387938666505853, 0.29353005454244607, 0.29318084388078275, 0.29283175488550045, 0.29248278776195924, 0.29213394271544735, 0.29178521995118151, 0.29143661967430612, 0.29108814208989386, 0.29073978740294515, 0.29039155581838794, 0.29004344754107825, 0.28969546277579883, 0.28934760172726021, 0.28899986460010019, 0.28865225159888347, 0.28830476292810214, 0.2879573987921743, 0.28761015939544565, 0.28726304494218813, 0.28691605563660016, 0.2865691916828067, 0.28622245328485907, 0.2858758406467341, 0.28552935397233525, 0.28518299346549181, 0.28483675932995867, 0.28449065176941657, 0.28414467098747143, 0.28379881718765498, 0.28345309057342405, 0.28310749134816071, 0.28276201971517212, 0.28241667587769048, 0.28207146003887229, 0.28172637240179943, 0.28138141316947796, 0.28103658254483854, 0.28069188073073631, 0.28034730792995011, 0.2800028643451834, 0.27965855017906355, 0.27931436563414164, 0.27897031091289259, 0.27862638621771507, 0.27828259175093084, 0.27793892771478546, 0.27759539431144753, 0.27725199174300907, 0.2769087202114851, 0.27656557991881303, 0.27622257106685355, 0.27587969385739008, 0.27553694849212834, 0.27519433517269665, 0.27485185410064578, 0.27450950547744812, 0.27416728950449876, 0.27382520638311458, 0.27348325631453418, 0.2731414394999182, 0.27279975614034824, 0.27245820643682817, 0.27211679059028271, 0.27177550880155799, 0.27143436127142145, 0.27109334820056152, 0.27075246978958695, 0.27041172623902798, 0.27007111774933523, 0.26973064452087991, 0.26939030675395392, 0.26905010464876872, 0.26871003840545665, 0.26837010822406993, 0.26803031430458069, 0.26769065684688104, 0.26735113605078281, 0.26701175211601702, 0.26667250524223457, 0.26633339562900576, 0.26599442347582003, 0.26565558898208619, 0.26531689234713129, 0.26497833377020225, 0.26463991345046423, 0.26430163158700115, 0.26396348837881561, 0.26362548402482872, 0.26328761872387929, 0.26294989267472502, 0.26261230607604147, 0.26227485912642201, 0.2619375520243783, 0.26160038496833904, 0.26126335815665103, 0.2609264717875785, 0.26058972605930303, 0.2602531211699235, 0.25991665731745595, 0.2595803346998331, 0.25924415351490515, 0.25890811396043867, 0.25857221623411719, 0.25823646053354077, 0.25790084705622562, 0.2575653759996045, 0.25723004756102658, 0.25689486193775679, 0.25655981932697625, 0.25622491992578211, 0.25589016393118669, 0.25555555154011844, 0.25522108294942125, 0.25488675835585439, 0.2545525779560926, 0.25421854194672511, 0.25388465052425702, 0.25355090388510804, 0.25321730222561262, 0.25288384574202011, 0.25255053463049454, 0.25221736908711384, 0.25188434930787096, 0.25155147548867274, 0.25121874782534043, 0.25088616651360923, 0.25055373174912776, 0.25022144372745914, 0.24988930264407971, 0.24955730869437964, 0.24922546207366231, 0.24889376297714472, 0.24856221159995662, 0.24823080813714127, 0.24789955278365483, 0.2475684457343662, 0.24723748718405741, 0.24690667732742244, 0.2465760163590684, 0.24624550447351462, 0.2459151418651927, 0.24558492872844645, 0.24525486525753198, 0.24492495164661671, 0.24459518808978054, 0.24426557478101485, 0.24393611191422265, 0.24360679968321863, 0.24327763828172838, 0.24294862790338922, 0.24261976874174945, 0.24229106099026854, 0.24196250484231663, 0.24163410049117517, 0.24130584813003558, 0.24097774795200039, 0.24064980015008253, 0.24032200491720518, 0.23999436244620215, 0.23966687292981653, 0.23933953656070228, 0.23901235353142286, 0.2386853240344517, 0.23835844826217178, 0.23803172640687587, 0.23770515866076564, 0.2373787452159527, 0.23705248626445768, 0.23672638199821028, 0.23640043260904947, 0.23607463828872244, 0.23574899922888587, 0.2354235156211047, 0.2350981876568527, 0.23477301552751179, 0.23444799942437267, 0.23412313953863345, 0.2337984360614011, 0.23347388918369028, 0.23314949909642352, 0.23282526599043141, 0.23250119005645153, 0.23217727148512957, 0.23185351046701846, 0.23152990719257854, 0.23120646185217725, 0.23088317463608932, 0.2305600457344959, 0.23023707533748561, 0.22991426363505357, 0.22959161081710167, 0.22926911707343839, 0.22894678259377815, 0.22862460756774211, 0.22830259218485766, 0.22798073663455809, 0.22765904110618268, 0.22733750578897693, 0.22701613087209133, 0.22669491654458263, 0.22637386299541296, 0.22605297041344991, 0.22573223898746647, 0.22541166890614023, 0.2250912603580546, 0.22477101353169765, 0.22445092861546229, 0.22413100579764628, 0.22381124526645213, 0.22349164720998632, 0.2231722118162604, 0.22285293927319, 0.22253382976859482, 0.22221488349019902, 0.22189610062563014, 0.22157748136242006, 0.22125902588800428, 0.22094073438972195, 0.22062260705481579, 0.2203046440704321, 0.21998684562361992, 0.21966921190133204, 0.21935174309042427, 0.21903443937765527, 0.21871730094968672, 0.21840032799308307, 0.21808352069431103, 0.21776687923974031, 0.21745040381564301, 0.21713409460819338, 0.21681795180346819, 0.21650197558744577, 0.21618616614600694, 0.21587052366493426, 0.21555504832991207, 0.21523974032652637, 0.21492459984026496, 0.21460962705651643, 0.21429482216057139, 0.21398018533762148, 0.21366571677275936, 0.21335141665097901, 0.21303728515717474, 0.21272332247614217, 0.21240952879257746, 0.21209590429107733, 0.21178244915613909, 0.21146916357216033, 0.21115604772343871, 0.21084310179417226, 0.21053032596845911, 0.21021772043029713, 0.20990528536358433, 0.20959302095211785, 0.20928092737959492, 0.20896900482961228, 0.20865725348566577, 0.2083456735311508, 0.20803426514936196, 0.20772302852349245, 0.20741196383663485, 0.20710107127178057, 0.2067903510118197, 0.20647980323954113, 0.20616942813763173, 0.20585922588867739, 0.20554919667516214, 0.20523934067946803, 0.20492965808387553, 0.20462014907056297, 0.20431081382160632, 0.20400165251897956, 0.20369266534455444, 0.20338385248010005, 0.20307521410728335, 0.20276675040766784, 0.20245846156271508, 0.20215034775378338, 0.20184240916212814, 0.20153464596890175, 0.20122705835515348, 0.20091964650182892, 0.2006124105897707, 0.20030535079971773, 0.19999846731230547, 0.19969176030806568, 0.1993852299674258, 0.19907887647071004, 0.19877269999813812, 0.19846670072982592, 0.19816087884578476, 0.19785523452592207, 0.19754976795004014, 0.19724447929783728, 0.19693936874890694, 0.19663443648273771, 0.1963296826787137, 0.19602510751611324, 0.19572071117411033, 0.19541649383177345, 0.19511245566806579, 0.19480859686184526, 0.19450491759186422, 0.1942014180367691, 0.19389809837510102, 0.19359495878529515, 0.19329199944568065, 0.19298922053448092, 0.19268662222981259, 0.19238420470968665, 0.19208196815200751, 0.19177991273457318, 0.19147803863507507, 0.19117634603109812, 0.19087483510011999, 0.1905735060195119, 0.19027235896653799, 0.1899713941183554, 0.1896706116520141, 0.18937001174445628, 0.18906959457251737, 0.18876936031292502, 0.18846930914229937, 0.18816944123715268, 0.18786975677388978, 0.18757025592880688, 0.18727093887809287, 0.18697180579782824, 0.18667285686398527, 0.18637409225242807, 0.18607551213891182, 0.1857771166990837, 0.18547890610848206, 0.18518088054253651, 0.18488304017656776, 0.18458538518578782, 0.18428791574529918, 0.18399063203009552, 0.18369353421506124, 0.18339662247497135, 0.18309989698449153, 0.18280335791817737, 0.18250700545047532, 0.18221083975572194, 0.18191486100814391, 0.18161906938185784, 0.18132346505087055, 0.18102804818907803, 0.18073281897026666, 0.18043777756811213, 0.18014292415617972, 0.17984825890792427, 0.17955378199668942, 0.17925949359570847, 0.17896539387810378, 0.17867148301688657, 0.17837776118495707, 0.17808422855510436, 0.17779088530000592, 0.17749773159222804, 0.17720476760422565, 0.1769119935083418, 0.17661940947680815, 0.17632701568174403, 0.17603481229515738, 0.17574279948894378, 0.17545097743488702, 0.17515934630465835, 0.17486790626981713, 0.17457665750180962, 0.17428560017197015, 0.17399473445152025, 0.17370406051156873, 0.17341357852311173, 0.17312328865703203, 0.17283319108409978, 0.17254328597497198, 0.17225357350019233, 0.17196405383019114, 0.17167472713528559, 0.17138559358567879, 0.17109665335146074, 0.17080790660260747, 0.17051935350898134, 0.17023099424033078, 0.16994282896628987, 0.1696548578563789, 0.16936708108000392, 0.16907949880645656, 0.16879211120491411, 0.16850491844443938, 0.16821792069398017, 0.16793111812237005, 0.1676445108983276, 0.16735809919045641, 0.16707188316724531, 0.16678586299706744, 0.16650003884818132, 0.1662144108887299, 0.16592897928674077, 0.16564374421012595, 0.16535870582668211, 0.16507386430408955, 0.16478921980991351, 0.16450477251160289, 0.16422052257649078, 0.16393647017179425, 0.16365261546461363, 0.16336895862193357, 0.16308549981062198, 0.16280223919743048, 0.16251917694899398, 0.1622363132318308, 0.16195364821234209, 0.16167118205681258, 0.16138891493140983, 0.16110684700218425, 0.16082497843506938, 0.16054330939588085, 0.16026184005031752, 0.15998057056396053, 0.15969950110227349, 0.15941863183060229, 0.1591379629141752, 0.15885749451810227, 0.15857722680737601, 0.15829715994687066, 0.15801729410134224, 0.15773762943542896, 0.15745816611364988, 0.15717890430040632, 0.15689984415998071, 0.15662098585653705, 0.15634232955412042, 0.15606387541665734, 0.15578562360795484, 0.15550757429170148, 0.15522972763146659, 0.15495208379070002, 0.15467464293273281, 0.15439740522077589, 0.15412037081792118, 0.15384353988714095, 0.15356691259128769, 0.15329048909309406, 0.15301426955517311, 0.15273825414001729, 0.15246244300999962, 0.15218683632737257, 0.15191143425426851, 0.15163623695269957, 0.1513612445845568, 0.15108645731161141, 0.1508118752955136, 0.15053749869779293, 0.15026332767985806, 0.14998936240299693, 0.14971560302837589, 0.14944204971704073, 0.14916870262991577, 0.14889556192780407, 0.14862262777138746, 0.14834990032122575, 0.14807737973775759, 0.14780506618129985, 0.14753295981204756, 0.14726106079007389, 0.14698936927533024, 0.1467178854276453, 0.14644660940672627, 0.14617554137215782, 0.1459046814834023, 0.14563402989979979, 0.14536358678056727, 0.14509335228479958, 0.14482332657146885, 0.14455350979942416, 0.14428390212739173, 0.14401450371397506, 0.14374531471765384, 0.14347633529678538, 0.14320756560960324, 0.14293900581421759, 0.14267065606861556, 0.14240251653066005, 0.1421345873580907, 0.1418668687085235, 0.14159936073945023, 0.14133206360823913, 0.1410649774721342, 0.14079810248825519, 0.14053143881359781, 0.1402649866050335, 0.13999874601930917, 0.13973271721304747, 0.139466900342746, 0.13920129556477817, 0.13893590303539238, 0.13867072291071214, 0.13840575534673627, 0.13814100049933831, 0.13787645852426655, 0.13761212957714442, 0.13734801381346962, 0.13708411138861482, 0.13682042245782711, 0.13655694717622757, 0.13629368569881217, 0.13603063818045069, 0.1357678047758874, 0.13550518563974023, 0.13524278092650155, 0.13498059079053693, 0.1347186153860862, 0.13445685486726289, 0.13419530938805369, 0.13393397910231941, 0.13367286416379365, 0.13341196472608363, 0.13315128094266987, 0.13289081296690586, 0.13263056095201819, 0.13237052505110669, 0.13211070541714331, 0.13185110220297347, 0.1315917155613151, 0.13133254564475855, 0.13107359260576712, 0.1308148565966758, 0.13055633776969244, 0.13029803627689718, 0.1300399522702419, 0.12978208590155094, 0.12952443732252056, 0.12926700668471841, 0.12900979413958452, 0.12875279983843035, 0.12849602393243914, 0.12823946657266555, 0.12798312791003541, 0.12772700809534637, 0.12747110727926703, 0.12721542561233729, 0.12695996324496805, 0.12670472032744146, 0.12644969700990999, 0.12619489344239743, 0.1259403097747982, 0.12568594615687734, 0.12543180273827048, 0.12517787966848332, 0.12492417709689252, 0.12467069517274471, 0.12441743404515682, 0.12416439386311573, 0.12391157477547871, 0.12365897693097239, 0.1234066004781938, 0.12315444556560934, 0.12290251234155541, 0.12265080095423786, 0.12239931155173178, 0.12214804428198212, 0.12189699929280273, 0.12164617673187716, 0.12139557674675766, 0.12114519948486602, 0.12089504509349241, 0.12064511371979636, 0.12039540551080602, 0.12014592061341828, 0.1198966591743989, 0.11964762134038159, 0.11939880725786911, 0.11915021707323237, 0.11890185093271055, 0.11865370898241101, 0.11840579136830942, 0.11815809823624912, 0.11791062973194166, 0.11766338600096643, 0.11741636718877052, 0.11716957344066886, 0.1169230049018436, 0.11667666171734481, 0.11643054403208986, 0.11618465199086331, 0.11593898573831729, 0.11569354541897092, 0.11544833117721021, 0.11520334315728853, 0.11495858150332605, 0.1147140463593096, 0.1144697378690932, 0.11422565617639691, 0.11398180142480779, 0.11373817375777939, 0.1134947733186315, 0.11325160025055042, 0.11300865469658872, 0.11276593679966462, 0.11252344670256309, 0.11228118454793473, 0.11203915047829616, 0.11179734463602992, 0.11155576716338383, 0.1113144182024719, 0.11107329789527348, 0.1108324063836334, 0.11059174380926196, 0.11035131031373496, 0.11011110603849283, 0.1098711311248417, 0.10963138571395276, 0.10939186994686195, 0.10915258396447036, 0.10891352790754361, 0.10867470191671219, 0.10843610613247134, 0.10819774069518084, 0.10795960574506497, 0.10772170142221243, 0.10748402786657602, 0.10724658521797303, 0.10700937361608492, 0.10677239320045712, 0.10653564411049921, 0.10629912648548434, 0.10606284046454995, 0.10582678618669689, 0.10559096379078986, 0.10535537341555712, 0.10512001519959058, 0.10488488928134504, 0.10464999579913919, 0.10441533489115495, 0.10418090669543706, 0.10394671134989392, 0.10371274899229621, 0.10347901976027818, 0.10324552379133672, 0.10301226122283141, 0.1027792321919847, 0.1025464368358816, 0.1023138752914694, 0.10208154769555827, 0.10184945418482044, 0.10161759489579059, 0.10138596996486571, 0.10115457952830453, 0.10092342372222812, 0.10069250268261959, 0.10046181654532382, 0.10023136544604749, 0.1000011495203591, 0.099771168903688645, 0.099541423731327849, 0.09931191413842988, 0.099082640260009347, 0.098853602230942195, 0.098624800185965478, 0.098396234259677584, 0.098167904586537957, 0.097939811300867152, 0.097711954536846446, 0.097484334428518282, 0.097256951109785494, 0.09702980471441186, 0.096802895376021825, 0.096576223228100333, 0.096349788403992886, 0.096123591036904876, 0.095897631259902694, 0.095671909205912509, 0.095446425007720881, 0.095221178797974315, 0.094996170709179539, 0.094771400873702671, 0.094546869423770163, 0.094322576491468135, 0.094098522208742263, 0.09387470670739817, 0.093651130119100312, 0.093427792575373259, 0.093204694207600802, 0.092981835147025793, 0.092759215524750638, 0.0925368354717368, 0.092314695118804413, 0.09209279459663311, 0.091871134035761304, 0.091649713566586077, 0.091428533319363625, 0.0912075934242082, 0.090986894011093278, 0.090766435209850671, 0.090546217150170527, 0.090326239961601495, 0.090106503773550561, 0.089887008715282712, 0.089667754915921272, 0.089448742504447676, 0.089229971609701197, 0.089011442360379278, 0.088793154885036862, 0.088575109312086897, 0.088357305769799943, 0.088139744386304286, 0.087922425289585715, 0.087705348607487466, 0.087488514467709944, 0.08727192299781128, 0.087055574325206608, 0.086839468577168233, 0.086623605880825794, 0.08640798636316549, 0.086192610151030857, 0.085977477371122157, 0.085762588149996433, 0.085547942614067507, 0.085333540889605985, 0.085119383102738533, 0.084905469379448872, 0.084691799845576843, 0.084478374626818842, 0.084265193848727327, 0.084052257636711258, 0.083839566116035213, 0.083627119411820272, 0.083414917649043407, 0.083202960952537375, 0.082991249446990989, 0.082779783256948458, 0.082568562506809995, 0.082357587320831316, 0.082146857823123698, 0.081936374137653867, 0.081726136388244053, 0.081516144698571547, 0.081306399192169088, 0.081096899992424532, 0.080887647222580961, 0.080678641005736407, 0.080469881464843684, 0.08026136872271078, 0.080053102902000239, 0.079845084125229615, 0.079637312514770908, 0.079429788192851014, 0.079222511281550834, 0.079015481902806162, 0.078808700178407076, 0.078602166229997883, 0.078395880179077337, 0.078189842146997979, 0.077984052254966796, 0.077778510624044672, 0.077573217375146442, 0.077368172629040832, 0.077163376506350523, 0.076958829127551587, 0.076754530612973992, 0.07655048108280138, 0.076346680657070787, 0.07614312945567292, 0.075939827598351439, 0.075736775204703677, 0.075533972394180193, 0.075331419286084611, 0.075129115999573726, 0.07492706265365745, 0.074725259367198316, 0.074523706258912137, 0.074322403447367402, 0.074121351050985385, 0.073920549188040141, 0.073719997976658014, 0.073519697534818185, 0.073319647980352287, 0.073119849430944295, 0.072920302004130577, 0.072721005817299789, 0.072521960987692591, 0.072323167632401986, 0.072124625868373093, 0.071926335812402709, 0.071728297581140077, 0.071530511291085674, 0.071332977058592206, 0.071135694999863941, 0.070938665230956932, 0.070741887867778575, 0.070545363026088159, 0.070349090821495874, 0.070153071369463693, 0.06995730478530493, 0.069761791184183908, 0.069566530681116401, 0.06937152339096897, 0.06917676942845935, 0.068982268908156397, 0.068788021944479749, 0.068594028651699779, 0.068400289143937976, 0.068206803535166005, 0.068013571939206652, 0.067820594469732987, 0.067627871240268811, 0.067435402364188213, 0.067243187954715511, 0.067051228124925588, 0.066859522987743503, 0.066668072655944433, 0.066476877242153676, 0.066285936858846595, 0.066095251618348394, 0.065904821632834398, 0.065714647014329552, 0.065524727874708755, 0.06533506432569669, 0.06514565647886722, 0.064956504445644325, 0.064767608337301219, 0.064578968264960568, 0.064390584339594492, 0.06420245667202451, 0.064014585372921151, 0.063826970552804285, 0.063639612322042849, 0.063452510790854899, 0.063265666069307613, 0.063079078267316624, 0.062892747494646906, 0.062706673860911943, 0.062520857475574176, 0.062335298447944554, 0.062149996887182757, 0.061964952902296755, 0.061780166602143194, 0.061595638095427174, 0.061411367490701974, 0.061227354896369435, 0.061043600420679134, 0.060860104171729268, 0.060676866257465933, 0.060493886785683237, 0.060311165864023353, 0.060128703599976352, 0.059946500100879874, 0.059764555473919623, 0.059582869826129037, 0.059401443264388953, 0.059220275895428165, 0.059039367825822531, 0.058858719161995698, 0.058678330010218605, 0.058498200476609585, 0.058318330667134155, 0.058138720687605283, 0.057959370643682562, 0.05778028064087315, 0.057601450784531105, 0.057422881179857443, 0.057244571931900079, 0.05706652314555366, 0.056888734925559736, 0.056711207376506478, 0.056533940602828903, 0.056356934708808371, 0.056180189798573088, 0.056003705976097273, 0.055827483345201878, 0.0556515220095542, 0.055475822072667713, 0.055300383637902295, 0.055125206808463667, 0.054950291687403896, 0.054775638377621061, 0.054601246981859253, 0.054427117602708353, 0.054253250342604364, 0.054079645303828694, 0.053906302588508759, 0.053733222298617711, 0.053560404535974104, 0.053387849402242393, 0.053215556998932045, 0.053043527427398374, 0.052871760788841982, 0.052700257184308652, 0.052529016714689625, 0.052358039480721263, 0.052187325582985, 0.052016875121907447, 0.051846688197760227, 0.051676764910659867, 0.051507105360568073, 0.051337709647290897, 0.051168577870479626, 0.050999710129630116, 0.050831106524082847, 0.050662767153023036, 0.050494692115480522, 0.050326881510329269, 0.050159335436288033, 0.04999205399191986, 0.049825037275632145, 0.049658285385676626, 0.049491798420148891, 0.049325576476989041, 0.049159619653981135, 0.04899392804875341, 0.048828501758777842, 0.048663340881370643, 0.048498445513691479, 0.048333815752744091, 0.048169451695376009, 0.048005353438278331, 0.047841521077985893, 0.047677954710876935, 0.047514654433173376, 0.047351620340940648, 0.047188852530087366, 0.04702635109636577, 0.046864116135371225, 0.046702147742542333, 0.046540446013160985, 0.046379011042352092, 0.046217842925083685, 0.04605694175616698, 0.045896307630255706, 0.045735940641846939, 0.045575840885280494, 0.04541600845473881, 0.045256443444247285, 0.045097145947673944, 0.044938116058729216, 0.044779353870966432, 0.044620859477781216, 0.04446263297241182, 0.044304674447938897, 0.044146983997285116, 0.043989561713215886, 0.043832407688338626, 0.043675522015103052, 0.043518904785800894, 0.043362556092566173, 0.043206476027374596, 0.043050664682044215, 0.042895122148234655, 0.042739848517447721, 0.042584843881027012, 0.042430108330157423, 0.042275641955866139, 0.042121444849021639, 0.04196751710033414, 0.04181385880035543, 0.041660470039478703, 0.041507350907938556, 0.041354501495811047, 0.041201921893013582, 0.041049612189304752, 0.040897572474284605, 0.04074580283739393, 0.04059430336791503, 0.040443074154971115, 0.040292115287526464, 0.04014142685438632, 0.039991008944196771, 0.039840861645444758, 0.039690985046458072, 0.039541379235405294, 0.039392044300295637, 0.039242980328979105, 0.039094187409145997, 0.038945665628327464, 0.038797415073895059, 0.038649435833060686, 0.038501727992876822, 0.038354291640236238, 0.038207126861871721, 0.038060233744356631, 0.037913612374104455, 0.037767262837368643, 0.037621185220243103, 0.037475379608661263, 0.037329846088396901, 0.037184584745063642, 0.037039595664114966, 0.03689487893084431, 0.036750434630384798, 0.036606262847709126, 0.036462363667629949, 0.036318737174799443, 0.036175383453709409, 0.036032302588691112, 0.035889494663915333, 0.035746959763392261, 0.035604697970971544, 0.035462709370342127, 0.035320994045032195, 0.035179552078409393, 0.035038383553680219, 0.034897488553890521, 0.034756867161925165, 0.034616519460508144, 0.034476445532202415, 0.034336645459409842, 0.034197119324371084, 0.034057867209165926, 0.033918889195712787, 0.033780185365768767, 0.033641755800929929, 0.033503600582630577, 0.033365719792143977, 0.033228113510581914, 0.033090781818894521, 0.03295372479787062, 0.032816942528137105, 0.032680435090159665, 0.032544202564241953, 0.032408245030526195, 0.032272562568992635, 0.032137155259459871, 0.032002023181584349, 0.03186716641486087, 0.031732585038622252, 0.031598279132039164, 0.031464248774120462, 0.031330494043712576, 0.031197015019500007, 0.031063811780005113, 0.030930884403587822, 0.030798232968445916, 0.030665857552614972, 0.030533758233967756, 0.030401935090215049, 0.030270388198905041, 0.030139117637423329, 0.030008123482993088, 0.029877405812674618, 0.029746964703365852, 0.029616800231801965, 0.029486912474555371, 0.029357301508035616, 0.029227967408489652, 0.029098910252001176, 0.028970130114491344, 0.028841627071718112, 0.028713401199276567, 0.028585452572598702, 0.028457781266953308, 0.028330387357446141, 0.028203270919019807, 0.028076432026453657, 0.02794987075436367, 0.02782358717720268, 0.027697581369259927, 0.027571853404661395, 0.027446403357369697, 0.027321231301183857, 0.02719633730973936, 0.027071721456508102, 0.026947383814798331, 0.026823324457754705, 0.026699543458358233, 0.026576040889425945, 0.026452816823611447, 0.026329871333404031, 0.026207204491129454, 0.026084816368949493, 0.025962707038861887, 0.025840876572700511, 0.025719325042134866, 0.025598052518670811, 0.025477059073649722, 0.02535634477824894, 0.025235909703481663, 0.025115753920196715, 0.0249958774990785, 0.024876280510647386, 0.024756963025259149, 0.024637925113105197, 0.024519166844212514, 0.024400688288443384, 0.024282489515495831, 0.024164570594903068, 0.024046931596033827, 0.023929572588092085, 0.023812493640117116, 0.023695694820983382, 0.023579176199400698, 0.0234629378439139, 0.023346979822903069, 0.023231302204583415, 0.023115905057004893, 0.023000788448052756, 0.022885952445447222, 0.022771397116743253, 0.022657122529330831, 0.022543128750434793, 0.022429415847114664, 0.022315983886264878, 0.022202832934614447, 0.022089963058727291, 0.021977374325001797, 0.021865066799670985, 0.021753040548802505, 0.021641295638298474, 0.021529832133895588, 0.021418650101164893, 0.021307749605512072, 0.021197130712176881, 0.021086793486233546, 0.020976737992590755, 0.020866964295991164, 0.02075747246101195, 0.020648262552064256, 0.020539334633393469, 0.020430688769079053, 0.020322325023034604, 0.020214243459007741, 0.020106444140580049, 0.019998927131167077, 0.019891692494018287, 0.019784740292217107, 0.019678070588680707, 0.019571683446160226, 0.019465578927240379, 0.01935975709433968, 0.0192542180097105, 0.01914896173543873, 0.019043988333443895, 0.01893929786547921, 0.018834890393131298, 0.018730765977820418, 0.018626924680800294, 0.018523366563158061, 0.018420091685814322, 0.018317100109523032, 0.018214391894871396, 0.01811196710228008, 0.018009825792002943, 0.017907968024127086, 0.017806393858572911, 0.017705103355093676, 0.017604096573276107, 0.017503373572539838, 0.017402934412137638, 0.017302779151155356, 0.017202907848511639, 0.017103320562958213, 0.017004017353079715, 0.016904998277293748, 0.016806263393850551, 0.016707812760833496, 0.016609646436158365, 0.016511764477573965, 0.016414166942661734, 0.016316853888835747, 0.016219825373342822, 0.0161230814532623, 0.016026622185506101, 0.015930447626818833, 0.015834557833777407, 0.015738952862791311, 0.015643632770102667, 0.015548597611785564, 0.015453847443746949, 0.015359382321725734, 0.015265202301293468, 0.015171307437853832, 0.015077697786642585, 0.014984373402728013, 0.01489133434101042, 0.014798580656222249, 0.014706112402928184, 0.01461392963552488, 0.014522032408241015, 0.014430420775137454, 0.014339094790106921, 0.014248054506874108, 0.014157299978995785, 0.014066831259860357, 0.013976648402688308, 0.013886751460531865, 0.013797140486275117, 0.013707815532633894, 0.013618776652155773, 0.013530023897219967, 0.013441557320037434, 0.013353376972650877, 0.013265482906934467, 0.013177875174594067, 0.013090553827166951, 0.013003518916022083, 0.012916770492359841, 0.012830308607212071, 0.012744133311442085, 0.012658244655744666, 0.012572642690645786, 0.01248732746650294, 0.012402299033504816, 0.012317557441671512, 0.012233102740854374, 0.01214893498073577, 0.012065054210829484, 0.011981460480480488, 0.011898153838864722, 0.01181513433498943, 0.011732402017692822, 0.011649956935644135, 0.011567799137343682, 0.011485928671122803, 0.01140434558514386, 0.01132304992740002, 0.011242041745715414, 0.011161321087745035, 0.011080888000974787, 0.01100074253272143, 0.010920884730132474, 0.010841314640186228, 0.010762032309691583, 0.010683037785288452, 0.010604331113447163, 0.010525912340468901, 0.010447781512485432, 0.01036993867545899, 0.010292383875182609, 0.010215117157279741, 0.010138138567204413, 0.010061448150241181, 0.0099850459515050116, 0.0099089320159413408, 0.0098331063883260184, 0.0097575691132653075, 0.0096823202351959403, 0.0096073597983847847, 0.0095326878469291776, 0.0094583044247567027, 0.0093842095756251909, 0.0093104033431227196, 0.0092368857706676133, 0.0091636569015084435, 0.0090907167787237508, 0.0090180654452223785, 0.00894570294374325, 0.0088736293168553138, 0.0088018446069576539, 0.0087303488562793796, 0.0086591421068795693, 0.0085882244006473818, 0.0085175957793017787, 0.008447256284391802, 0.008377205957296463, 0.0083074448392244093, 0.008237972971214369, 0.0081687903941348727, 0.0080998971486841986, 0.0080312932753905386, 0.0079629788146117764, 0.0078949538065354874, 0.00782721829117905, 0.0077597723083895342, 0.007692615897843702, 0.007625749099047896, 0.0075591719513381506, 0.0074928844938800809, 0.0074268867656689386, 0.0073611788055293892, 0.0072957606521157903, 0.0072306323439119691, 0.0071657939192312226, 0.0071012454162163174, 0.0070369868728394347, 0.0069730183269022805, 0.0069093398160359198, 0.0068459513777007208, 0.0067828530491864658, 0.0067200448676122959, 0.0066575268699266554, 0.0065952990929072364, 0.006533361573161145, 0.0064717143471245131, 0.0064103574510628314, 0.0063492909210707826, 0.0062885147930722973, 0.0062280291028203871, 0.0061678338858971449, 0.0061079291777139111, 0.0060483150135111075, 0.0059889914283582368, 0.0059299584571537167, 0.0058712161346252678, 0.0058127644953293589, 0.0057546035736517065, 0.0056967334038067752, 0.0056391540198381107, 0.0055818654556182845, 0.0055248677448485051, 0.0054681609210592286, 0.0054117450176094928, 0.0053556200676874166, 0.0052997861043098116, 0.0052442431603224038, 0.005188991268399612, 0.0051340304610447141, 0.0050793607705897359, 0.0050249822291955071, 0.0049708948688514942, 0.0049170987213758011, 0.0048635938184154459, 0.0048103801914459177, 0.0047574578717714533, 0.0047048268905249269, 0.004652487278667683, 0.0046004390669898143, 0.0045486822861099951, 0.0044972169664753148, 0.0044460431383615551, 0.004395160831873024, 0.0043445700769422779, 0.0042942709033307325, 0.0042442633406280517, 0.0041945474182523146, 0.0041451231654502374, 0.0040959906112967848, 0.0040471497846953364, 0.0039986007143777424, 0.0039503434289041017, 0.003902377956663039, 0.003854704325871372, 0.0038073225645741671, 0.0037602327006450165, 0.0037134347617855945, 0.0036669287755259905, 0.0036207147692244313, 0.0035747927700674476, 0.0035291628050697632, 0.003483824901074295, 0.0034387790847522082, 0.00339402538260275, 0.0033495638209533607, 0.0033053944259596735, 0.0032615172236054035, 0.003217932239702348, 0.0031746394998904415, 0.0031316390296377006, 0.0030889308542401683, 0.0030465149988219697, 0.0030043914883353118, 0.0029625603475603168, 0.0029210216011051338, 0.0028797752734060489, 0.0028388213887270974, 0.0027981599711604521, 0.0027577910446262011, 0.0027177146328722923, 0.0026779307594746449, 0.0026384394478371487, 0.0025992407211914426, 0.0025603346025971918, 0.0025217211149418106, 0.0024834002809406841, 0.0024453721231369463, 0.0024076366639015911, 0.0023701939254333615, 0.0023330439297588601, 0.0022961866987325497, 0.0022596222540365307, 0.0022233506171807638, 0.0021873718095028472, 0.0021516858521682392, 0.0021162927661700914, 0.0020811925723291935, 0.0020463852912941394, 0.0020118709435411053, 0.0019776495493740165, 0.001943721128924436, 0.0019100857021515094, 0.001876743288842242, 0.0018436939086109994, 0.0018109375808998962, 0.001778474324978685, 0.0017463041599445894, 0.0017144271047225823, 0.0016828431780650521, 0.0016515523985519698, 0.0016205547845909996, 0.001589850354417166, 0.0015594391260930762, 0.0015293211175089194, 0.0014994963463823563, 0.0014699648302585189, 0.0014407265865100105, 0.0014117816323369614, 0.0013831299847668621, 0.0013547716606548965, 0.0013267066766834423, 0.0012989350493623486, 0.0012714567950290467, 0.001244271929848273, 0.0012173804698121238, 0.0011907824307402226, 0.0011644778282794976, 0.0011384666779041819, 0.0011127489949160907, 0.0010873247944441777, 0.0010621940914449235, 0.0010373569007020023, 0.0010128132368265041, 0.00098856311425687959, 0.00096460654725882833, 0.00094094354992541041, 0.00091757413617687966, 0.00089449831976090577, 0.00087171611425240769, 0.0008492275330535537, 0.00082703258939381685, 0.00080513129632991953, 0.00078352366674577789, 0.00076220971335261289, 0.00074118944868895031, 0.00072046288512034318, 0.00070003003483981585, 0.00067989090986741996, 0.00066004552205045641, 0.00064049388306353094, 0.00062123600440833204, 0.0006022718974137975, 0.00058360157323600337, 0.00056522504285821951, 0.00054714231709085404, 0.00052935340657156438, 0.00051185832176509072, 0.00049465707296331152, 0.00047774967028535453, 0.00046113612367731927, 0.00044481644291255451, 0.00042879063759154734, 0.00041305871714181208, 0.00039762069081805684, 0.0003824765677020725, 0.0003676263567027882, 0.00035307006655616036, 0.00033880770582522812, 0.00032483928290027997, 0.0003111648059985761, 0.00029778428316434846, 0.00028469772226913381, 0.00027190513101132963, 0.00025940651691652716, 0.00024720188733734494, 0.00023529124945342872, 0.00022367461027150704, 0.00021235197662539118, 0.00020132335517580868, 0.00019058875241068085, 0.00018014817464490074, 0.00017000162802038865, 0.00016014911850603664, 0.00015059065189787502, 0.00014132623381890586, 0.00013235586971915847, 0.00012367956487557841, 0.00011529732439236051, 0.00010720915320039381, 9.9415056057872153e-05, 9.1915037549794576e-05, 8.4709102088298405e-05, 7.7797253912381681e-05, 7.1179497088069699e-05, 6.4855835508526027e-05, 5.8826272893719445e-05, 5.3090812790757003e-05, 4.7649458573606474e-05, 4.2502213443262882e-05, 3.7649080427748505e-05, 3.309006238200185e-05, 2.882516198804419e-05, 2.4854381754757515e-05, 2.117772401805107e-05, 1.779519094086135e-05, 1.470678451293006e-05, 1.1912506551192692e-05, 9.4123586994454556e-06, 7.2063424284007915e-06, 5.2944590357983934e-06, 3.6767096464052074e-06, 2.3530952119044102e-06, 1.323616510895409e-06, 5.882741490603749e-07, 1.4706855888668713e-07, 0.0, 0.0}; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *transpo; Stream *transpo_stream; PyObject *feedback; Stream *feedback_stream; MYFLT winsize; MYFLT pointerPos; int in_count; MYFLT *buffer; // samples memory int modebuffer[4]; } Harmonizer; static void Harmonizer_transform_ii(Harmonizer *self) { MYFLT val, amp, inc, ratio, rate, del, xind, pos, envpos, fpart; int i, ipart; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT trans = PyFloat_AS_DOUBLE(self->transpo); MYFLT feed = PyFloat_AS_DOUBLE(self->feedback); if (feed < 0.0) feed = 0.0; else if (feed > 1.0) feed = 1.0; ratio = MYPOW(2.0, trans/12.0); rate = (ratio-1.0) / self->winsize; inc = -rate / self->sr; for (i=0; ibufsize; i++) { /* first overlap */ pos = self->pointerPos; envpos = pos * 8192.0; ipart = (int)envpos; fpart = envpos - ipart; amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart; del = pos * self->winsize; xind = self->in_count - (del * self->sr); if (xind < 0) xind += self->sr; ipart = (int)xind; fpart = xind - ipart; val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart; self->data[i] = val * amp; /* second overlap */ pos = self->pointerPos + 0.5; if (pos >= 1) pos -= 1.0; envpos = pos * 8192.0; ipart = (int)envpos; fpart = envpos - ipart; amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart; del = pos * self->winsize; xind = self->in_count - (del * self->sr); if (xind < 0) xind += self->sr; ipart = (int)xind; fpart = xind - ipart; val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart; self->data[i] += (val * amp); self->pointerPos += inc; if (self->pointerPos < 0.0) self->pointerPos += 1.0; else if (self->pointerPos >= 1.0) self->pointerPos -= 1.0; self->buffer[self->in_count] = in[i] + (self->data[i] * feed); if (self->in_count == 0) self->buffer[(int)self->sr] = self->buffer[0]; self->in_count++; if (self->in_count >= self->sr) self->in_count = 0; } } static void Harmonizer_transform_ai(Harmonizer *self) { MYFLT val, amp, inc, ratio, rate, del, xind, pos, envpos, fpart; int i, ipart; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *trans = Stream_getData((Stream *)self->transpo_stream); MYFLT feed = PyFloat_AS_DOUBLE(self->feedback); if (feed < 0.0) feed = 0.0; else if (feed > 1.0) feed = 1.0; MYFLT oneOnWinsize = 1.0 / self->winsize; MYFLT oneOnSr = 1.0 / self->sr; for (i=0; ibufsize; i++) { ratio = MYPOW(2.0, trans[i]/12.0); rate = (ratio-1.0) * oneOnWinsize; inc = -rate * oneOnSr;; /* first overlap */ pos = self->pointerPos; envpos = pos * 8192.0; ipart = (int)envpos; fpart = envpos - ipart; amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart; del = pos * self->winsize; xind = self->in_count - (del * self->sr); if (xind < 0) xind += self->sr; ipart = (int)xind; fpart = xind - ipart; val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart; self->data[i] = val * amp; /* second overlap */ pos = self->pointerPos + 0.5; if (pos >= 1) pos -= 1.0; envpos = pos * 8192.0; ipart = (int)envpos; fpart = envpos - ipart; amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart; del = pos * self->winsize; xind = self->in_count - (del * self->sr); if (xind < 0) xind += self->sr; ipart = (int)xind; fpart = xind - ipart; val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart; self->data[i] += (val * amp); self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; self->buffer[self->in_count] = in[i] + (self->data[i] * feed); if (self->in_count == 0) self->buffer[(int)self->sr] = self->buffer[0]; self->in_count++; if (self->in_count >= self->sr) self->in_count = 0; } } static void Harmonizer_transform_ia(Harmonizer *self) { MYFLT val, amp, inc, ratio, rate, del, xind, pos, envpos, fpart, feedback; int i, ipart; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT trans = PyFloat_AS_DOUBLE(self->transpo); MYFLT *feed = Stream_getData((Stream *)self->feedback_stream); ratio = MYPOW(2.0, trans/12.0); rate = (ratio-1.0) / self->winsize; inc = -rate / self->sr; for (i=0; ibufsize; i++) { if (feed[i] < 0.0) feedback = 0.0; else if (feed[i] > 1.0) feedback = 1.0; else feedback = feed[i]; /* first overlap */ pos = self->pointerPos; envpos = pos * 8192.0; ipart = (int)envpos; fpart = envpos - ipart; amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart; del = pos * self->winsize; xind = self->in_count - (del * self->sr); if (xind < 0) xind += self->sr; ipart = (int)xind; fpart = xind - ipart; val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart; self->data[i] = val * amp; /* second overlap */ pos = self->pointerPos + 0.5; if (pos > 1) pos -= 1.0; envpos = pos * 8192.0; ipart = (int)envpos; fpart = envpos - ipart; amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart; del = pos * self->winsize; xind = self->in_count - (del * self->sr); if (xind < 0) xind += self->sr; ipart = (int)xind; fpart = xind - ipart; val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart; self->data[i] += (val * amp); self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; self->buffer[self->in_count] = in[i] + (self->data[i] * feedback); if (self->in_count == 0) self->buffer[(int)self->sr] = self->buffer[0]; self->in_count++; if (self->in_count >= self->sr) self->in_count = 0; } } static void Harmonizer_transform_aa(Harmonizer *self) { MYFLT val, amp, inc, ratio, rate, del, xind, pos, envpos, fpart, feedback; int i, ipart; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *trans = Stream_getData((Stream *)self->transpo_stream); MYFLT *feed = Stream_getData((Stream *)self->feedback_stream); MYFLT oneOnWinsize = 1.0 / self->winsize; MYFLT oneOnSr = 1.0 / self->sr; for (i=0; ibufsize; i++) { ratio = MYPOW(2.0, trans[i]/12.0); rate = (ratio-1.0) * oneOnWinsize; inc = -rate * oneOnSr;; if (feed[i] < 0.0) feedback = 0.0; else if (feed[i] > 1.0) feedback = 1.0; else feedback = feed[i]; /* first overlap */ pos = self->pointerPos; envpos = pos * 8192.0; ipart = (int)envpos; fpart = envpos - ipart; amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart; del = pos * self->winsize; xind = self->in_count - (del * self->sr); if (xind < 0) xind += self->sr; ipart = (int)xind; fpart = xind - ipart; val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart; self->data[i] = val * amp; /* second overlap */ pos = self->pointerPos + 0.5; if (pos > 1) pos -= 1.0; envpos = pos * 8192.0; ipart = (int)envpos; fpart = envpos - ipart; amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart; del = pos * self->winsize; xind = self->in_count - (del * self->sr); if (xind < 0) xind += self->sr; ipart = (int)xind; fpart = xind - ipart; val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart; self->data[i] += (val * amp); self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; self->buffer[self->in_count] = in[i] + (self->data[i] * feedback); if (self->in_count == 0) self->buffer[(int)self->sr] = self->buffer[0]; self->in_count++; if (self->in_count >= self->sr) self->in_count = 0; } } static void Harmonizer_feedbacktprocessing_ii(Harmonizer *self) { POST_PROCESSING_II }; static void Harmonizer_feedbacktprocessing_ai(Harmonizer *self) { POST_PROCESSING_AI }; static void Harmonizer_feedbacktprocessing_ia(Harmonizer *self) { POST_PROCESSING_IA }; static void Harmonizer_feedbacktprocessing_aa(Harmonizer *self) { POST_PROCESSING_AA }; static void Harmonizer_feedbacktprocessing_ireva(Harmonizer *self) { POST_PROCESSING_IREVA }; static void Harmonizer_feedbacktprocessing_areva(Harmonizer *self) { POST_PROCESSING_AREVA }; static void Harmonizer_feedbacktprocessing_revai(Harmonizer *self) { POST_PROCESSING_REVAI }; static void Harmonizer_feedbacktprocessing_revaa(Harmonizer *self) { POST_PROCESSING_REVAA }; static void Harmonizer_feedbacktprocessing_revareva(Harmonizer *self) { POST_PROCESSING_REVAREVA }; static void Harmonizer_setProcMode(Harmonizer *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Harmonizer_transform_ii; break; case 1: self->proc_func_ptr = Harmonizer_transform_ai; break; case 10: self->proc_func_ptr = Harmonizer_transform_ia; break; case 11: self->proc_func_ptr = Harmonizer_transform_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Harmonizer_feedbacktprocessing_ii; break; case 1: self->muladd_func_ptr = Harmonizer_feedbacktprocessing_ai; break; case 2: self->muladd_func_ptr = Harmonizer_feedbacktprocessing_revai; break; case 10: self->muladd_func_ptr = Harmonizer_feedbacktprocessing_ia; break; case 11: self->muladd_func_ptr = Harmonizer_feedbacktprocessing_aa; break; case 12: self->muladd_func_ptr = Harmonizer_feedbacktprocessing_revaa; break; case 20: self->muladd_func_ptr = Harmonizer_feedbacktprocessing_ireva; break; case 21: self->muladd_func_ptr = Harmonizer_feedbacktprocessing_areva; break; case 22: self->muladd_func_ptr = Harmonizer_feedbacktprocessing_revareva; break; } } static void Harmonizer_compute_next_data_frame(Harmonizer *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Harmonizer_traverse(Harmonizer *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->transpo); Py_VISIT(self->transpo_stream); Py_VISIT(self->feedback); Py_VISIT(self->feedback_stream); return 0; } static int Harmonizer_clear(Harmonizer *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->transpo); Py_CLEAR(self->transpo_stream); Py_CLEAR(self->feedback); Py_CLEAR(self->feedback_stream); return 0; } static void Harmonizer_dealloc(Harmonizer* self) { pyo_DEALLOC free(self->buffer); Harmonizer_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Harmonizer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT wintmp; PyObject *inputtmp, *input_streamtmp, *transpotmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL; Harmonizer *self; self = (Harmonizer *)type->tp_alloc(type, 0); self->transpo = PyFloat_FromDouble(-7.0); self->feedback = PyFloat_FromDouble(0.0); self->winsize = 0.1; self->pointerPos = 1.0; self->in_count = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Harmonizer_compute_next_data_frame); self->mode_func_ptr = Harmonizer_setProcMode; static char *kwlist[] = {"input", "transpo", "feedback", "winsize", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOFOO, kwlist, &inputtmp, &transpotmp, &feedbacktmp, &wintmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (transpotmp) { PyObject_CallMethod((PyObject *)self, "setTranspo", "O", transpotmp); } if (feedbacktmp) { PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->buffer = (MYFLT *)realloc(self->buffer, (self->sr+1) * sizeof(MYFLT)); for (i=0; i<(self->sr+1); i++) { self->buffer[i] = 0.; } if (wintmp > 0.0 && wintmp <= 1.0) self->winsize = wintmp; else printf("Harmonizer : winsize lower than 0.0 or larger than 1.0 second, keeping default value.\n"); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Harmonizer_getServer(Harmonizer* self) { GET_SERVER }; static PyObject * Harmonizer_getStream(Harmonizer* self) { GET_STREAM }; static PyObject * Harmonizer_setMul(Harmonizer *self, PyObject *arg) { SET_MUL }; static PyObject * Harmonizer_setAdd(Harmonizer *self, PyObject *arg) { SET_ADD }; static PyObject * Harmonizer_setSub(Harmonizer *self, PyObject *arg) { SET_SUB }; static PyObject * Harmonizer_setDiv(Harmonizer *self, PyObject *arg) { SET_DIV }; static PyObject * Harmonizer_play(Harmonizer *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Harmonizer_out(Harmonizer *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Harmonizer_stop(Harmonizer *self) { STOP }; static PyObject * Harmonizer_multiply(Harmonizer *self, PyObject *arg) { MULTIPLY }; static PyObject * Harmonizer_inplace_multiply(Harmonizer *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Harmonizer_add(Harmonizer *self, PyObject *arg) { ADD }; static PyObject * Harmonizer_inplace_add(Harmonizer *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Harmonizer_sub(Harmonizer *self, PyObject *arg) { SUB }; static PyObject * Harmonizer_inplace_sub(Harmonizer *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Harmonizer_div(Harmonizer *self, PyObject *arg) { DIV }; static PyObject * Harmonizer_inplace_div(Harmonizer *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Harmonizer_setTranspo(Harmonizer *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->transpo); if (isNumber == 1) { self->transpo = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->transpo = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->transpo, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->transpo_stream); self->transpo_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Harmonizer_setFeedback(Harmonizer *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->feedback); if (isNumber == 1) { self->feedback = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->feedback = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->feedback_stream); self->feedback_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Harmonizer_setWinsize(Harmonizer *self, PyObject *arg) { MYFLT wintmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { wintmp = PyFloat_AsDouble(arg); if (wintmp > 0.0 && wintmp <= 1.0) self->winsize = wintmp; else printf("winsize lower than 0.0 or larger than 1.0 second!\n"); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Harmonizer_members[] = { {"server", T_OBJECT_EX, offsetof(Harmonizer, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Harmonizer, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Harmonizer, input), 0, "Input sound object."}, {"transpo", T_OBJECT_EX, offsetof(Harmonizer, transpo), 0, "Transposition factor."}, {"feedback", T_OBJECT_EX, offsetof(Harmonizer, feedback), 0, "Feedback factor."}, {"mul", T_OBJECT_EX, offsetof(Harmonizer, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Harmonizer, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Harmonizer_methods[] = { {"getServer", (PyCFunction)Harmonizer_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Harmonizer_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Harmonizer_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Harmonizer_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Harmonizer_stop, METH_NOARGS, "Stops computing."}, {"setTranspo", (PyCFunction)Harmonizer_setTranspo, METH_O, "Sets global transpo factor."}, {"setFeedback", (PyCFunction)Harmonizer_setFeedback, METH_O, "Sets feedback factor."}, {"setWinsize", (PyCFunction)Harmonizer_setWinsize, METH_O, "Sets the window size."}, {"setMul", (PyCFunction)Harmonizer_setMul, METH_O, "Sets granulator mul factor."}, {"setAdd", (PyCFunction)Harmonizer_setAdd, METH_O, "Sets granulator add factor."}, {"setSub", (PyCFunction)Harmonizer_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Harmonizer_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Harmonizer_as_number = { (binaryfunc)Harmonizer_add, /*nb_add*/ (binaryfunc)Harmonizer_sub, /*nb_subtract*/ (binaryfunc)Harmonizer_multiply, /*nb_multiply*/ (binaryfunc)Harmonizer_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_feedback*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Harmonizer_inplace_add, /*inplace_add*/ (binaryfunc)Harmonizer_inplace_sub, /*inplace_subtract*/ (binaryfunc)Harmonizer_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Harmonizer_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject HarmonizerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_transpo*/ "_pyo.Harmonizer_base", /*tp_name*/ sizeof(Harmonizer), /*tp_basictranspo*/ 0, /*tp_itemtranspo*/ (destructor)Harmonizer_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Harmonizer_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Harmonizer objects. Harmonize an input sound.", /* tp_doc */ (traverseproc)Harmonizer_traverse, /* tp_traverse */ (inquiry)Harmonizer_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Harmonizer_methods, /* tp_methods */ Harmonizer_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Harmonizer_new, /* tp_new */ }; pyo/src/objects/exprmodule.c0000644000175000017500000011261412652732202015433 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" // arithmetic operators #define OP_ADD 0 #define OP_SUB 1 #define OP_MUL 2 #define OP_DIV 3 #define OP_EXP 4 #define OP_MOD 5 #define OP_NEG 6 // moving phase operators #define OP_INC 7 #define OP_DEC 8 #define OP_PHS 9 // trigonometric functions #define OP_SIN 10 #define OP_COS 11 #define OP_TAN 12 #define OP_TANH 13 #define OP_ATAN 14 #define OP_ATAN2 15 // conditional operators #define OP_LT 40 #define OP_LE 41 #define OP_GT 42 #define OP_GE 43 #define OP_EQ 44 #define OP_NE 45 #define OP_IF 46 #define OP_AND 47 #define OP_OR 48 // power and logarithmic functions #define OP_SQRT 50 #define OP_LOG 51 #define OP_LOG2 52 #define OP_LOG10 53 #define OP_POW 54 #define OP_FABS 55 #define OP_FLOOR 56 #define OP_CEIL 57 #define OP_EEXP 58 #define OP_ROUND 59 #define OP_MIN 60 #define OP_MAX 61 #define OP_WRAP 62 // filters #define OP_RPOLE 70 #define OP_RZERO 71 // random functions #define OP_RANDF 80 #define OP_RANDI 81 // sample-and-hold functions #define OP_SAH 90 // math constants #define OP_CONST 99 #define OP_PI 100 #define OP_TWOPI 101 #define OP_E 102 typedef struct t_expr { int type_op; int num; int *nodes; int *vars; int *input; int *output; MYFLT *values; MYFLT *previous; MYFLT result; } expr; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *variables; int count; MYFLT oneOverSr; MYFLT *input_buffer; MYFLT *output_buffer; expr lexp[1024]; int modebuffer[2]; } Expr; void clearexpr(expr ex) { if (ex.nodes) { free(ex.nodes); } if (ex.vars) { free(ex.vars); } if (ex.input) { free(ex.input); } if (ex.output) { free(ex.output); } if (ex.values) { free(ex.values); } if (ex.previous) { free(ex.previous); } } expr initexpr(const char *op, int size) { expr ex; int i, value = -1, num = 0; if (strcmp(op, "+") == 0) { value = OP_ADD; num = 2; } else if (strcmp(op, "-") == 0) { value = OP_SUB; num = 2; } else if (strcmp(op, "*") == 0) {value = OP_MUL; num = 2; } else if (strcmp(op, "/") == 0) {value = OP_DIV; num = 2; } else if (strcmp(op, "^") == 0) {value = OP_EXP; num = 2; } else if (strcmp(op, "%") == 0) {value = OP_MOD; num = 2; } else if (strcmp(op, "neg") == 0) {value = OP_NEG; num = 1; } else if (strcmp(op, "++") == 0) {value = OP_INC; num = 2; } else if (strcmp(op, "--") == 0) {value = OP_DEC; num = 2; } else if (strcmp(op, "~") == 0) {value = OP_PHS; num = 2; } else if (strcmp(op, "sin") == 0) {value = OP_SIN; num = 1; } else if (strcmp(op, "cos") == 0) {value = OP_COS; num = 1; } else if (strcmp(op, "tan") == 0) {value = OP_TAN; num = 1; } else if (strcmp(op, "tanh") == 0) {value = OP_TANH; num = 1; } else if (strcmp(op, "atan") == 0) {value = OP_ATAN; num = 1; } else if (strcmp(op, "atan2") == 0) {value = OP_ATAN2; num = 2; } else if (strcmp(op, "<") == 0) {value = OP_LT; num = 2; } else if (strcmp(op, "<=") == 0) {value = OP_LE; num = 2; } else if (strcmp(op, ">") == 0) {value = OP_GT; num = 2; } else if (strcmp(op, ">=") == 0) {value = OP_GE; num = 2; } else if (strcmp(op, "==") == 0) {value = OP_EQ; num = 2; } else if (strcmp(op, "!=") == 0) {value = OP_NE; num = 2; } else if (strcmp(op, "if") == 0) {value = OP_IF; num = 3; } else if (strcmp(op, "and") == 0) {value = OP_AND; num = 2; } else if (strcmp(op, "or") == 0) {value = OP_OR; num = 2; } else if (strcmp(op, "sqrt") == 0) {value = OP_SQRT; num = 1; } else if (strcmp(op, "log") == 0) {value = OP_LOG; num = 1; } else if (strcmp(op, "log2") == 0) {value = OP_LOG2; num = 1; } else if (strcmp(op, "log10") == 0) {value = OP_LOG10; num = 1; } else if (strcmp(op, "pow") == 0) {value = OP_POW; num = 2; } else if (strcmp(op, "abs") == 0) {value = OP_FABS; num = 1; } else if (strcmp(op, "floor") == 0) {value = OP_FLOOR; num = 1; } else if (strcmp(op, "ceil") == 0) {value = OP_CEIL; num = 1; } else if (strcmp(op, "exp") == 0) {value = OP_EEXP; num = 1; } else if (strcmp(op, "round") == 0) {value = OP_ROUND; num = 1; } else if (strcmp(op, "min") == 0) {value = OP_MIN; num = 2; } else if (strcmp(op, "max") == 0) {value = OP_MAX; num = 2; } else if (strcmp(op, "wrap") == 0) {value = OP_WRAP; num = 1; } else if (strcmp(op, "randf") == 0) {value = OP_RANDF; num = 2; } else if (strcmp(op, "randi") == 0) {value = OP_RANDI; num = 2; } else if (strcmp(op, "sah") == 0) {value = OP_SAH; num = 2; } // stream, trigger else if (strcmp(op, "rpole") == 0) {value = OP_RPOLE; num = 2; } else if (strcmp(op, "rzero") == 0) {value = OP_RZERO; num = 2; } else if (strcmp(op, "const") == 0) {value = OP_CONST; num = 1; } else if (strcmp(op, "pi") == 0) {value = OP_PI; num = 0; } else if (strcmp(op, "twopi") == 0) {value = OP_TWOPI; num = 0; } else if (strcmp(op, "e") == 0) {value = OP_E; num = 0; } else if (size == 1) {value = OP_CONST; num = 1; } ex.type_op = value; ex.num = num; ex.nodes = (int *)malloc(num); ex.vars = (int *)malloc(num); ex.input = (int *)malloc(num); ex.output = (int *)malloc(num); ex.values = (MYFLT *)malloc(num); ex.previous = (MYFLT *)malloc(num); for (i=0; iinput_stream); if (self->count == 0) { for (i=0; ibufsize; i++) { self->data[i] = in[i]; } } else { for (i=0; ibufsize; i++) { self->input_buffer[i] = in[i]; for (j=0; jcount; j++) { for (k=0; klexp[j].num; k++) { if (self->lexp[j].nodes[k] != -1) { self->lexp[j].values[k] = self->lexp[self->lexp[j].nodes[k]].result; } else if (self->lexp[j].vars[k] != -1) { self->lexp[j].values[k] = self->lexp[self->lexp[j].vars[k]].result; } else if (self->lexp[j].input[k] < 1) { pos = i + self->lexp[j].input[k]; if (pos < 0) pos += self->bufsize; self->lexp[j].values[k] = self->input_buffer[pos]; } else if (self->lexp[j].output[k] < 0) { pos = i + self->lexp[j].output[k]; if (pos < 0) pos += self->bufsize; self->lexp[j].values[k] = self->output_buffer[pos]; } } switch (self->lexp[j].type_op) { case OP_ADD: self->lexp[j].result = self->lexp[j].values[0] + self->lexp[j].values[1]; break; case OP_SUB: self->lexp[j].result = self->lexp[j].values[0] - self->lexp[j].values[1]; break; case OP_MUL: self->lexp[j].result = self->lexp[j].values[0] * self->lexp[j].values[1]; break; case OP_DIV: self->lexp[j].result = self->lexp[j].values[0] / self->lexp[j].values[1]; break; case OP_EXP: self->lexp[j].result = MYPOW(self->lexp[j].values[0], self->lexp[j].values[1]); break; case OP_MOD: self->lexp[j].result = MYFMOD(self->lexp[j].values[0], self->lexp[j].values[1]); break; case OP_NEG: self->lexp[j].result = -self->lexp[j].values[0]; break; case OP_INC: self->lexp[j].result = self->lexp[j].previous[0]; self->lexp[j].previous[0] = MYFMOD(self->lexp[j].previous[0] + self->lexp[j].values[0], self->lexp[j].values[1]); break; case OP_DEC: self->lexp[j].result -= self->lexp[j].values[0]; if (self->lexp[j].result < 0) { self->lexp[j].result += self->lexp[j].values[1]; } break; case OP_PHS: tmp = self->lexp[j].previous[0] + self->lexp[j].values[1]; if (tmp >= 1) { tmp -= 1.0; } self->lexp[j].result = tmp; self->lexp[j].previous[0] += (self->lexp[j].values[0] * self->oneOverSr); if (self->lexp[j].previous[0] >= 1) { self->lexp[j].previous[0] -= 1.0; } break; case OP_SIN: self->lexp[j].result = MYSIN(self->lexp[j].values[0]); break; case OP_COS: self->lexp[j].result = MYCOS(self->lexp[j].values[0]); break; case OP_TAN: self->lexp[j].result = MYTAN(self->lexp[j].values[0]); break; case OP_TANH: self->lexp[j].result = MYTANH(self->lexp[j].values[0]); break; case OP_ATAN: self->lexp[j].result = MYATAN(self->lexp[j].values[0]); break; case OP_ATAN2: self->lexp[j].result = MYATAN2(self->lexp[j].values[0], self->lexp[j].values[1]); break; case OP_LT: self->lexp[j].result = self->lexp[j].values[0] < self->lexp[j].values[1] ? 1.0 : 0.0; break; case OP_LE: self->lexp[j].result = self->lexp[j].values[0] <= self->lexp[j].values[1] ? 1.0 : 0.0; break; case OP_GT: self->lexp[j].result = self->lexp[j].values[0] > self->lexp[j].values[1] ? 1.0 : 0.0; break; case OP_GE: self->lexp[j].result = self->lexp[j].values[0] >= self->lexp[j].values[1] ? 1.0 : 0.0; break; case OP_EQ: self->lexp[j].result = self->lexp[j].values[0] == self->lexp[j].values[1] ? 1.0 : 0.0; break; case OP_NE: self->lexp[j].result = self->lexp[j].values[0] != self->lexp[j].values[1] ? 1.0 : 0.0; break; case OP_IF: self->lexp[j].result = self->lexp[j].values[0] != 0 ? self->lexp[j].values[1] : self->lexp[j].values[2]; break; case OP_AND: self->lexp[j].result = self->lexp[j].values[0] != 0 && self->lexp[j].values[1] != 0 ? 1.0 : 0.0; break; case OP_OR: self->lexp[j].result = self->lexp[j].values[0] != 0 || self->lexp[j].values[1] != 0 ? 1.0 : 0.0; break; case OP_SQRT: self->lexp[j].result = MYSQRT(self->lexp[j].values[0]); break; case OP_LOG: self->lexp[j].result = MYLOG(self->lexp[j].values[0]); break; case OP_LOG2: self->lexp[j].result = MYLOG2(self->lexp[j].values[0]); break; case OP_LOG10: self->lexp[j].result = MYLOG10(self->lexp[j].values[0]); break; case OP_POW: self->lexp[j].result = MYPOW(self->lexp[j].values[0], self->lexp[j].values[1]); break; case OP_FABS: self->lexp[j].result = MYFABS(self->lexp[j].values[0]); break; case OP_FLOOR: self->lexp[j].result = MYFLOOR(self->lexp[j].values[0]); break; case OP_CEIL: self->lexp[j].result = MYCEIL(self->lexp[j].values[0]); break; case OP_EEXP: self->lexp[j].result = MYEXP(self->lexp[j].values[0]); break; case OP_ROUND: self->lexp[j].result = MYROUND(self->lexp[j].values[0]); break; case OP_MIN: self->lexp[j].result = self->lexp[j].values[0] < self->lexp[j].values[1] ? self->lexp[j].values[0] : self->lexp[j].values[1]; break; case OP_MAX: self->lexp[j].result = self->lexp[j].values[0] > self->lexp[j].values[1] ? self->lexp[j].values[0] : self->lexp[j].values[1]; break; case OP_WRAP: tmp = self->lexp[j].values[0]; while (tmp < 0.0) {tmp += 1.0; } while (tmp >= 1.0) {tmp -= 1.0; } self->lexp[j].result = tmp; break; case OP_RANDF: self->lexp[j].result = RANDOM_UNIFORM * (self->lexp[j].values[1] - self->lexp[j].values[0]) + self->lexp[j].values[0]; break; case OP_RANDI: self->lexp[j].result = MYFLOOR(RANDOM_UNIFORM * (self->lexp[j].values[1] - self->lexp[j].values[0]) + self->lexp[j].values[0]); break; case OP_SAH: self->lexp[j].result = self->lexp[j].values[1] < self->lexp[j].previous[1] ? self->lexp[j].values[0] : self->lexp[j].result; self->lexp[j].previous[1] = self->lexp[j].values[1]; break; case OP_RPOLE: self->lexp[j].result = self->lexp[j].values[0] + self->lexp[j].result * self->lexp[j].values[1]; break; case OP_RZERO: self->lexp[j].result = self->lexp[j].values[0] - self->lexp[j].previous[0] * self->lexp[j].values[1]; self->lexp[j].previous[0] = self->lexp[j].values[0]; break; case OP_CONST: self->lexp[j].result = self->lexp[j].values[0]; break; case OP_PI: self->lexp[j].result = PI; break; case OP_TWOPI: self->lexp[j].result = TWOPI; break; case OP_E: self->lexp[j].result = E; break; } result = self->lexp[j].result; } self->data[i] = self->output_buffer[i] = result; } } } static void Expr_postprocessing_ii(Expr *self) { POST_PROCESSING_II }; static void Expr_postprocessing_ai(Expr *self) { POST_PROCESSING_AI }; static void Expr_postprocessing_ia(Expr *self) { POST_PROCESSING_IA }; static void Expr_postprocessing_aa(Expr *self) { POST_PROCESSING_AA }; static void Expr_postprocessing_ireva(Expr *self) { POST_PROCESSING_IREVA }; static void Expr_postprocessing_areva(Expr *self) { POST_PROCESSING_AREVA }; static void Expr_postprocessing_revai(Expr *self) { POST_PROCESSING_REVAI }; static void Expr_postprocessing_revaa(Expr *self) { POST_PROCESSING_REVAA }; static void Expr_postprocessing_revareva(Expr *self) { POST_PROCESSING_REVAREVA }; static void Expr_setProcMode(Expr *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Expr_process; switch (muladdmode) { case 0: self->muladd_func_ptr = Expr_postprocessing_ii; break; case 1: self->muladd_func_ptr = Expr_postprocessing_ai; break; case 2: self->muladd_func_ptr = Expr_postprocessing_revai; break; case 10: self->muladd_func_ptr = Expr_postprocessing_ia; break; case 11: self->muladd_func_ptr = Expr_postprocessing_aa; break; case 12: self->muladd_func_ptr = Expr_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Expr_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Expr_postprocessing_areva; break; case 22: self->muladd_func_ptr = Expr_postprocessing_revareva; break; } } static void Expr_compute_next_data_frame(Expr *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Expr_traverse(Expr *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->variables); return 0; } static int Expr_clear(Expr *self) { int i; pyo_CLEAR for (i=0; icount; i++) { clearexpr(self->lexp[i]); } free(self->input_buffer); free(self->output_buffer); Py_CLEAR(self->input); Py_CLEAR(self->variables); return 0; } static void Expr_dealloc(Expr* self) { pyo_DEALLOC Expr_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Expr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *exprtmp=NULL, *multmp=NULL, *addtmp=NULL; Expr *self; self = (Expr *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Expr_compute_next_data_frame); self->mode_func_ptr = Expr_setProcMode; self->oneOverSr = 1.0 / self->sr; self->variables = PyDict_New(); static char *kwlist[] = {"input", "expr", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &exprtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (exprtmp) { PyObject_CallMethod((PyObject *)self, "setExpr", "O", exprtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->input_buffer = (MYFLT *)realloc(self->input_buffer, self->bufsize * sizeof(MYFLT)); self->output_buffer = (MYFLT *)realloc(self->output_buffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->input_buffer[i] = self->output_buffer[i] = 0.0; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Expr_getServer(Expr* self) { GET_SERVER }; static PyObject * Expr_getStream(Expr* self) { GET_STREAM }; static PyObject * Expr_setMul(Expr *self, PyObject *arg) { SET_MUL }; static PyObject * Expr_setAdd(Expr *self, PyObject *arg) { SET_ADD }; static PyObject * Expr_setSub(Expr *self, PyObject *arg) { SET_SUB }; static PyObject * Expr_setDiv(Expr *self, PyObject *arg) { SET_DIV }; static PyObject * Expr_play(Expr *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Expr_out(Expr *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Expr_stop(Expr *self) { STOP }; static PyObject * Expr_multiply(Expr *self, PyObject *arg) { MULTIPLY }; static PyObject * Expr_inplace_multiply(Expr *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Expr_add(Expr *self, PyObject *arg) { ADD }; static PyObject * Expr_inplace_add(Expr *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Expr_sub(Expr *self, PyObject *arg) { SUB }; static PyObject * Expr_inplace_sub(Expr *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Expr_div(Expr *self, PyObject *arg) { DIV }; static PyObject * Expr_inplace_div(Expr *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Expr_setExpr(Expr *self, PyObject *arg) { int i, j = 0, count = 0; PyObject *sentence = NULL, *exp = NULL, *explist = NULL, *tmpstr = NULL; PyObject *varDict = NULL, *waitingDict = NULL, *waitingList = NULL; Py_ssize_t len, start, end; PyDict_Clear(self->variables); varDict = PyDict_New(); waitingDict = PyDict_New(); if (PyString_Check(arg)) { Py_INCREF(arg); Py_XDECREF(sentence); sentence = arg; len = PyString_Size(sentence); if (len == 0) { Py_INCREF(Py_None); return Py_None; } if (PyUnicode_Count(sentence, PyString_FromString(")"), 0, len) != PyUnicode_Count(sentence, PyString_FromString("("), 0, len)) { printf("Expr: mismatched brackets, expression bypassed.\n"); Py_INCREF(Py_None); return Py_None; } for (i=0; icount; i++) { clearexpr(self->lexp[i]); } self->count = 0; while (PyUnicode_Find(sentence, PyString_FromString(")"), 0, len, 1) != -1) { end = PyUnicode_Find(sentence, PyString_FromString(")"), 0, len, 1) + 1; start = PyUnicode_Find(sentence, PyString_FromString("("), 0, end, -1); exp = PySequence_GetSlice(sentence, start, end); if (PyUnicode_Contains(exp, PyString_FromString("let ")) || PyUnicode_Contains(exp, PyString_FromString("var "))) { sentence = PyUnicode_Concat(PySequence_GetSlice(sentence, 0, start), PySequence_GetSlice(sentence, end, len)); } else { sentence = PyUnicode_Replace(sentence, exp, PyUnicode_Format(PyString_FromString("_%d"), PyInt_FromLong(self->count)), 1); } exp = PyUnicode_Replace(exp, PyString_FromString("("), PyString_FromString(""), -1); exp = PyUnicode_Replace(exp, PyString_FromString(")"), PyString_FromString(""), -1); explist = PyUnicode_Split(exp, NULL, -1); // Prepare variable from "var" function if (PyUnicode_Compare(PyList_GetItem(explist, 0), PyString_FromString("var")) == 0) { PyList_SetItem(explist, 0, PyString_FromString("const")); PyDict_SetItem(self->variables, PyList_GetItem(explist, 1), PyInt_FromLong(self->count)); PySequence_DelItem(explist, 1); } // Prepare variable from "let" function if (PyUnicode_Compare(PyList_GetItem(explist, 0), PyString_FromString("let")) == 0) { PyList_SetItem(explist, 0, PyString_FromString("const")); if (PyDict_GetItem(waitingDict, PyList_GetItem(explist, 1)) != NULL) { waitingList = PyDict_GetItem(waitingDict, PyList_GetItem(explist, 1)); for (j=0; jlexp[count].vars[i] = self->count; } PyDict_DelItem(waitingDict, PyList_GetItem(explist, 1)); } PyDict_SetItem(varDict, PyList_GetItem(explist, 1), PyInt_FromLong(self->count)); PySequence_DelItem(explist, 1); } // Initialize expression node self->lexp[self->count] = initexpr(PyString_AsString(PyList_GetItem(explist, 0)), PyList_Size(explist)); if (PyList_Size(explist) == 1 && self->lexp[self->count].type_op == OP_CONST) { PyList_Insert(explist, 0, PyString_FromString("const")); } while (PyList_Size(explist) < (self->lexp[self->count].num+1)) { PyList_Append(explist, PyString_FromString("0.0")); } for (i=0; ilexp[self->count].num; i++) { if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyString_FromString("_"))) { tmpstr = PyUnicode_Replace(PyList_GetItem(explist, i+1), PyString_FromString("_"), PyString_FromString(""), -1); self->lexp[self->count].nodes[i] = PyInt_AsLong(PyInt_FromString(PyString_AsString(tmpstr), NULL, 0)); } else if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyString_FromString("#"))) { if (PyDict_GetItem(self->variables, PyList_GetItem(explist, i+1)) != NULL) { self->lexp[self->count].vars[i] = PyInt_AsLong(PyDict_GetItem(self->variables, PyList_GetItem(explist, i+1))); } else if (PyDict_GetItem(varDict, PyList_GetItem(explist, i+1)) != NULL) { self->lexp[self->count].vars[i] = PyInt_AsLong(PyDict_GetItem(varDict, PyList_GetItem(explist, i+1))); } else { if (PyDict_GetItem(waitingDict, PyList_GetItem(explist, i+1)) == NULL) waitingList = PyList_New(0); else waitingList = PyDict_GetItem(waitingDict, PyList_GetItem(explist, i+1)); PyList_Append(waitingList, PyTuple_Pack(2, PyInt_FromLong(self->count), PyInt_FromLong(i))); PyDict_SetItem(waitingDict, PyList_GetItem(explist, i+1), waitingList); } } else if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyString_FromString("$x"))) { tmpstr = PyUnicode_Replace(PyList_GetItem(explist, i+1), PyString_FromString("$x"), PyString_FromString(""), -1); tmpstr = PyUnicode_Replace(tmpstr, PyString_FromString("["), PyString_FromString(""), -1); tmpstr = PyUnicode_Replace(tmpstr, PyString_FromString("]"), PyString_FromString(""), -1); self->lexp[self->count].input[i] = PyInt_AsLong(PyInt_FromString(PyString_AsString(tmpstr), NULL, 0)); } else if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyString_FromString("$y"))) { tmpstr = PyUnicode_Replace(PyList_GetItem(explist, i+1), PyString_FromString("$y"), PyString_FromString(""), -1); tmpstr = PyUnicode_Replace(tmpstr, PyString_FromString("["), PyString_FromString(""), -1); tmpstr = PyUnicode_Replace(tmpstr, PyString_FromString("]"), PyString_FromString(""), -1); self->lexp[self->count].output[i] = PyInt_AsLong(PyInt_FromString(PyString_AsString(tmpstr), NULL, 0)); } else { self->lexp[self->count].values[i] = PyFloat_AsDouble(PyFloat_FromString(PyList_GetItem(explist, i+1), NULL)); } } len = PyString_Size(sentence); self->count++; } explist = PyUnicode_Split(sentence, NULL, -1); if (PyList_Size(explist) == 1) PyList_Insert(explist, 0, PyString_FromString("const")); // Initialize last expression node self->lexp[self->count] = initexpr(PyString_AsString(PyList_GetItem(explist, 0)), PyList_Size(explist)); for (i=0; ilexp[self->count].num; i++) { if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyString_FromString("_"))) { tmpstr = PyUnicode_Replace(PyList_GetItem(explist, i+1), PyString_FromString("_"), PyString_FromString(""), -1); self->lexp[self->count].nodes[i] = PyInt_AsLong(PyInt_FromString(PyString_AsString(tmpstr), NULL, 0)); } else if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyString_FromString("#"))) { self->lexp[self->count].vars[i] = PyInt_AsLong(PyDict_GetItem(varDict, PyList_GetItem(explist, i+1))); } else if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyString_FromString("$x"))) { tmpstr = PyUnicode_Replace(PyList_GetItem(explist, i+1), PyString_FromString("$x"), PyString_FromString(""), -1); tmpstr = PyUnicode_Replace(tmpstr, PyString_FromString("["), PyString_FromString(""), -1); tmpstr = PyUnicode_Replace(tmpstr, PyString_FromString("]"), PyString_FromString(""), -1); self->lexp[self->count].input[i] = PyInt_AsLong(PyInt_FromString(PyString_AsString(tmpstr), NULL, 0)); } else if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyString_FromString("$y"))) { tmpstr = PyUnicode_Replace(PyList_GetItem(explist, i+1), PyString_FromString("$y"), PyString_FromString(""), -1); tmpstr = PyUnicode_Replace(tmpstr, PyString_FromString("["), PyString_FromString(""), -1); tmpstr = PyUnicode_Replace(tmpstr, PyString_FromString("]"), PyString_FromString(""), -1); self->lexp[self->count].output[i] = PyInt_AsLong(PyInt_FromString(PyString_AsString(tmpstr), NULL, 0)); } else { self->lexp[self->count].values[i] = PyFloat_AsDouble(PyFloat_FromString(PyList_GetItem(explist, i+1), NULL)); } } self->count++; } Py_XDECREF(sentence); Py_XDECREF(exp); Py_XDECREF(explist); Py_XDECREF(tmpstr); Py_XDECREF(varDict); Py_XDECREF(waitingDict); Py_XDECREF(waitingList); Py_INCREF(Py_None); return Py_None; } static PyObject * Expr_setVar(Expr *self, PyObject *args, PyObject *kwds) { int index; PyObject *varname = NULL, *value = NULL; static char *kwlist[] = {"varname", "value", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &varname, &value)) Py_RETURN_NONE; if (PyDict_GetItem(self->variables, varname)) { index = PyInt_AsLong(PyDict_GetItem(self->variables, varname)); self->lexp[index].values[0] = PyFloat_AsDouble(value); } Py_INCREF(Py_None); return Py_None; } static PyObject * Expr_printNodes(Expr *self) { int i; for (i=0; icount; i++) { print_expr(self->lexp[i], i); } Py_INCREF(Py_None); return Py_None; }; static PyMemberDef Expr_members[] = { {"server", T_OBJECT_EX, offsetof(Expr, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Expr, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Expr, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(Expr, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Expr, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Expr_methods[] = { {"getServer", (PyCFunction)Expr_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Expr_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Expr_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Expr_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Expr_stop, METH_NOARGS, "Stops computing."}, {"printNodes", (PyCFunction)Expr_printNodes, METH_NOARGS, "Print the list of nodes."}, {"setVar", (PyCFunction)Expr_setVar, METH_VARARGS|METH_KEYWORDS, "Sets a variable value."}, {"setExpr", (PyCFunction)Expr_setExpr, METH_O, "Sets a new expression."}, {"setMul", (PyCFunction)Expr_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Expr_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Expr_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Expr_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Expr_as_number = { (binaryfunc)Expr_add, /*nb_add*/ (binaryfunc)Expr_sub, /*nb_subtract*/ (binaryfunc)Expr_multiply, /*nb_multiply*/ (binaryfunc)Expr_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Expr_inplace_add, /*inplace_add*/ (binaryfunc)Expr_inplace_sub, /*inplace_subtract*/ (binaryfunc)Expr_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Expr_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ExprType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Expr_base", /*tp_name*/ sizeof(Expr), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Expr_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Expr_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Expr objects. Resolve a prefix notation sentence at audio rate.", /* tp_doc */ (traverseproc)Expr_traverse, /* tp_traverse */ (inquiry)Expr_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Expr_methods, /* tp_methods */ Expr_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Expr_new, /* tp_new */ }; pyo/src/objects/hilbertmodule.c0000644000175000017500000004362212652732202016110 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; MYFLT coefs[12]; // sample memories MYFLT x1[12]; MYFLT y1[12]; MYFLT *buffer_streams; } HilbertMain; /* 6th order allpass poles */ static const MYFLT poles[12] = {.3609, 2.7412, 11.1573, 44.7581, 179.6242, 798.4578, 1.2524, 5.5671, 22.3423, 89.6271, 364.7914, 2770.1114}; static void HilbertMain_compute_variables(HilbertMain *self) { int i; MYFLT polefreq[12]; MYFLT rc[12]; MYFLT alpha[12]; for (i=0; i<12; i++) { polefreq[i] = poles[i] * 15.0; rc[i] = 1.0 / (TWOPI * polefreq[i]); alpha[i] = 1.0 / rc[i]; self->coefs[i] = - (1.0 - (alpha[i] / (2.0 * self->sr))) / (1.0 + (alpha[i] / (2.0 * self->sr))); } } static void HilbertMain_filters(HilbertMain *self) { MYFLT xn1, xn2, yn1, yn2; int j, i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { xn1 = in[i]; for (j=0; j<6; j++) { yn1 = self->coefs[j] * (xn1 - self->y1[j]) + self->x1[j]; self->x1[j] = xn1; self->y1[j] = yn1; xn1 = yn1; } xn2 = in[i]; for (j=6; j<12; j++) { yn2 = self->coefs[j] * (xn2 - self->y1[j]) + self->x1[j]; self->x1[j] = xn2; self->y1[j] = yn2; xn2 = yn2; } self->buffer_streams[i] = yn1; self->buffer_streams[i+self->bufsize] = yn2; } } MYFLT * HilbertMain_getSamplesBuffer(HilbertMain *self) { return (MYFLT *)self->buffer_streams; } static void HilbertMain_setProcMode(HilbertMain *self) { self->proc_func_ptr = HilbertMain_filters; } static void HilbertMain_compute_next_data_frame(HilbertMain *self) { (*self->proc_func_ptr)(self); } static int HilbertMain_traverse(HilbertMain *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int HilbertMain_clear(HilbertMain *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void HilbertMain_dealloc(HilbertMain* self) { pyo_DEALLOC free(self->buffer_streams); HilbertMain_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * HilbertMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp; HilbertMain *self; self = (HilbertMain *)type->tp_alloc(type, 0); INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, HilbertMain_compute_next_data_frame); self->mode_func_ptr = HilbertMain_setProcMode; for (i=0; i<12; i++) { self->x1[i] = 0.0; self->y1[i] = 0.0; } static char *kwlist[] = {"input", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &inputtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, 2 * self->bufsize * sizeof(MYFLT)); HilbertMain_compute_variables((HilbertMain *)self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * HilbertMain_getServer(HilbertMain* self) { GET_SERVER }; static PyObject * HilbertMain_getStream(HilbertMain* self) { GET_STREAM }; static PyObject * HilbertMain_play(HilbertMain *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * HilbertMain_stop(HilbertMain *self) { STOP }; static PyMemberDef HilbertMain_members[] = { {"server", T_OBJECT_EX, offsetof(HilbertMain, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(HilbertMain, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(HilbertMain, input), 0, "Input sound object."}, {NULL} /* Sentinel */ }; static PyMethodDef HilbertMain_methods[] = { {"getServer", (PyCFunction)HilbertMain_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)HilbertMain_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)HilbertMain_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)HilbertMain_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject HilbertMainType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.HilbertMain_base", /*tp_name*/ sizeof(HilbertMain), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)HilbertMain_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "HilbertMain objects. Hilbert transform. Created real and imaginary parts from an audio stream", /* tp_doc */ (traverseproc)HilbertMain_traverse, /* tp_traverse */ (inquiry)HilbertMain_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ HilbertMain_methods, /* tp_methods */ HilbertMain_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ HilbertMain_new, /* tp_new */ }; /************************************************************************************************/ /* Hilbert streamer object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD HilbertMain *mainSplitter; int modebuffer[2]; int chnl; // 0 = real, 1 = imag } Hilbert; static void Hilbert_postprocessing_ii(Hilbert *self) { POST_PROCESSING_II }; static void Hilbert_postprocessing_ai(Hilbert *self) { POST_PROCESSING_AI }; static void Hilbert_postprocessing_ia(Hilbert *self) { POST_PROCESSING_IA }; static void Hilbert_postprocessing_aa(Hilbert *self) { POST_PROCESSING_AA }; static void Hilbert_postprocessing_ireva(Hilbert *self) { POST_PROCESSING_IREVA }; static void Hilbert_postprocessing_areva(Hilbert *self) { POST_PROCESSING_AREVA }; static void Hilbert_postprocessing_revai(Hilbert *self) { POST_PROCESSING_REVAI }; static void Hilbert_postprocessing_revaa(Hilbert *self) { POST_PROCESSING_REVAA }; static void Hilbert_postprocessing_revareva(Hilbert *self) { POST_PROCESSING_REVAREVA }; static void Hilbert_setProcMode(Hilbert *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Hilbert_postprocessing_ii; break; case 1: self->muladd_func_ptr = Hilbert_postprocessing_ai; break; case 2: self->muladd_func_ptr = Hilbert_postprocessing_revai; break; case 10: self->muladd_func_ptr = Hilbert_postprocessing_ia; break; case 11: self->muladd_func_ptr = Hilbert_postprocessing_aa; break; case 12: self->muladd_func_ptr = Hilbert_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Hilbert_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Hilbert_postprocessing_areva; break; case 22: self->muladd_func_ptr = Hilbert_postprocessing_revareva; break; } } static void Hilbert_compute_next_data_frame(Hilbert *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = HilbertMain_getSamplesBuffer((HilbertMain *)self->mainSplitter); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int Hilbert_traverse(Hilbert *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainSplitter); return 0; } static int Hilbert_clear(Hilbert *self) { pyo_CLEAR Py_CLEAR(self->mainSplitter); return 0; } static void Hilbert_dealloc(Hilbert* self) { pyo_DEALLOC Hilbert_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Hilbert_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; Hilbert *self; self = (Hilbert *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Hilbert_compute_next_data_frame); self->mode_func_ptr = Hilbert_setProcMode; static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainSplitter); Py_INCREF(maintmp); self->mainSplitter = (HilbertMain *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Hilbert_getServer(Hilbert* self) { GET_SERVER }; static PyObject * Hilbert_getStream(Hilbert* self) { GET_STREAM }; static PyObject * Hilbert_setMul(Hilbert *self, PyObject *arg) { SET_MUL }; static PyObject * Hilbert_setAdd(Hilbert *self, PyObject *arg) { SET_ADD }; static PyObject * Hilbert_setSub(Hilbert *self, PyObject *arg) { SET_SUB }; static PyObject * Hilbert_setDiv(Hilbert *self, PyObject *arg) { SET_DIV }; static PyObject * Hilbert_play(Hilbert *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Hilbert_out(Hilbert *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Hilbert_stop(Hilbert *self) { STOP }; static PyObject * Hilbert_multiply(Hilbert *self, PyObject *arg) { MULTIPLY }; static PyObject * Hilbert_inplace_multiply(Hilbert *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Hilbert_add(Hilbert *self, PyObject *arg) { ADD }; static PyObject * Hilbert_inplace_add(Hilbert *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Hilbert_sub(Hilbert *self, PyObject *arg) { SUB }; static PyObject * Hilbert_inplace_sub(Hilbert *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Hilbert_div(Hilbert *self, PyObject *arg) { DIV }; static PyObject * Hilbert_inplace_div(Hilbert *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Hilbert_members[] = { {"server", T_OBJECT_EX, offsetof(Hilbert, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Hilbert, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Hilbert, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Hilbert, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Hilbert_methods[] = { {"getServer", (PyCFunction)Hilbert_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Hilbert_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Hilbert_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Hilbert_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Hilbert_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Hilbert_setMul, METH_O, "Sets Hilbert mul factor."}, {"setAdd", (PyCFunction)Hilbert_setAdd, METH_O, "Sets Hilbert add factor."}, {"setSub", (PyCFunction)Hilbert_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Hilbert_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Hilbert_as_number = { (binaryfunc)Hilbert_add, /*nb_add*/ (binaryfunc)Hilbert_sub, /*nb_subtract*/ (binaryfunc)Hilbert_multiply, /*nb_multiply*/ (binaryfunc)Hilbert_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Hilbert_inplace_add, /*inplace_add*/ (binaryfunc)Hilbert_inplace_sub, /*inplace_subtract*/ (binaryfunc)Hilbert_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Hilbert_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject HilbertType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Hilbert_base", /*tp_name*/ sizeof(Hilbert), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Hilbert_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Hilbert_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Hilbert objects. Reads one band from a Hilbert transform.", /* tp_doc */ (traverseproc)Hilbert_traverse, /* tp_traverse */ (inquiry)Hilbert_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Hilbert_methods, /* tp_methods */ Hilbert_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Hilbert_new, /* tp_new */ };pyo/src/objects/fadermodule.c0000644000175000017500000015452212652732202015542 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD int modebuffer[2]; int fademode; int ended; MYFLT topValue; MYFLT attack; MYFLT release; MYFLT duration; double currentTime; MYFLT sampleToSec; } Fader; static void Fader_internal_stop(Fader *self) { int i; Stream_setStreamActive(self->stream, 0); Stream_setStreamChnl(self->stream, 0); Stream_setStreamToDac(self->stream, 0); for (i=0; ibufsize; i++) { self->data[i] = 0; } } static void Fader_generate_auto(Fader *self) { MYFLT val; int i; if (self->ended == 1) { Fader_internal_stop((Fader *)self); return; } for (i=0; ibufsize; i++) { if (self->currentTime <= self->attack) val = self->currentTime / self->attack; else if (self->currentTime > self->duration) { val = 0.; self->ended = 1; } else if (self->currentTime >= (self->duration - self->release)) val = (self->duration - self->currentTime) / self->release; else val = 1.; self->data[i] = val; self->currentTime += self->sampleToSec; } } static void Fader_generate_wait(Fader *self) { MYFLT val; int i; if (self->fademode == 1 && self->currentTime > self->release) { Fader_internal_stop((Fader *)self); return; } for (i=0; ibufsize; i++) { if (self->fademode == 0) { if (self->currentTime <= self->attack) val = self->currentTime / self->attack; else val = 1.; self->topValue = val; } else { if (self->currentTime <= self->release) val = (1. - self->currentTime / self->release) * self->topValue; else val = 0.; } self->data[i] = val; self->currentTime += self->sampleToSec; } } static void Fader_postprocessing_ii(Fader *self) { POST_PROCESSING_II }; static void Fader_postprocessing_ai(Fader *self) { POST_PROCESSING_AI }; static void Fader_postprocessing_ia(Fader *self) { POST_PROCESSING_IA }; static void Fader_postprocessing_aa(Fader *self) { POST_PROCESSING_AA }; static void Fader_postprocessing_ireva(Fader *self) { POST_PROCESSING_IREVA }; static void Fader_postprocessing_areva(Fader *self) { POST_PROCESSING_AREVA }; static void Fader_postprocessing_revai(Fader *self) { POST_PROCESSING_REVAI }; static void Fader_postprocessing_revaa(Fader *self) { POST_PROCESSING_REVAA }; static void Fader_postprocessing_revareva(Fader *self) { POST_PROCESSING_REVAREVA }; static void Fader_setProcMode(Fader *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; if (self->duration == 0.0) self->proc_func_ptr = Fader_generate_wait; else self->proc_func_ptr = Fader_generate_auto; switch (muladdmode) { case 0: self->muladd_func_ptr = Fader_postprocessing_ii; break; case 1: self->muladd_func_ptr = Fader_postprocessing_ai; break; case 2: self->muladd_func_ptr = Fader_postprocessing_revai; break; case 10: self->muladd_func_ptr = Fader_postprocessing_ia; break; case 11: self->muladd_func_ptr = Fader_postprocessing_aa; break; case 12: self->muladd_func_ptr = Fader_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Fader_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Fader_postprocessing_areva; break; case 22: self->muladd_func_ptr = Fader_postprocessing_revareva; break; } } static void Fader_compute_next_data_frame(Fader *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Fader_traverse(Fader *self, visitproc visit, void *arg) { pyo_VISIT return 0; } static int Fader_clear(Fader *self) { pyo_CLEAR return 0; } static void Fader_dealloc(Fader* self) { pyo_DEALLOC Fader_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Fader_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *multmp=NULL, *addtmp=NULL; Fader *self; self = (Fader *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->topValue = 0.0; self->fademode = 0; self->ended = 0; self->attack = 0.01; self->release = 0.1; self->duration = 0.0; self->currentTime = 0.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Fader_compute_next_data_frame); self->mode_func_ptr = Fader_setProcMode; Stream_setStreamActive(self->stream, 0); self->sampleToSec = 1. / self->sr; static char *kwlist[] = {"fadein", "fadeout", "dur", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FFFOO, kwlist, &self->attack, &self->release, &self->duration, &multmp, &addtmp)) Py_RETURN_NONE; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Fader_getServer(Fader* self) { GET_SERVER }; static PyObject * Fader_getStream(Fader* self) { GET_STREAM }; static PyObject * Fader_setMul(Fader *self, PyObject *arg) { SET_MUL }; static PyObject * Fader_setAdd(Fader *self, PyObject *arg) { SET_ADD }; static PyObject * Fader_setSub(Fader *self, PyObject *arg) { SET_SUB }; static PyObject * Fader_setDiv(Fader *self, PyObject *arg) { SET_DIV }; static PyObject * Fader_play(Fader *self, PyObject *args, PyObject *kwds) { self->fademode = 0; self->ended = 0; self->currentTime = 0.0; (*self->mode_func_ptr)(self); PLAY }; static PyObject * Fader_stop(Fader *self) { if (self->duration == 0.0) { self->fademode = 1; self->currentTime = 0.0; } else Fader_internal_stop((Fader *)self); Py_INCREF(Py_None); return Py_None; } static PyObject * Fader_multiply(Fader *self, PyObject *arg) { MULTIPLY }; static PyObject * Fader_inplace_multiply(Fader *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Fader_add(Fader *self, PyObject *arg) { ADD }; static PyObject * Fader_inplace_add(Fader *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Fader_sub(Fader *self, PyObject *arg) { SUB }; static PyObject * Fader_inplace_sub(Fader *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Fader_div(Fader *self, PyObject *arg) { DIV }; static PyObject * Fader_inplace_div(Fader *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Fader_setFadein(Fader *self, PyObject *arg) { self->attack = PyFloat_AsDouble(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * Fader_setFadeout(Fader *self, PyObject *arg) { self->release = PyFloat_AsDouble(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * Fader_setDur(Fader *self, PyObject *arg) { self->duration = PyFloat_AsDouble(arg); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Fader_members[] = { {"server", T_OBJECT_EX, offsetof(Fader, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Fader, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Fader, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Fader, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Fader_methods[] = { {"getServer", (PyCFunction)Fader_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Fader_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Fader_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Fader_stop, METH_NOARGS, "Starts fadeout and stops computing."}, {"setMul", (PyCFunction)Fader_setMul, METH_O, "Sets Fader mul factor."}, {"setAdd", (PyCFunction)Fader_setAdd, METH_O, "Sets Fader add factor."}, {"setSub", (PyCFunction)Fader_setSub, METH_O, "Sets inverse add factor."}, {"setFadein", (PyCFunction)Fader_setFadein, METH_O, "Sets fadein time in seconds."}, {"setFadeout", (PyCFunction)Fader_setFadeout, METH_O, "Sets fadeout time in seconds."}, {"setDur", (PyCFunction)Fader_setDur, METH_O, "Sets duration in seconds (0 means wait for stop method to start fadeout)."}, {"setDiv", (PyCFunction)Fader_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Fader_as_number = { (binaryfunc)Fader_add, /*nb_add*/ (binaryfunc)Fader_sub, /*nb_subtract*/ (binaryfunc)Fader_multiply, /*nb_multiply*/ (binaryfunc)Fader_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Fader_inplace_add, /*inplace_add*/ (binaryfunc)Fader_inplace_sub, /*inplace_subtract*/ (binaryfunc)Fader_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Fader_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject FaderType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Fader_base", /*tp_name*/ sizeof(Fader), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Fader_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Fader_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Fader objects. Generates fadin and fadeout signal.", /* tp_doc */ (traverseproc)Fader_traverse, /* tp_traverse */ (inquiry)Fader_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Fader_methods, /* tp_methods */ Fader_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Fader_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD int modebuffer[2]; int fademode; MYFLT topValue; MYFLT attack; MYFLT decay; MYFLT sustain; MYFLT release; MYFLT duration; double currentTime; MYFLT sampleToSec; } Adsr; static void Adsr_internal_stop(Adsr *self) { int i; Stream_setStreamActive(self->stream, 0); Stream_setStreamChnl(self->stream, 0); Stream_setStreamToDac(self->stream, 0); for (i=0; ibufsize; i++) { self->data[i] = 0; } } static void Adsr_generate_auto(Adsr *self) { MYFLT val, invatt, invdec, invrel; int i; if (self->currentTime > self->duration) Adsr_internal_stop((Adsr *)self); invatt = 1.0 / self->attack; invdec = 1.0 / self->decay; invrel = 1.0 / self->release; for (i=0; ibufsize; i++) { if (self->currentTime <= self->attack) val = self->currentTime * invatt; else if (self->currentTime <= (self->attack + self->decay)) val = (self->decay - (self->currentTime - self->attack)) * invdec * (1. - self->sustain) + self->sustain; else if (self->currentTime > self->duration) val = 0.; else if (self->currentTime >= (self->duration - self->release)) val = (self->duration - self->currentTime) * invrel * self->sustain; else val = self->sustain; self->data[i] = val; self->currentTime += self->sampleToSec; } } static void Adsr_generate_wait(Adsr *self) { MYFLT val, invatt, invdec, invrel; int i; if (self->fademode == 1 && self->currentTime > self->release) Adsr_internal_stop((Adsr *)self); invatt = 1.0 / self->attack; invdec = 1.0 / self->decay; invrel = 1.0 / self->release; for (i=0; ibufsize; i++) { if (self->fademode == 0) { if (self->currentTime <= self->attack) val = self->currentTime * invatt; else if (self->currentTime <= (self->attack + self->decay)) val = (self->decay - (self->currentTime - self->attack)) * invdec * (1. - self->sustain) + self->sustain; else val = self->sustain; self->topValue = val; } else { if (self->currentTime <= self->release) { val = self->topValue * (1. - self->currentTime * invrel); } else val = 0.; } self->data[i] = val; self->currentTime += self->sampleToSec; } } static void Adsr_postprocessing_ii(Adsr *self) { POST_PROCESSING_II }; static void Adsr_postprocessing_ai(Adsr *self) { POST_PROCESSING_AI }; static void Adsr_postprocessing_ia(Adsr *self) { POST_PROCESSING_IA }; static void Adsr_postprocessing_aa(Adsr *self) { POST_PROCESSING_AA }; static void Adsr_postprocessing_ireva(Adsr *self) { POST_PROCESSING_IREVA }; static void Adsr_postprocessing_areva(Adsr *self) { POST_PROCESSING_AREVA }; static void Adsr_postprocessing_revai(Adsr *self) { POST_PROCESSING_REVAI }; static void Adsr_postprocessing_revaa(Adsr *self) { POST_PROCESSING_REVAA }; static void Adsr_postprocessing_revareva(Adsr *self) { POST_PROCESSING_REVAREVA }; static void Adsr_setProcMode(Adsr *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; if (self->duration == 0.0) self->proc_func_ptr = Adsr_generate_wait; else self->proc_func_ptr = Adsr_generate_auto; switch (muladdmode) { case 0: self->muladd_func_ptr = Adsr_postprocessing_ii; break; case 1: self->muladd_func_ptr = Adsr_postprocessing_ai; break; case 2: self->muladd_func_ptr = Adsr_postprocessing_revai; break; case 10: self->muladd_func_ptr = Adsr_postprocessing_ia; break; case 11: self->muladd_func_ptr = Adsr_postprocessing_aa; break; case 12: self->muladd_func_ptr = Adsr_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Adsr_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Adsr_postprocessing_areva; break; case 22: self->muladd_func_ptr = Adsr_postprocessing_revareva; break; } } static void Adsr_compute_next_data_frame(Adsr *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Adsr_traverse(Adsr *self, visitproc visit, void *arg) { pyo_VISIT return 0; } static int Adsr_clear(Adsr *self) { pyo_CLEAR return 0; } static void Adsr_dealloc(Adsr* self) { pyo_DEALLOC Adsr_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Adsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *multmp=NULL, *addtmp=NULL; Adsr *self; self = (Adsr *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->topValue = 0.0; self->fademode = 0; self->attack = 0.01; self->decay = 0.05; self->sustain = 0.707; self->release = 0.1; self->duration = 0.0; self->currentTime = 0.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Adsr_compute_next_data_frame); self->mode_func_ptr = Adsr_setProcMode; Stream_setStreamActive(self->stream, 0); self->sampleToSec = 1. / self->sr; static char *kwlist[] = {"attack", "decay", "sustain", "release", "dur", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FFFFFOO, kwlist, &self->attack, &self->decay, &self->sustain, &self->release, &self->duration, &multmp, &addtmp)) Py_RETURN_NONE; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (self->attack < 0.000001) self->attack = 0.000001; if (self->decay < 0.000001) self->decay = 0.000001; if (self->release < 0.000001) self->release = 0.000001; if (self->sustain < 0.0) self->sustain = 0.0; else if (self->sustain > 1.0) self->sustain = 1.0; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Adsr_getServer(Adsr* self) { GET_SERVER }; static PyObject * Adsr_getStream(Adsr* self) { GET_STREAM }; static PyObject * Adsr_setMul(Adsr *self, PyObject *arg) { SET_MUL }; static PyObject * Adsr_setAdd(Adsr *self, PyObject *arg) { SET_ADD }; static PyObject * Adsr_setSub(Adsr *self, PyObject *arg) { SET_SUB }; static PyObject * Adsr_setDiv(Adsr *self, PyObject *arg) { SET_DIV }; static PyObject * Adsr_play(Adsr *self, PyObject *args, PyObject *kwds) { self->fademode = 0; self->currentTime = 0.0; (*self->mode_func_ptr)(self); PLAY }; static PyObject * Adsr_stop(Adsr *self) { if (self->duration == 0.0) { self->fademode = 1; self->currentTime = 0.0; } else Adsr_internal_stop((Adsr *)self); Py_INCREF(Py_None); return Py_None; } static PyObject * Adsr_multiply(Adsr *self, PyObject *arg) { MULTIPLY }; static PyObject * Adsr_inplace_multiply(Adsr *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Adsr_add(Adsr *self, PyObject *arg) { ADD }; static PyObject * Adsr_inplace_add(Adsr *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Adsr_sub(Adsr *self, PyObject *arg) { SUB }; static PyObject * Adsr_inplace_sub(Adsr *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Adsr_div(Adsr *self, PyObject *arg) { DIV }; static PyObject * Adsr_inplace_div(Adsr *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Adsr_setAttack(Adsr *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->attack = PyFloat_AsDouble(arg); if (self->attack < 0.000001) self->attack = 0.000001; } Py_INCREF(Py_None); return Py_None; } static PyObject * Adsr_setDecay(Adsr *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->decay = PyFloat_AsDouble(arg); if (self->decay < 0.000001) self->decay = 0.000001; } Py_INCREF(Py_None); return Py_None; } static PyObject * Adsr_setSustain(Adsr *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->sustain = PyFloat_AsDouble(arg); if (self->sustain < 0.0) self->sustain = 0.0; else if (self->sustain > 1.0) self->sustain = 1.0; } Py_INCREF(Py_None); return Py_None; } static PyObject * Adsr_setRelease(Adsr *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->release = PyFloat_AsDouble(arg); if (self->release < 0.000001) self->release = 0.000001; } Py_INCREF(Py_None); return Py_None; } static PyObject * Adsr_setDur(Adsr *self, PyObject *arg) { if (PyNumber_Check(arg)) self->duration = PyFloat_AsDouble(arg); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Adsr_members[] = { {"server", T_OBJECT_EX, offsetof(Adsr, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Adsr, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Adsr, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Adsr, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Adsr_methods[] = { {"getServer", (PyCFunction)Adsr_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Adsr_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Adsr_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Adsr_stop, METH_NOARGS, "Starts fadeout and stops computing."}, {"setMul", (PyCFunction)Adsr_setMul, METH_O, "Sets Adsr mul factor."}, {"setAdd", (PyCFunction)Adsr_setAdd, METH_O, "Sets Adsr add factor."}, {"setSub", (PyCFunction)Adsr_setSub, METH_O, "Sets inverse add factor."}, {"setAttack", (PyCFunction)Adsr_setAttack, METH_O, "Sets attack time in seconds."}, {"setDecay", (PyCFunction)Adsr_setDecay, METH_O, "Sets attack time in seconds."}, {"setSustain", (PyCFunction)Adsr_setSustain, METH_O, "Sets attack time in seconds."}, {"setRelease", (PyCFunction)Adsr_setRelease, METH_O, "Sets release time in seconds."}, {"setDur", (PyCFunction)Adsr_setDur, METH_O, "Sets duration in seconds (0 means wait for stop method to start fadeout)."}, {"setDiv", (PyCFunction)Adsr_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Adsr_as_number = { (binaryfunc)Adsr_add, /*nb_add*/ (binaryfunc)Adsr_sub, /*nb_subtract*/ (binaryfunc)Adsr_multiply, /*nb_multiply*/ (binaryfunc)Adsr_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Adsr_inplace_add, /*inplace_add*/ (binaryfunc)Adsr_inplace_sub, /*inplace_subtract*/ (binaryfunc)Adsr_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Adsr_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject AdsrType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Adsr_base", /*tp_name*/ sizeof(Adsr), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Adsr_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Adsr_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Adsr objects. Generates Adsr envelope signal.", /* tp_doc */ (traverseproc)Adsr_traverse, /* tp_traverse */ (inquiry)Adsr_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Adsr_methods, /* tp_methods */ Adsr_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Adsr_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *pointslist; int modebuffer[2]; double currentTime; double currentValue; MYFLT sampleToSec; double increment; MYFLT *targets; MYFLT *times; int which; int flag; int newlist; int loop; int listsize; int okToPause; } Linseg; static void Linseg_convert_pointslist(Linseg *self) { int i; PyObject *tup; self->listsize = PyList_Size(self->pointslist); self->targets = (MYFLT *)realloc(self->targets, self->listsize * sizeof(MYFLT)); self->times = (MYFLT *)realloc(self->times, self->listsize * sizeof(MYFLT)); for (i=0; ilistsize; i++) { tup = PyList_GET_ITEM(self->pointslist, i); self->times[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 0)); self->targets[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1)); } } static void Linseg_reinit(Linseg *self) { if (self->newlist == 1) { Linseg_convert_pointslist((Linseg *)self); self->newlist = 0; } self->currentTime = 0.0; self->currentValue = self->targets[0]; self->which = 0; self->flag = 1; self->okToPause = 1; } static void Linseg_generate(Linseg *self) { int i; for (i=0; ibufsize; i++) { if (self->flag == 1) { if (self->currentTime >= self->times[self->which]) { self->which++; if (self->which == self->listsize) { if (self->loop == 1) Linseg_reinit((Linseg *)self); else { self->flag = 0; self->okToPause = 0; self->currentValue = self->targets[self->which-1]; } } else { if ((self->times[self->which] - self->times[self->which-1]) <= 0) self->increment = self->targets[self->which] - self->currentValue; else self->increment = (self->targets[self->which] - self->targets[self->which-1]) / ((self->times[self->which] - self->times[self->which-1]) / self->sampleToSec); } } if (self->currentTime <= self->times[self->listsize-1]) self->currentValue += self->increment; self->data[i] = (MYFLT)self->currentValue; self->currentTime += self->sampleToSec; } else self->data[i] = (MYFLT)self->currentValue; } } static void Linseg_postprocessing_ii(Linseg *self) { POST_PROCESSING_II }; static void Linseg_postprocessing_ai(Linseg *self) { POST_PROCESSING_AI }; static void Linseg_postprocessing_ia(Linseg *self) { POST_PROCESSING_IA }; static void Linseg_postprocessing_aa(Linseg *self) { POST_PROCESSING_AA }; static void Linseg_postprocessing_ireva(Linseg *self) { POST_PROCESSING_IREVA }; static void Linseg_postprocessing_areva(Linseg *self) { POST_PROCESSING_AREVA }; static void Linseg_postprocessing_revai(Linseg *self) { POST_PROCESSING_REVAI }; static void Linseg_postprocessing_revaa(Linseg *self) { POST_PROCESSING_REVAA }; static void Linseg_postprocessing_revareva(Linseg *self) { POST_PROCESSING_REVAREVA }; static void Linseg_setProcMode(Linseg *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Linseg_generate; switch (muladdmode) { case 0: self->muladd_func_ptr = Linseg_postprocessing_ii; break; case 1: self->muladd_func_ptr = Linseg_postprocessing_ai; break; case 2: self->muladd_func_ptr = Linseg_postprocessing_revai; break; case 10: self->muladd_func_ptr = Linseg_postprocessing_ia; break; case 11: self->muladd_func_ptr = Linseg_postprocessing_aa; break; case 12: self->muladd_func_ptr = Linseg_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Linseg_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Linseg_postprocessing_areva; break; case 22: self->muladd_func_ptr = Linseg_postprocessing_revareva; break; } } static void Linseg_compute_next_data_frame(Linseg *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Linseg_traverse(Linseg *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->pointslist); return 0; } static int Linseg_clear(Linseg *self) { pyo_CLEAR Py_CLEAR(self->pointslist); return 0; } static void Linseg_dealloc(Linseg* self) { pyo_DEALLOC free(self->targets); free(self->times); Linseg_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Linseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, initToFirstVal = 0; PyObject *pointslist=NULL, *multmp=NULL, *addtmp=NULL; Linseg *self; self = (Linseg *)type->tp_alloc(type, 0); self->loop = 0; self->newlist = 1; self->okToPause = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Linseg_compute_next_data_frame); self->mode_func_ptr = Linseg_setProcMode; Stream_setStreamActive(self->stream, 0); self->sampleToSec = 1. / self->sr; static char *kwlist[] = {"list", "loop", "initToFirstVal", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iiOO", kwlist, &pointslist, &self->loop, &initToFirstVal, &multmp, &addtmp)) Py_RETURN_NONE; Py_INCREF(pointslist); Py_XDECREF(self->pointslist); self->pointslist = pointslist; Linseg_convert_pointslist((Linseg *)self); if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (initToFirstVal) { for (i=0; ibufsize; i++) { self->data[i] = self->targets[0]; } } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Linseg_getServer(Linseg* self) { GET_SERVER }; static PyObject * Linseg_getStream(Linseg* self) { GET_STREAM }; static PyObject * Linseg_setMul(Linseg *self, PyObject *arg) { SET_MUL }; static PyObject * Linseg_setAdd(Linseg *self, PyObject *arg) { SET_ADD }; static PyObject * Linseg_setSub(Linseg *self, PyObject *arg) { SET_SUB }; static PyObject * Linseg_setDiv(Linseg *self, PyObject *arg) { SET_DIV }; static PyObject * Linseg_play(Linseg *self, PyObject *args, PyObject *kwds) { Linseg_reinit((Linseg *)self); PLAY }; static PyObject * Linseg_stop(Linseg *self) { self->okToPause = 0; STOP }; static PyObject * Linseg_pause(Linseg *self) { if (self->okToPause == 1) self->flag = 1 - self->flag; Py_INCREF(Py_None); return Py_None; }; static PyObject * Linseg_multiply(Linseg *self, PyObject *arg) { MULTIPLY }; static PyObject * Linseg_inplace_multiply(Linseg *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Linseg_add(Linseg *self, PyObject *arg) { ADD }; static PyObject * Linseg_inplace_add(Linseg *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Linseg_sub(Linseg *self, PyObject *arg) { SUB }; static PyObject * Linseg_inplace_sub(Linseg *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Linseg_div(Linseg *self, PyObject *arg) { DIV }; static PyObject * Linseg_inplace_div(Linseg *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Linseg_setList(Linseg *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute."); return PyInt_FromLong(-1); } if (! PyList_Check(value)) { PyErr_SetString(PyExc_TypeError, "The points list attribute value must be a list of tuples."); return PyInt_FromLong(-1); } Py_INCREF(value); Py_DECREF(self->pointslist); self->pointslist = value; self->newlist = 1; Py_INCREF(Py_None); return Py_None; } static PyObject * Linseg_setLoop(Linseg *self, PyObject *arg) { ASSERT_ARG_NOT_NULL self->loop = PyInt_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Linseg_members[] = { {"server", T_OBJECT_EX, offsetof(Linseg, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Linseg, stream), 0, "Stream object."}, {"pointslist", T_OBJECT_EX, offsetof(Linseg, pointslist), 0, "List of target points."}, {"mul", T_OBJECT_EX, offsetof(Linseg, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Linseg, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Linseg_methods[] = { {"getServer", (PyCFunction)Linseg_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Linseg_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Linseg_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Linseg_stop, METH_NOARGS, "Starts fadeout and stops computing."}, {"pause", (PyCFunction)Linseg_pause, METH_NOARGS, "Toggles between play and stop without reset."}, {"setList", (PyCFunction)Linseg_setList, METH_O, "Sets target points list."}, {"setLoop", (PyCFunction)Linseg_setLoop, METH_O, "Sets looping mode."}, {"setMul", (PyCFunction)Linseg_setMul, METH_O, "Sets Linseg mul factor."}, {"setAdd", (PyCFunction)Linseg_setAdd, METH_O, "Sets Linseg add factor."}, {"setSub", (PyCFunction)Linseg_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Linseg_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Linseg_as_number = { (binaryfunc)Linseg_add, /*nb_add*/ (binaryfunc)Linseg_sub, /*nb_subtract*/ (binaryfunc)Linseg_multiply, /*nb_multiply*/ (binaryfunc)Linseg_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Linseg_inplace_add, /*inplace_add*/ (binaryfunc)Linseg_inplace_sub, /*inplace_subtract*/ (binaryfunc)Linseg_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Linseg_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject LinsegType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Linseg_base", /*tp_name*/ sizeof(Linseg), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Linseg_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Linseg_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Linseg objects. Generates a linear segments break-points line.", /* tp_doc */ (traverseproc)Linseg_traverse, /* tp_traverse */ (inquiry)Linseg_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Linseg_methods, /* tp_methods */ Linseg_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Linseg_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *pointslist; int modebuffer[2]; double currentTime; double currentValue; MYFLT sampleToSec; double inc; double pointer; MYFLT range; double steps; MYFLT *targets; MYFLT *times; int which; int flag; int newlist; int loop; int listsize; double exp; double exp_tmp; int inverse; int inverse_tmp; int okToPause; } Expseg; static void Expseg_convert_pointslist(Expseg *self) { int i; PyObject *tup; self->listsize = PyList_Size(self->pointslist); self->targets = (MYFLT *)realloc(self->targets, self->listsize * sizeof(MYFLT)); self->times = (MYFLT *)realloc(self->times, self->listsize * sizeof(MYFLT)); for (i=0; ilistsize; i++) { tup = PyList_GET_ITEM(self->pointslist, i); self->times[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 0)); self->targets[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1)); } } static void Expseg_reinit(Expseg *self) { if (self->newlist == 1) { Expseg_convert_pointslist((Expseg *)self); self->newlist = 0; } self->currentTime = 0.0; self->currentValue = self->targets[0]; self->which = 0; self->flag = 1; self->exp = self->exp_tmp; self->inverse = self->inverse_tmp; self->okToPause = 1; } static void Expseg_generate(Expseg *self) { int i; double scl; for (i=0; ibufsize; i++) { if (self->flag == 1) { if (self->currentTime >= self->times[self->which]) { self->which++; if (self->which == self->listsize) { if (self->loop == 1) Expseg_reinit((Expseg *)self); else { self->flag = 0; self->currentValue = self->targets[self->which-1]; self->okToPause = 0; } } else { self->range = self->targets[self->which] - self->targets[self->which-1]; self->steps = (self->times[self->which] - self->times[self->which-1]) * self->sr; if (self->steps <= 0) self->inc = 1.0; else self->inc = 1.0 / self->steps; } self->pointer = 0.0; } if (self->currentTime <= self->times[self->listsize-1]) { if (self->pointer >= 1.0) self->pointer = 1.0; if (self->inverse == 1 && self->range < 0.0) scl = 1.0 - pow(1.0 - self->pointer, self->exp); else scl = pow(self->pointer, self->exp); self->currentValue = scl * self->range + self->targets[self->which-1]; self->pointer += self->inc; } self->data[i] = (MYFLT)self->currentValue; self->currentTime += self->sampleToSec; } else self->data[i] = (MYFLT)self->currentValue; } } static void Expseg_postprocessing_ii(Expseg *self) { POST_PROCESSING_II }; static void Expseg_postprocessing_ai(Expseg *self) { POST_PROCESSING_AI }; static void Expseg_postprocessing_ia(Expseg *self) { POST_PROCESSING_IA }; static void Expseg_postprocessing_aa(Expseg *self) { POST_PROCESSING_AA }; static void Expseg_postprocessing_ireva(Expseg *self) { POST_PROCESSING_IREVA }; static void Expseg_postprocessing_areva(Expseg *self) { POST_PROCESSING_AREVA }; static void Expseg_postprocessing_revai(Expseg *self) { POST_PROCESSING_REVAI }; static void Expseg_postprocessing_revaa(Expseg *self) { POST_PROCESSING_REVAA }; static void Expseg_postprocessing_revareva(Expseg *self) { POST_PROCESSING_REVAREVA }; static void Expseg_setProcMode(Expseg *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Expseg_generate; switch (muladdmode) { case 0: self->muladd_func_ptr = Expseg_postprocessing_ii; break; case 1: self->muladd_func_ptr = Expseg_postprocessing_ai; break; case 2: self->muladd_func_ptr = Expseg_postprocessing_revai; break; case 10: self->muladd_func_ptr = Expseg_postprocessing_ia; break; case 11: self->muladd_func_ptr = Expseg_postprocessing_aa; break; case 12: self->muladd_func_ptr = Expseg_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Expseg_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Expseg_postprocessing_areva; break; case 22: self->muladd_func_ptr = Expseg_postprocessing_revareva; break; } } static void Expseg_compute_next_data_frame(Expseg *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Expseg_traverse(Expseg *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->pointslist); return 0; } static int Expseg_clear(Expseg *self) { pyo_CLEAR Py_CLEAR(self->pointslist); return 0; } static void Expseg_dealloc(Expseg* self) { pyo_DEALLOC free(self->targets); free(self->times); Expseg_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Expseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, initToFirstVal = 0; PyObject *pointslist=NULL, *multmp=NULL, *addtmp=NULL; Expseg *self; self = (Expseg *)type->tp_alloc(type, 0); self->loop = 0; self->newlist = 1; self->exp = self->exp_tmp = 10; self->inverse = self->inverse_tmp = 1; self->okToPause = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Expseg_compute_next_data_frame); self->mode_func_ptr = Expseg_setProcMode; Stream_setStreamActive(self->stream, 0); self->sampleToSec = 1. / self->sr; static char *kwlist[] = {"list", "loop", "exp", "inverse", "initToFirstVal", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|idiiOO", kwlist, &pointslist, &self->loop, &self->exp_tmp, &self->inverse_tmp, &initToFirstVal, &multmp, &addtmp)) Py_RETURN_NONE; Py_INCREF(pointslist); Py_XDECREF(self->pointslist); self->pointslist = pointslist; Expseg_convert_pointslist((Expseg *)self); if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (initToFirstVal) { for (i=0; ibufsize; i++) { self->data[i] = self->targets[0]; } } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Expseg_getServer(Expseg* self) { GET_SERVER }; static PyObject * Expseg_getStream(Expseg* self) { GET_STREAM }; static PyObject * Expseg_setMul(Expseg *self, PyObject *arg) { SET_MUL }; static PyObject * Expseg_setAdd(Expseg *self, PyObject *arg) { SET_ADD }; static PyObject * Expseg_setSub(Expseg *self, PyObject *arg) { SET_SUB }; static PyObject * Expseg_setDiv(Expseg *self, PyObject *arg) { SET_DIV }; static PyObject * Expseg_play(Expseg *self, PyObject *args, PyObject *kwds) { Expseg_reinit((Expseg *)self); PLAY }; static PyObject * Expseg_stop(Expseg *self) { self->okToPause = 0; STOP }; static PyObject * Expseg_pause(Expseg *self) { if (self->okToPause == 1) self->flag = 1 - self->flag; Py_INCREF(Py_None); return Py_None; }; static PyObject * Expseg_multiply(Expseg *self, PyObject *arg) { MULTIPLY }; static PyObject * Expseg_inplace_multiply(Expseg *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Expseg_add(Expseg *self, PyObject *arg) { ADD }; static PyObject * Expseg_inplace_add(Expseg *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Expseg_sub(Expseg *self, PyObject *arg) { SUB }; static PyObject * Expseg_inplace_sub(Expseg *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Expseg_div(Expseg *self, PyObject *arg) { DIV }; static PyObject * Expseg_inplace_div(Expseg *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Expseg_setList(Expseg *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute."); return PyInt_FromLong(-1); } if (! PyList_Check(value)) { PyErr_SetString(PyExc_TypeError, "The points list attribute value must be a list of tuples."); return PyInt_FromLong(-1); } Py_INCREF(value); Py_DECREF(self->pointslist); self->pointslist = value; self->newlist = 1; Py_INCREF(Py_None); return Py_None; } static PyObject * Expseg_setLoop(Expseg *self, PyObject *arg) { ASSERT_ARG_NOT_NULL self->loop = PyInt_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * Expseg_setExp(Expseg *self, PyObject *arg) { ASSERT_ARG_NOT_NULL if (PyNumber_Check(arg)) self->exp_tmp = PyFloat_AsDouble(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * Expseg_setInverse(Expseg *self, PyObject *arg) { ASSERT_ARG_NOT_NULL if (PyNumber_Check(arg)) self->inverse_tmp = PyInt_AsLong(PyNumber_Int(arg)); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Expseg_members[] = { {"server", T_OBJECT_EX, offsetof(Expseg, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Expseg, stream), 0, "Stream object."}, {"pointslist", T_OBJECT_EX, offsetof(Expseg, pointslist), 0, "List of target points."}, {"mul", T_OBJECT_EX, offsetof(Expseg, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Expseg, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Expseg_methods[] = { {"getServer", (PyCFunction)Expseg_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Expseg_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Expseg_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Expseg_stop, METH_NOARGS, "Starts fadeout and stops computing."}, {"pause", (PyCFunction)Expseg_pause, METH_NOARGS, "Toggles between play and stop without reset."}, {"setList", (PyCFunction)Expseg_setList, METH_O, "Sets target points list."}, {"setLoop", (PyCFunction)Expseg_setLoop, METH_O, "Sets looping mode."}, {"setExp", (PyCFunction)Expseg_setExp, METH_O, "Sets exponent factor."}, {"setInverse", (PyCFunction)Expseg_setInverse, METH_O, "Sets inverse factor."}, {"setMul", (PyCFunction)Expseg_setMul, METH_O, "Sets Expseg mul factor."}, {"setAdd", (PyCFunction)Expseg_setAdd, METH_O, "Sets Expseg add factor."}, {"setSub", (PyCFunction)Expseg_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Expseg_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Expseg_as_number = { (binaryfunc)Expseg_add, /*nb_add*/ (binaryfunc)Expseg_sub, /*nb_subtract*/ (binaryfunc)Expseg_multiply, /*nb_multiply*/ (binaryfunc)Expseg_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Expseg_inplace_add, /*inplace_add*/ (binaryfunc)Expseg_inplace_sub, /*inplace_subtract*/ (binaryfunc)Expseg_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Expseg_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ExpsegType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Expseg_base", /*tp_name*/ sizeof(Expseg), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Expseg_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Expseg_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Expseg objects. Generates a linear segments break-points line.", /* tp_doc */ (traverseproc)Expseg_traverse, /* tp_traverse */ (inquiry)Expseg_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Expseg_methods, /* tp_methods */ Expseg_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Expseg_new, /* tp_new */ };pyo/src/objects/metromodule.c0000644000175000017500000063717012652732202015614 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" /****************/ /**** Metro *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *time; Stream *time_stream; int modebuffer[3]; double sampleToSec; double currentTime; double offset; int flag; } Metro; static void Metro_generate_i(Metro *self) { MYFLT val; double tm, off; int i; tm = PyFloat_AS_DOUBLE(self->time); off = tm * self->offset; for (i=0; ibufsize; i++) { if (self->currentTime >= tm) { val = 0; self->currentTime -= tm; self->flag = 1; } else if (self->currentTime >= off && self->flag == 1) { val = 1; self->flag = 0; } else val = 0; self->data[i] = val; self->currentTime += self->sampleToSec; } } static void Metro_generate_a(Metro *self) { MYFLT val; double off, tmd; int i; MYFLT *tm = Stream_getData((Stream *)self->time_stream); for (i=0; ibufsize; i++) { tmd = (double)tm[i]; off = tmd * self->offset; if (self->currentTime >= tmd) { val = 0; self->currentTime -= tmd; self->flag = 1; } else if (self->currentTime >= off && self->flag == 1) { val = 1; self->flag = 0; } else val = 0; self->data[i] = val; self->currentTime += self->sampleToSec; } } static void Metro_postprocessing_ii(Metro *self) { POST_PROCESSING_II }; static void Metro_postprocessing_ai(Metro *self) { POST_PROCESSING_AI }; static void Metro_postprocessing_ia(Metro *self) { POST_PROCESSING_IA }; static void Metro_postprocessing_aa(Metro *self) { POST_PROCESSING_AA }; static void Metro_postprocessing_ireva(Metro *self) { POST_PROCESSING_IREVA }; static void Metro_postprocessing_areva(Metro *self) { POST_PROCESSING_AREVA }; static void Metro_postprocessing_revai(Metro *self) { POST_PROCESSING_REVAI }; static void Metro_postprocessing_revaa(Metro *self) { POST_PROCESSING_REVAA }; static void Metro_postprocessing_revareva(Metro *self) { POST_PROCESSING_REVAREVA }; static void Metro_setProcMode(Metro *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Metro_generate_i; break; case 1: self->proc_func_ptr = Metro_generate_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Metro_postprocessing_ii; break; case 1: self->muladd_func_ptr = Metro_postprocessing_ai; break; case 2: self->muladd_func_ptr = Metro_postprocessing_revai; break; case 10: self->muladd_func_ptr = Metro_postprocessing_ia; break; case 11: self->muladd_func_ptr = Metro_postprocessing_aa; break; case 12: self->muladd_func_ptr = Metro_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Metro_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Metro_postprocessing_areva; break; case 22: self->muladd_func_ptr = Metro_postprocessing_revareva; break; } } static void Metro_compute_next_data_frame(Metro *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Metro_traverse(Metro *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->time); Py_VISIT(self->time_stream); return 0; } static int Metro_clear(Metro *self) { pyo_CLEAR Py_CLEAR(self->time); Py_CLEAR(self->time_stream); return 0; } static void Metro_dealloc(Metro* self) { pyo_DEALLOC Metro_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Metro_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *timetmp=NULL; Metro *self; self = (Metro *)type->tp_alloc(type, 0); self->time = PyFloat_FromDouble(1.); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->flag = 1; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Metro_compute_next_data_frame); self->mode_func_ptr = Metro_setProcMode; Stream_setStreamActive(self->stream, 0); self->sampleToSec = 1.0 / self->sr; self->currentTime = 0.; static char *kwlist[] = {"time", "offset", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Od", kwlist, &timetmp, &self->offset)) Py_RETURN_NONE; if (timetmp) { PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Metro_getServer(Metro* self) { GET_SERVER }; static PyObject * Metro_getStream(Metro* self) { GET_STREAM }; static PyObject * Metro_setMul(Metro *self, PyObject *arg) { SET_MUL }; static PyObject * Metro_setAdd(Metro *self, PyObject *arg) { SET_ADD }; static PyObject * Metro_setSub(Metro *self, PyObject *arg) { SET_SUB }; static PyObject * Metro_setDiv(Metro *self, PyObject *arg) { SET_DIV }; static PyObject * Metro_play(Metro *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Metro_stop(Metro *self) { STOP }; static PyObject * Metro_multiply(Metro *self, PyObject *arg) { MULTIPLY }; static PyObject * Metro_inplace_multiply(Metro *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Metro_add(Metro *self, PyObject *arg) { ADD }; static PyObject * Metro_inplace_add(Metro *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Metro_sub(Metro *self, PyObject *arg) { SUB }; static PyObject * Metro_inplace_sub(Metro *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Metro_div(Metro *self, PyObject *arg) { DIV }; static PyObject * Metro_inplace_div(Metro *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Metro_setTime(Metro *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->time); if (isNumber == 1) { self->time = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->time = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->time, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->time_stream); self->time_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Metro_members[] = { {"server", T_OBJECT_EX, offsetof(Metro, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Metro, stream), 0, "Stream object."}, {"time", T_OBJECT_EX, offsetof(Metro, time), 0, "Metro time factor."}, {"mul", T_OBJECT_EX, offsetof(Metro, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Metro, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Metro_methods[] = { {"getServer", (PyCFunction)Metro_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Metro_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Metro_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Metro_stop, METH_NOARGS, "Stops computing."}, {"setTime", (PyCFunction)Metro_setTime, METH_O, "Sets time factor."}, {"setMul", (PyCFunction)Metro_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Metro_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Metro_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Metro_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Metro_as_number = { (binaryfunc)Metro_add, /*nb_add*/ (binaryfunc)Metro_sub, /*nb_subtract*/ (binaryfunc)Metro_multiply, /*nb_multiply*/ (binaryfunc)Metro_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Metro_inplace_add, /*inplace_add*/ (binaryfunc)Metro_inplace_sub, /*inplace_subtract*/ (binaryfunc)Metro_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Metro_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject MetroType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Metro_base", /*tp_name*/ sizeof(Metro), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Metro_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Metro_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Metro objects. Create a metronome.", /* tp_doc */ (traverseproc)Metro_traverse, /* tp_traverse */ (inquiry)Metro_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Metro_methods, /* tp_methods */ Metro_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Metro_new, /* tp_new */ }; /****************/ /**** Seqer *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *time; Stream *time_stream; PyObject *tmp; int modebuffer[1]; double sampleToSec; double currentTime; double duration; int *seq; int count; MYFLT *buffer_streams; int seqsize; int poly; int flag; int tap; int voiceCount; int newseq; } Seqer; static void Seqer_reset(Seqer *self) { int i; self->seqsize = PyList_Size(self->tmp); self->seq = (int *)realloc(self->seq, self->seqsize * sizeof(int)); for (i=0; iseqsize; i++) { self->seq[i] = PyInt_AS_LONG(PyNumber_Int(PyList_GET_ITEM(self->tmp, i))); } self->newseq = 0; } static void Seqer_generate_i(Seqer *self) { double tm; int i; tm = PyFloat_AS_DOUBLE(self->time); if (self->currentTime == -1.0) { self->currentTime = tm; } for (i=0; i<(self->poly*self->bufsize); i++) { self->buffer_streams[i] = 0.0; } for (i=0; ibufsize; i++) { self->currentTime += self->sampleToSec; if (self->currentTime >= tm) { self->currentTime -= tm; self->count++; if (self->count >= self->seq[self->tap]) { self->count = 0; self->buffer_streams[i + self->voiceCount * self->bufsize] = 1.0; self->voiceCount++; if (self->voiceCount >= self->poly) self->voiceCount = 0; self->tap++; if (self->tap >= self->seqsize) { self->tap = 0; if (self->newseq == 1) Seqer_reset(self); } } } } } static void Seqer_generate_a(Seqer *self) { double tm; int i; MYFLT *time = Stream_getData((Stream *)self->time_stream); if (self->currentTime == -1.0) { self->currentTime = time[0]; } for (i=0; i<(self->poly*self->bufsize); i++) { self->buffer_streams[i] = 0.0; } for (i=0; ibufsize; i++) { tm = (double)time[i]; self->currentTime += self->sampleToSec; if (self->currentTime >= tm) { self->currentTime -= tm; self->count++; if (self->count >= self->seq[self->tap]) { self->count = 0; self->buffer_streams[i + self->voiceCount * self->bufsize] = 1.0; self->voiceCount++; if (self->voiceCount >= self->poly) self->voiceCount = 0; self->tap++; if (self->tap >= self->seqsize) { self->tap = 0; if (self->newseq == 1) Seqer_reset(self); } } } } } MYFLT * Seqer_getSamplesBuffer(Seqer *self) { return (MYFLT *)self->buffer_streams; } static void Seqer_setProcMode(Seqer *self) { int procmode = self->modebuffer[0]; switch (procmode) { case 0: self->proc_func_ptr = Seqer_generate_i; break; case 1: self->proc_func_ptr = Seqer_generate_a; break; } } static void Seqer_compute_next_data_frame(Seqer *self) { (*self->proc_func_ptr)(self); } static int Seqer_traverse(Seqer *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->time); Py_VISIT(self->time_stream); Py_VISIT(self->tmp); return 0; } static int Seqer_clear(Seqer *self) { pyo_CLEAR Py_CLEAR(self->time); Py_CLEAR(self->time_stream); Py_CLEAR(self->tmp); return 0; } static void Seqer_dealloc(Seqer* self) { pyo_DEALLOC free(self->buffer_streams); Seqer_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Seqer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *timetmp=NULL, *seqtmp=NULL; Seqer *self; self = (Seqer *)type->tp_alloc(type, 0); self->time = PyFloat_FromDouble(1.); self->flag = 1; self->poly = 1; self->seqsize = 1; self->seq = (int *)realloc(self->seq, self->seqsize * sizeof(int)); self->seq[0] = 1; self->newseq = 0; self->duration = -1.0; self->tap = 0; self->count = 0; self->voiceCount = 0; self->modebuffer[0] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Seqer_compute_next_data_frame); self->mode_func_ptr = Seqer_setProcMode; Stream_setStreamActive(self->stream, 0); self->sampleToSec = 1.0 / self->sr; self->currentTime = -1.0; static char *kwlist[] = {"time", "seq", "poly", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist, &timetmp, &seqtmp, &self->poly)) Py_RETURN_NONE; if (timetmp) { PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp); } if (seqtmp) { PyObject_CallMethod((PyObject *)self, "setSeq", "O", seqtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->poly * self->bufsize * sizeof(MYFLT)); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Seqer_getServer(Seqer* self) { GET_SERVER }; static PyObject * Seqer_getStream(Seqer* self) { GET_STREAM }; static PyObject * Seqer_play(Seqer *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Seqer_stop(Seqer *self) { STOP }; static PyObject * Seqer_setTime(Seqer *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->time); if (isNumber == 1) { self->time = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->time = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->time, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->time_stream); self->time_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Seqer_setSeq(Seqer *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL int isList = PyList_Check(arg); if (isList == 1) { tmp = arg; Py_INCREF(tmp); Py_XDECREF(self->tmp); self->tmp = tmp; self->newseq = 1; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Seqer_members[] = { {"server", T_OBJECT_EX, offsetof(Seqer, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Seqer, stream), 0, "Stream object."}, {"time", T_OBJECT_EX, offsetof(Seqer, time), 0, "Seqer time factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Seqer_methods[] = { {"getServer", (PyCFunction)Seqer_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Seqer_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Seqer_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Seqer_stop, METH_NOARGS, "Stops computing."}, {"setTime", (PyCFunction)Seqer_setTime, METH_O, "Sets time factor."}, {"setSeq", (PyCFunction)Seqer_setSeq, METH_O, "Sets duration sequence."}, {NULL} /* Sentinel */ }; PyTypeObject SeqerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Seqer_base", /*tp_name*/ sizeof(Seqer), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Seqer_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Seqer objects. Creates a metronome with a duration sequence.", /* tp_doc */ (traverseproc)Seqer_traverse, /* tp_traverse */ (inquiry)Seqer_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Seqer_methods, /* tp_methods */ Seqer_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Seqer_new, /* tp_new */ }; /************************************************************************************************/ /* Seq streamer object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD Seqer *mainPlayer; int chnl; int modebuffer[2]; } Seq; static void Seq_postprocessing_ii(Seq *self) { POST_PROCESSING_II }; static void Seq_postprocessing_ai(Seq *self) { POST_PROCESSING_AI }; static void Seq_postprocessing_ia(Seq *self) { POST_PROCESSING_IA }; static void Seq_postprocessing_aa(Seq *self) { POST_PROCESSING_AA }; static void Seq_postprocessing_ireva(Seq *self) { POST_PROCESSING_IREVA }; static void Seq_postprocessing_areva(Seq *self) { POST_PROCESSING_AREVA }; static void Seq_postprocessing_revai(Seq *self) { POST_PROCESSING_REVAI }; static void Seq_postprocessing_revaa(Seq *self) { POST_PROCESSING_REVAA }; static void Seq_postprocessing_revareva(Seq *self) { POST_PROCESSING_REVAREVA }; static void Seq_setProcMode(Seq *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Seq_postprocessing_ii; break; case 1: self->muladd_func_ptr = Seq_postprocessing_ai; break; case 2: self->muladd_func_ptr = Seq_postprocessing_revai; break; case 10: self->muladd_func_ptr = Seq_postprocessing_ia; break; case 11: self->muladd_func_ptr = Seq_postprocessing_aa; break; case 12: self->muladd_func_ptr = Seq_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Seq_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Seq_postprocessing_areva; break; case 22: self->muladd_func_ptr = Seq_postprocessing_revareva; break; } } static void Seq_compute_next_data_frame(Seq *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = Seqer_getSamplesBuffer((Seqer *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int Seq_traverse(Seq *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int Seq_clear(Seq *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void Seq_dealloc(Seq* self) { pyo_DEALLOC Seq_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Seq_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; Seq *self; self = (Seq *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Seq_compute_next_data_frame); self->mode_func_ptr = Seq_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (Seqer *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Seq_getServer(Seq* self) { GET_SERVER }; static PyObject * Seq_getStream(Seq* self) { GET_STREAM }; static PyObject * Seq_setMul(Seq *self, PyObject *arg) { SET_MUL }; static PyObject * Seq_setAdd(Seq *self, PyObject *arg) { SET_ADD }; static PyObject * Seq_setSub(Seq *self, PyObject *arg) { SET_SUB }; static PyObject * Seq_setDiv(Seq *self, PyObject *arg) { SET_DIV }; static PyObject * Seq_play(Seq *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Seq_out(Seq *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Seq_stop(Seq *self) { STOP }; static PyObject * Seq_multiply(Seq *self, PyObject *arg) { MULTIPLY }; static PyObject * Seq_inplace_multiply(Seq *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Seq_add(Seq *self, PyObject *arg) { ADD }; static PyObject * Seq_inplace_add(Seq *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Seq_sub(Seq *self, PyObject *arg) { SUB }; static PyObject * Seq_inplace_sub(Seq *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Seq_div(Seq *self, PyObject *arg) { DIV }; static PyObject * Seq_inplace_div(Seq *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Seq_members[] = { {"server", T_OBJECT_EX, offsetof(Seq, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Seq, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Seq, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Seq, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Seq_methods[] = { {"getServer", (PyCFunction)Seq_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Seq_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Seq_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Seq_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Seq_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Seq_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Seq_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Seq_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Seq_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Seq_as_number = { (binaryfunc)Seq_add, /*nb_add*/ (binaryfunc)Seq_sub, /*nb_subtract*/ (binaryfunc)Seq_multiply, /*nb_multiply*/ (binaryfunc)Seq_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Seq_inplace_add, /*inplace_add*/ (binaryfunc)Seq_inplace_sub, /*inplace_subtract*/ (binaryfunc)Seq_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Seq_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SeqType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Seq_base", /*tp_name*/ sizeof(Seq), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Seq_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Seq_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Seq objects. Reads a channel from a Seqer.", /* tp_doc */ (traverseproc)Seq_traverse, /* tp_traverse */ (inquiry)Seq_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Seq_methods, /* tp_methods */ Seq_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Seq_new, /* tp_new */ }; /****************/ /**** Clouder *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *density; Stream *density_stream; int modebuffer[1]; int poly; int voiceCount; MYFLT *buffer_streams; } Clouder; static void Clouder_generate_i(Clouder *self) { int i, rnd; MYFLT dens = PyFloat_AS_DOUBLE(self->density); if (dens <= 0.0) dens = 0.0; else if (dens > self->sr) dens = self->sr; for (i=0; i<(self->poly*self->bufsize); i++) { self->buffer_streams[i] = 0.0; } dens *= 0.5; for (i=0; ibufsize; i++) { rnd = (int)(rand() / (MYFLT)RAND_MAX * self->sr); if (rnd < dens) { self->buffer_streams[i + self->voiceCount++ * self->bufsize] = 1.0; if (self->voiceCount == self->poly) self->voiceCount = 0; } } } static void Clouder_generate_a(Clouder *self) { MYFLT dens; int i, rnd; MYFLT *density = Stream_getData((Stream *)self->density_stream); for (i=0; i<(self->poly*self->bufsize); i++) { self->buffer_streams[i] = 0.0; } for (i=0; ibufsize; i++) { dens = density[i]; if (dens <= 0.0) dens = 0.0; else if (dens > self->sr) dens = self->sr; dens *= 0.5; rnd = (int)(rand() / (MYFLT)RAND_MAX * self->sr); if (rnd < dens) { self->buffer_streams[i + self->voiceCount++ * self->bufsize] = 1.0; if (self->voiceCount == self->poly) self->voiceCount = 0; } } } MYFLT * Clouder_getSamplesBuffer(Clouder *self) { return (MYFLT *)self->buffer_streams; } static void Clouder_setProcMode(Clouder *self) { int procmode = self->modebuffer[0]; switch (procmode) { case 0: self->proc_func_ptr = Clouder_generate_i; break; case 1: self->proc_func_ptr = Clouder_generate_a; break; } } static void Clouder_compute_next_data_frame(Clouder *self) { (*self->proc_func_ptr)(self); } static int Clouder_traverse(Clouder *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->density); Py_VISIT(self->density_stream); return 0; } static int Clouder_clear(Clouder *self) { pyo_CLEAR Py_CLEAR(self->density); Py_CLEAR(self->density_stream); return 0; } static void Clouder_dealloc(Clouder* self) { pyo_DEALLOC free(self->buffer_streams); Clouder_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Clouder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *densitytmp=NULL; Clouder *self; self = (Clouder *)type->tp_alloc(type, 0); self->density = PyFloat_FromDouble(10.0); self->poly = 1; self->voiceCount = 0; self->modebuffer[0] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Clouder_compute_next_data_frame); self->mode_func_ptr = Clouder_setProcMode; Stream_setStreamActive(self->stream, 0); static char *kwlist[] = {"density", "poly", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &densitytmp, &self->poly)) Py_RETURN_NONE; if (densitytmp) { PyObject_CallMethod((PyObject *)self, "setDensity", "O", densitytmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); Server_generateSeed((Server *)self->server, CLOUD_ID); self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->poly * self->bufsize * sizeof(MYFLT)); return (PyObject *)self; } static PyObject * Clouder_getServer(Clouder* self) { GET_SERVER }; static PyObject * Clouder_getStream(Clouder* self) { GET_STREAM }; static PyObject * Clouder_play(Clouder *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Clouder_stop(Clouder *self) { STOP }; static PyObject * Clouder_setDensity(Clouder *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->density); if (isNumber == 1) { self->density = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->density = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->density, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->density_stream); self->density_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Clouder_members[] = { {"server", T_OBJECT_EX, offsetof(Clouder, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Clouder, stream), 0, "Stream object."}, {"density", T_OBJECT_EX, offsetof(Clouder, density), 0, "Clouder density factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Clouder_methods[] = { {"getServer", (PyCFunction)Clouder_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Clouder_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Clouder_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Clouder_stop, METH_NOARGS, "Stops computing."}, {"setDensity", (PyCFunction)Clouder_setDensity, METH_O, "Sets density factor."}, {NULL} /* Sentinel */ }; PyTypeObject ClouderType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Clouder_base", /*tp_name*/ sizeof(Clouder), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Clouder_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Clouder objects. Create a cloud of triggers.", /* tp_doc */ (traverseproc)Clouder_traverse, /* tp_traverse */ (inquiry)Clouder_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Clouder_methods, /* tp_methods */ Clouder_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Clouder_new, /* tp_new */ }; /************************************************************************************************/ /* Cloud streamer object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD Clouder *mainPlayer; int chnl; int modebuffer[2]; } Cloud; static void Cloud_postprocessing_ii(Cloud *self) { POST_PROCESSING_II }; static void Cloud_postprocessing_ai(Cloud *self) { POST_PROCESSING_AI }; static void Cloud_postprocessing_ia(Cloud *self) { POST_PROCESSING_IA }; static void Cloud_postprocessing_aa(Cloud *self) { POST_PROCESSING_AA }; static void Cloud_postprocessing_ireva(Cloud *self) { POST_PROCESSING_IREVA }; static void Cloud_postprocessing_areva(Cloud *self) { POST_PROCESSING_AREVA }; static void Cloud_postprocessing_revai(Cloud *self) { POST_PROCESSING_REVAI }; static void Cloud_postprocessing_revaa(Cloud *self) { POST_PROCESSING_REVAA }; static void Cloud_postprocessing_revareva(Cloud *self) { POST_PROCESSING_REVAREVA }; static void Cloud_setProcMode(Cloud *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Cloud_postprocessing_ii; break; case 1: self->muladd_func_ptr = Cloud_postprocessing_ai; break; case 2: self->muladd_func_ptr = Cloud_postprocessing_revai; break; case 10: self->muladd_func_ptr = Cloud_postprocessing_ia; break; case 11: self->muladd_func_ptr = Cloud_postprocessing_aa; break; case 12: self->muladd_func_ptr = Cloud_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Cloud_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Cloud_postprocessing_areva; break; case 22: self->muladd_func_ptr = Cloud_postprocessing_revareva; break; } } static void Cloud_compute_next_data_frame(Cloud *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = Clouder_getSamplesBuffer((Clouder *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int Cloud_traverse(Cloud *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int Cloud_clear(Cloud *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void Cloud_dealloc(Cloud* self) { pyo_DEALLOC Cloud_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Cloud_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; Cloud *self; self = (Cloud *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Cloud_compute_next_data_frame); self->mode_func_ptr = Cloud_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (Clouder *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Cloud_getServer(Cloud* self) { GET_SERVER }; static PyObject * Cloud_getStream(Cloud* self) { GET_STREAM }; static PyObject * Cloud_setMul(Cloud *self, PyObject *arg) { SET_MUL }; static PyObject * Cloud_setAdd(Cloud *self, PyObject *arg) { SET_ADD }; static PyObject * Cloud_setSub(Cloud *self, PyObject *arg) { SET_SUB }; static PyObject * Cloud_setDiv(Cloud *self, PyObject *arg) { SET_DIV }; static PyObject * Cloud_play(Cloud *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Cloud_out(Cloud *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Cloud_stop(Cloud *self) { STOP }; static PyObject * Cloud_multiply(Cloud *self, PyObject *arg) { MULTIPLY }; static PyObject * Cloud_inplace_multiply(Cloud *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Cloud_add(Cloud *self, PyObject *arg) { ADD }; static PyObject * Cloud_inplace_add(Cloud *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Cloud_sub(Cloud *self, PyObject *arg) { SUB }; static PyObject * Cloud_inplace_sub(Cloud *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Cloud_div(Cloud *self, PyObject *arg) { DIV }; static PyObject * Cloud_inplace_div(Cloud *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Cloud_members[] = { {"server", T_OBJECT_EX, offsetof(Cloud, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Cloud, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Cloud, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Cloud, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Cloud_methods[] = { {"getServer", (PyCFunction)Cloud_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Cloud_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Cloud_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Cloud_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Cloud_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Cloud_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Cloud_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Cloud_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Cloud_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Cloud_as_number = { (binaryfunc)Cloud_add, /*nb_add*/ (binaryfunc)Cloud_sub, /*nb_subtract*/ (binaryfunc)Cloud_multiply, /*nb_multiply*/ (binaryfunc)Cloud_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Cloud_inplace_add, /*inplace_add*/ (binaryfunc)Cloud_inplace_sub, /*inplace_subtract*/ (binaryfunc)Cloud_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Cloud_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject CloudType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Cloud_base", /*tp_name*/ sizeof(Cloud), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Cloud_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Cloud_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Cloud objects. Reads a channel from a Clouder.", /* tp_doc */ (traverseproc)Cloud_traverse, /* tp_traverse */ (inquiry)Cloud_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Cloud_methods, /* tp_methods */ Cloud_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Cloud_new, /* tp_new */ }; /****************/ /**** Trig *****/ /****************/ typedef struct { pyo_audio_HEAD int flag; int modebuffer[2]; } Trig; static void Trig_postprocessing_ii(Trig *self) { POST_PROCESSING_II }; static void Trig_postprocessing_ai(Trig *self) { POST_PROCESSING_AI }; static void Trig_postprocessing_ia(Trig *self) { POST_PROCESSING_IA }; static void Trig_postprocessing_aa(Trig *self) { POST_PROCESSING_AA }; static void Trig_postprocessing_ireva(Trig *self) { POST_PROCESSING_IREVA }; static void Trig_postprocessing_areva(Trig *self) { POST_PROCESSING_AREVA }; static void Trig_postprocessing_revai(Trig *self) { POST_PROCESSING_REVAI }; static void Trig_postprocessing_revaa(Trig *self) { POST_PROCESSING_REVAA }; static void Trig_postprocessing_revareva(Trig *self) { POST_PROCESSING_REVAREVA }; static void Trig_setProcMode(Trig *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Trig_postprocessing_ii; break; case 1: self->muladd_func_ptr = Trig_postprocessing_ai; break; case 2: self->muladd_func_ptr = Trig_postprocessing_revai; break; case 10: self->muladd_func_ptr = Trig_postprocessing_ia; break; case 11: self->muladd_func_ptr = Trig_postprocessing_aa; break; case 12: self->muladd_func_ptr = Trig_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Trig_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Trig_postprocessing_areva; break; case 22: self->muladd_func_ptr = Trig_postprocessing_revareva; break; } } static void Trig_compute_next_data_frame(Trig *self) { if (self->flag == 1) { self->data[0] = 1.0; self->flag = 0; } else self->data[0] = 0.0; (*self->muladd_func_ptr)(self); } static int Trig_traverse(Trig *self, visitproc visit, void *arg) { pyo_VISIT return 0; } static int Trig_clear(Trig *self) { pyo_CLEAR return 0; } static void Trig_dealloc(Trig* self) { pyo_DEALLOC Trig_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Trig_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; Trig *self; self = (Trig *)type->tp_alloc(type, 0); self->flag = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Trig_compute_next_data_frame); self->mode_func_ptr = Trig_setProcMode; static char *kwlist[] = {NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) Py_RETURN_NONE; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Trig_getServer(Trig* self) { GET_SERVER }; static PyObject * Trig_getStream(Trig* self) { GET_STREAM }; static PyObject * Trig_setMul(Trig *self, PyObject *arg) { SET_MUL }; static PyObject * Trig_setAdd(Trig *self, PyObject *arg) { SET_ADD }; static PyObject * Trig_setSub(Trig *self, PyObject *arg) { SET_SUB }; static PyObject * Trig_setDiv(Trig *self, PyObject *arg) { SET_DIV }; static PyObject * Trig_play(Trig *self, PyObject *args, PyObject *kwds) { self->flag = 1; PLAY }; static PyObject * Trig_stop(Trig *self) { STOP }; static PyObject * Trig_multiply(Trig *self, PyObject *arg) { MULTIPLY }; static PyObject * Trig_inplace_multiply(Trig *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Trig_add(Trig *self, PyObject *arg) { ADD }; static PyObject * Trig_inplace_add(Trig *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Trig_sub(Trig *self, PyObject *arg) { SUB }; static PyObject * Trig_inplace_sub(Trig *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Trig_div(Trig *self, PyObject *arg) { DIV }; static PyObject * Trig_inplace_div(Trig *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Trig_members[] = { {"server", T_OBJECT_EX, offsetof(Trig, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Trig, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Trig, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Trig, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Trig_methods[] = { {"getServer", (PyCFunction)Trig_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Trig_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Trig_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Trig_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Trig_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Trig_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Trig_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Trig_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Trig_as_number = { (binaryfunc)Trig_add, /*nb_add*/ (binaryfunc)Trig_sub, /*nb_subtract*/ (binaryfunc)Trig_multiply, /*nb_multiply*/ (binaryfunc)Trig_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Trig_inplace_add, /*inplace_add*/ (binaryfunc)Trig_inplace_sub, /*inplace_subtract*/ (binaryfunc)Trig_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Trig_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Trig_base", /*tp_name*/ sizeof(Trig), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Trig_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Trig_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Trig objects. Sends one trig.", /* tp_doc */ (traverseproc)Trig_traverse, /* tp_traverse */ (inquiry)Trig_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Trig_methods, /* tp_methods */ Trig_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Trig_new, /* tp_new */ }; /****************/ /**** Beater *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *time; Stream *time_stream; int modebuffer[1]; int poly; int voiceCount; int taps; int last_taps; int tapCount; int currentTap; int weight1; int last_weight1; int weight2; int last_weight2; int weight3; int last_weight3; int newFlag; int fillStart; int fillEnd; int sequence[64]; int tmp_sequence[64]; int tapList[64]; int tapLength; int tapProb[64]; int preset[32][65]; int preCall; MYFLT durations[64]; MYFLT tmp_durations[64]; MYFLT accentTable[64]; MYFLT tmp_accentTable[64]; MYFLT tapDur; double sampleToSec; double currentTime; MYFLT *buffer_streams; MYFLT *tap_buffer_streams; MYFLT *amp_buffer_streams; MYFLT *dur_buffer_streams; MYFLT *end_buffer_streams; MYFLT *amplitudes; } Beater; static MYFLT Beater_defineAccent(int n) { if (n == 1) return (MYFLT)((rand() % 15) + 112) / 127.; // 112 -> 127 else if (n == 2) return (MYFLT)((rand() % 20) + 70) / 127.; // 70 -> 90 else if (n == 3) return (MYFLT)((rand() % 20) + 40) / 127.; // 40 -> 60 else return 0.5; } static void Beater_restore(Beater *self) { int i; self->fillEnd = 0; for (i=0; itaps; i++) { self->accentTable[i] = self->tmp_accentTable[i]; self->sequence[i] = self->tmp_sequence[i]; self->durations[i] = self->tmp_durations[i]; } } static void Beater_makeTable(Beater *self, int fill) { short i; short len; int w1, w2, w3; if (fill == 0) { self->last_taps = self->taps; w1 = self->last_weight1 = self->weight1; w2 = self->last_weight2 = self->weight2; w3 = self->last_weight3 = self->weight3; self->newFlag = 0; } else { w1 = self->weight1 + 20; w2 = self->weight2 + 20; w3 = self->weight3 + 20; self->fillStart = 0; self->fillEnd = 1; for (i=0; itaps; i++) { self->tmp_accentTable[i] = self->accentTable[i]; self->tmp_sequence[i] = self->sequence[i]; self->tmp_durations[i] = self->durations[i]; } } if ((self->taps % 7) == 0) { len = 7; for (i=0; i < self->taps; i++) { if ((i % len) == 4 || (i % len) == 2) { self->tapProb[i] = w2; self->accentTable[i] = Beater_defineAccent(2); } else if ((i % len) == 0) { self->tapProb[i] = w1; self->accentTable[i] = Beater_defineAccent(1); } else { self->tapProb[i] = w3; self->accentTable[i] = Beater_defineAccent(3); } } } else if ((self->taps % 6) == 0) { len = 6; for (i=0; i < self->taps; i++) { if ((i % len) == 3) { self->tapProb[i] = w2; self->accentTable[i] = Beater_defineAccent(2); } else if ((i % len) == 0) { self->tapProb[i] = w1; self->accentTable[i] = Beater_defineAccent(1); } else { self->tapProb[i] = w3; self->accentTable[i] = Beater_defineAccent(3); } } } else if ((self->taps % 5) == 0) { len = 5; for (i=0; i < self->taps; i++) { if ((i % len) == 3) { self->tapProb[i] = w2; self->accentTable[i] = Beater_defineAccent(2); } else if ((i % len) == 0) { self->tapProb[i] = w1; self->accentTable[i] = Beater_defineAccent(1); } else { self->tapProb[i] = w3; self->accentTable[i] = Beater_defineAccent(3); } } } else if ((self->taps % 4) == 0) { len = 4; for (i=0; i < self->taps; i++) { if ((i % len) == 2) { self->tapProb[i] = w2; self->accentTable[i] = Beater_defineAccent(2); } else if ((i % len) == 0) { self->tapProb[i] = w1; self->accentTable[i] = Beater_defineAccent(1); } else { self->tapProb[i] = w3; self->accentTable[i] = Beater_defineAccent(3); } } } else if ((self->taps % 3) == 0) { len = 3; for (i=0; i < self->taps; i++) { if ((i % len) == 0) { self->tapProb[i] = w1; self->accentTable[i] = Beater_defineAccent(1); } else { self->tapProb[i] = w3; self->accentTable[i] = Beater_defineAccent(3); } } } else if ((self->taps % 2) == 0) { len = 2; for (i=0; i < self->taps; i++) { if ((i % len) == 0) { self->tapProb[i] = w1; self->accentTable[i] = Beater_defineAccent(1); } else { self->tapProb[i] = w3; self->accentTable[i] = Beater_defineAccent(3); } } } } static void Beater_makeSequence(Beater *self) { short i, j; j = 0; for (i=0; i < self->taps; i++) { if ((rand() % 100) < self->tapProb[i]) { self->sequence[i] = 1; self->tapList[j++] = i; } else self->sequence[i] = 0; } self->tapLength = j; } static void Beater_calculateDurations(Beater *self) { int i; for (i=0; i < (self->tapLength-1); i++) { self->durations[self->tapList[i]] = (self->tapList[i+1] - self->tapList[i]) * self->tapDur - 0.005; } self->durations[self->tapList[self->tapLength-1]] = (self->last_taps - self->tapList[self->tapLength-1] + self->tapList[0]) * self->tapDur - 0.005; } static void Beater_makePresetActive(Beater *self, int n) { int i, j, len; self->preCall = -1; len = self->preset[n][0]; if (len != self->taps) { self->taps = len; Beater_makeTable(self, 0); } j = 0; for (i=0; itaps; i++) { self->sequence[i] = self->preset[n][i+1]; if (self->sequence[i] == 1) self->tapList[j++] = i; } self->tapLength = j; } static void Beater_generate_i(Beater *self) { int i, j; double tm; tm = PyFloat_AS_DOUBLE(self->time); self->tapDur = (MYFLT)tm; Beater_calculateDurations(self); if (self->currentTime == -1.0) { self->currentTime = tm; } for (i=0; i<(self->poly*self->bufsize); i++) { self->buffer_streams[i] = self->end_buffer_streams[i] = 0.0; } for (i=0; ibufsize; i++) { self->tap_buffer_streams[i + self->voiceCount * self->bufsize] = (MYFLT)self->currentTap; for (j=0; jpoly; j++) { self->amp_buffer_streams[i + j * self->bufsize] = self->amplitudes[j]; } self->dur_buffer_streams[i + self->voiceCount * self->bufsize] = self->durations[self->tapCount]; if (self->currentTime >= tm) { self->currentTime -= tm; if (self->tapCount == (self->last_taps-2)) self->end_buffer_streams[i + self->voiceCount * self->bufsize] = 1.0; if (self->sequence[self->tapCount] == 1) { self->currentTap = self->tapCount; self->amplitudes[self->voiceCount] = self->accentTable[self->tapCount]; self->buffer_streams[i + self->voiceCount++ * self->bufsize] = 1.0; if (self->voiceCount == self->poly) self->voiceCount = 0; } self->tapCount++; if (self->tapCount >= self->last_taps) { self->tapCount = 0; if (self->fillStart == 1) { Beater_makeTable(self, 1); Beater_makeSequence(self); } else if (self->fillEnd == 1 && self->newFlag == 1) { Beater_restore(self); Beater_makeTable(self, 0); Beater_makeSequence(self); } else if (self->fillEnd == 1 && self->preCall != -1) { Beater_restore(self); Beater_makePresetActive(self, self->preCall); } else if (self->fillEnd == 1) { Beater_restore(self); } else if (self->preCall != -1) { Beater_makePresetActive(self, self->preCall); } else if (self->last_taps != self->taps || self->last_weight1 != self->weight1 || self->last_weight2 != self->weight2 || self->last_weight3 != self->weight3 || self->newFlag == 1) { Beater_makeTable(self, 0); Beater_makeSequence(self); } } } self->currentTime += self->sampleToSec; } } static void Beater_generate_a(Beater *self) { double tm; int i, j; MYFLT *time = Stream_getData((Stream *)self->time_stream); self->tapDur = time[0]; Beater_calculateDurations(self); if (self->currentTime == -1.0) { self->currentTime = (double)time[0]; } for (i=0; i<(self->poly*self->bufsize); i++) { self->buffer_streams[i] = self->end_buffer_streams[i] = 0.0; } for (i=0; ibufsize; i++) { tm = (double)time[i]; self->tap_buffer_streams[i + self->voiceCount * self->bufsize] = (MYFLT)self->currentTap; for (j=0; jpoly; j++) { self->amp_buffer_streams[i + j * self->bufsize] = self->amplitudes[j]; } self->dur_buffer_streams[i + self->voiceCount * self->bufsize] = self->durations[self->tapCount]; if (self->currentTime >= tm) { self->currentTime -= tm; if (self->tapCount == (self->last_taps-2)) self->end_buffer_streams[i + self->voiceCount * self->bufsize] = 1.0; if (self->sequence[self->tapCount] == 1) { self->currentTap = self->tapCount; self->amplitudes[self->voiceCount] = self->accentTable[self->tapCount]; self->buffer_streams[i + self->voiceCount++ * self->bufsize] = 1.0; if (self->voiceCount == self->poly) self->voiceCount = 0; } self->tapCount++; if (self->tapCount >= self->last_taps) { self->tapCount = 0; if (self->fillStart == 1) { Beater_makeTable(self, 1); Beater_makeSequence(self); } else if (self->fillEnd == 1 && self->newFlag == 1) { Beater_restore(self); Beater_makeTable(self, 0); Beater_makeSequence(self); } else if (self->fillEnd == 1 && self->preCall != -1) { Beater_restore(self); Beater_makePresetActive(self, self->preCall); } else if (self->fillEnd == 1) { Beater_restore(self); } else if (self->preCall != -1) { Beater_makePresetActive(self, self->preCall); } else if (self->last_taps != self->taps || self->last_weight1 != self->weight1 || self->last_weight2 != self->weight2 || self->last_weight3 != self->weight3 || self->newFlag == 1) { self->tapDur = time[i]; Beater_makeTable(self, 0); Beater_makeSequence(self); } } } self->currentTime += self->sampleToSec; } } MYFLT * Beater_getSamplesBuffer(Beater *self) { return (MYFLT *)self->buffer_streams; } MYFLT * Beater_getTapBuffer(Beater *self) { return (MYFLT *)self->tap_buffer_streams; } MYFLT * Beater_getAmpBuffer(Beater *self) { return (MYFLT *)self->amp_buffer_streams; } MYFLT * Beater_getDurBuffer(Beater *self) { return (MYFLT *)self->dur_buffer_streams; } MYFLT * Beater_getEndBuffer(Beater *self) { return (MYFLT *)self->end_buffer_streams; } static void Beater_setProcMode(Beater *self) { int procmode = self->modebuffer[0]; switch (procmode) { case 0: self->proc_func_ptr = Beater_generate_i; break; case 1: self->proc_func_ptr = Beater_generate_a; break; } } static void Beater_compute_next_data_frame(Beater *self) { (*self->proc_func_ptr)(self); } static int Beater_traverse(Beater *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->time); Py_VISIT(self->time_stream); return 0; } static int Beater_clear(Beater *self) { pyo_CLEAR Py_CLEAR(self->time); Py_CLEAR(self->time_stream); return 0; } static void Beater_dealloc(Beater* self) { pyo_DEALLOC free(self->buffer_streams); free(self->tap_buffer_streams); free(self->amp_buffer_streams); free(self->dur_buffer_streams); free(self->end_buffer_streams); free(self->amplitudes); Beater_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Beater_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, j; PyObject *timetmp=NULL; Beater *self; self = (Beater *)type->tp_alloc(type, 0); for (i=0; i<32; i++) { for (j=0; j<64; j++) { self->preset[i][j] = 0; } } self->preCall = -1; self->time = PyFloat_FromDouble(0.125); self->tapDur = 0.125; self->poly = 1; self->voiceCount = 0; self->modebuffer[0] = 0; self->taps = 16; self->tapCount = 0; self->currentTap = 0; self->weight1 = 80; self->weight2 = 50; self->weight3 = 30; self->last_taps = self->last_weight1 = self->last_weight2 = self->last_weight3 = -1; self->newFlag = self->fillStart = self->fillEnd = 0; self->tapLength = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Beater_compute_next_data_frame); self->mode_func_ptr = Beater_setProcMode; self->sampleToSec = 1. / self->sr; self->currentTime = -1.0; Stream_setStreamActive(self->stream, 0); static char *kwlist[] = {"time", "taps", "weight1", "weight2", "weight3", "poly", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oiiiii", kwlist, &timetmp, &self->taps, &self->weight1, &self->weight2, &self->weight3, &self->poly)) Py_RETURN_NONE; if (timetmp) { PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); Server_generateSeed((Server *)self->server, BEATER_ID); self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->poly * self->bufsize * sizeof(MYFLT)); self->tap_buffer_streams = (MYFLT *)realloc(self->tap_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT)); self->amp_buffer_streams = (MYFLT *)realloc(self->amp_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT)); self->dur_buffer_streams = (MYFLT *)realloc(self->dur_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT)); self->end_buffer_streams = (MYFLT *)realloc(self->end_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT)); for (i=0; i<(self->poly*self->bufsize); i++) { self->buffer_streams[i] = self->tap_buffer_streams[i] = self->amp_buffer_streams[i] = self->dur_buffer_streams[i] = self->end_buffer_streams[i] = 0.0; } self->amplitudes = (MYFLT *)realloc(self->amplitudes, self->poly * sizeof(MYFLT)); for (i=0; ipoly; i++) { self->amplitudes[i] = 0.0; } Beater_makeTable(self, 0); Beater_makeSequence(self); return (PyObject *)self; } static PyObject * Beater_getServer(Beater* self) { GET_SERVER }; static PyObject * Beater_getStream(Beater* self) { GET_STREAM }; static PyObject * Beater_play(Beater *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Beater_stop(Beater *self) { STOP }; static PyObject * Beater_setTime(Beater *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->time); if (isNumber == 1) { self->time = PyNumber_Float(tmp); self->tapDur = PyFloat_AS_DOUBLE(self->time); self->modebuffer[0] = 0; } else { self->time = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->time, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->time_stream); self->time_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; MYFLT *time = Stream_getData((Stream *)self->time_stream); self->tapDur = time[0]; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Beater_reset(Beater *self) { self->voiceCount = 0; self->tapCount = 0; self->currentTap = 0; self->currentTime = -1.0; Py_INCREF(Py_None); return Py_None; } static PyObject * Beater_setTaps(Beater *self, PyObject *arg) { if (PyInt_Check(arg)) self->taps = PyInt_AS_LONG(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * Beater_setWeights(Beater *self, PyObject *args, PyObject *kwds) { PyObject *w1=NULL, *w2=NULL, *w3=NULL; static char *kwlist[] = {"weight1", "weight2", "weight3", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &w1, &w2, &w3)) { Py_INCREF(Py_None); return Py_None; } if (PyInt_Check(w1)) self->weight1 = PyInt_AS_LONG(w1); if (PyInt_Check(w2)) self->weight2 = PyInt_AS_LONG(w2); if (PyInt_Check(w3)) self->weight3 = PyInt_AS_LONG(w3); Py_INCREF(Py_None); return Py_None; } static PyObject * Beater_newPattern(Beater *self) { self->newFlag = 1; Py_INCREF(Py_None); return Py_None; } static PyObject * Beater_fillPattern(Beater *self) { self->fillStart = 1; Py_INCREF(Py_None); return Py_None; } static PyObject * Beater_storePreset(Beater *self, PyObject *arg) { int i, n; if (PyInt_Check(arg)) { n = PyInt_AS_LONG(arg); self->preset[n][0] = self->taps; for (i=0; itaps; i++) { self->preset[n][i+1] = self->sequence[i]; } } Py_INCREF(Py_None); return Py_None; } static PyObject * Beater_recallPreset(Beater *self, PyObject *arg) { int x; if (PyInt_Check(arg)) { x = PyInt_AS_LONG(arg); if (x >= 0 && x < 32) self->preCall = x; } if (Stream_getStreamActive(self->stream) == 0) Beater_makePresetActive(self, self->preCall); Py_INCREF(Py_None); return Py_None; } static PyObject * Beater_getPresets(Beater *self) { int i, j; PyObject *list, *tmp; list = PyList_New(0); for (i=0; i<32; i++) { if (self->preset[i][0] != 0) { tmp = PyList_New(0); PyList_Append(tmp, PyInt_FromLong(self->preset[i][0])); for (j=0; jpreset[i][0]; j++) { PyList_Append(tmp, PyInt_FromLong(self->preset[i][j+1])); } PyList_Append(list, tmp); } } return list; } static PyObject * Beater_setPresets(Beater *self, PyObject *arg) { int i, j, len, len2; PyObject *tmp; if (PyList_Check(arg)) { len = PyList_Size(arg); for (i=0; ipreset[i][0] = len2; for (j=0; jpreset[i][j+1] = PyInt_AsLong(PyList_GetItem(tmp, j+1)); } } } } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Beater_members[] = { {"server", T_OBJECT_EX, offsetof(Beater, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Beater, stream), 0, "Stream object."}, {"time", T_OBJECT_EX, offsetof(Beater, time), 0, "Tap duration."}, {NULL} /* Sentinel */ }; static PyMethodDef Beater_methods[] = { {"getServer", (PyCFunction)Beater_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Beater_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Beater_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Beater_stop, METH_NOARGS, "Stops computing."}, {"setTime", (PyCFunction)Beater_setTime, METH_O, "Sets tap duration."}, {"setTaps", (PyCFunction)Beater_setTaps, METH_O, "Sets number of taps in the pattern."}, {"setWeights", (PyCFunction)Beater_setWeights, METH_VARARGS|METH_KEYWORDS, "Sets probabilities for time accents in the pattern."}, {"new", (PyCFunction)Beater_newPattern, METH_NOARGS, "Generates a new pattern."}, {"fill", (PyCFunction)Beater_fillPattern, METH_NOARGS, "Generates a fillin pattern and then restore the current pattern."}, {"store", (PyCFunction)Beater_storePreset, METH_O, "Store the current pattern in a memory slot."}, {"recall", (PyCFunction)Beater_recallPreset, METH_O, "Recall a pattern previously stored in a memory slot."}, {"getPresets", (PyCFunction)Beater_getPresets, METH_NOARGS, "Returns the list of stored presets."}, {"setPresets", (PyCFunction)Beater_setPresets, METH_O, "Store a list of presets."}, {"reset", (PyCFunction)Beater_reset, METH_NOARGS, "Resets counters to 0."}, {NULL} /* Sentinel */ }; PyTypeObject BeaterType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Beater_base", /*tp_name*/ sizeof(Beater), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Beater_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Beater objects. Create an algorithmic beat sequence.", /* tp_doc */ (traverseproc)Beater_traverse, /* tp_traverse */ (inquiry)Beater_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Beater_methods, /* tp_methods */ Beater_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Beater_new, /* tp_new */ }; /************************************************************************************************/ /* Beat streamer object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD Beater *mainPlayer; int chnl; int modebuffer[2]; } Beat; static void Beat_postprocessing_ii(Beat *self) { POST_PROCESSING_II }; static void Beat_postprocessing_ai(Beat *self) { POST_PROCESSING_AI }; static void Beat_postprocessing_ia(Beat *self) { POST_PROCESSING_IA }; static void Beat_postprocessing_aa(Beat *self) { POST_PROCESSING_AA }; static void Beat_postprocessing_ireva(Beat *self) { POST_PROCESSING_IREVA }; static void Beat_postprocessing_areva(Beat *self) { POST_PROCESSING_AREVA }; static void Beat_postprocessing_revai(Beat *self) { POST_PROCESSING_REVAI }; static void Beat_postprocessing_revaa(Beat *self) { POST_PROCESSING_REVAA }; static void Beat_postprocessing_revareva(Beat *self) { POST_PROCESSING_REVAREVA }; static void Beat_setProcMode(Beat *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Beat_postprocessing_ii; break; case 1: self->muladd_func_ptr = Beat_postprocessing_ai; break; case 2: self->muladd_func_ptr = Beat_postprocessing_revai; break; case 10: self->muladd_func_ptr = Beat_postprocessing_ia; break; case 11: self->muladd_func_ptr = Beat_postprocessing_aa; break; case 12: self->muladd_func_ptr = Beat_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Beat_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Beat_postprocessing_areva; break; case 22: self->muladd_func_ptr = Beat_postprocessing_revareva; break; } } static void Beat_compute_next_data_frame(Beat *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = Beater_getSamplesBuffer((Beater *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int Beat_traverse(Beat *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int Beat_clear(Beat *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void Beat_dealloc(Beat* self) { pyo_DEALLOC Beat_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Beat_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; Beat *self; self = (Beat *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Beat_compute_next_data_frame); self->mode_func_ptr = Beat_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (Beater *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Beat_getServer(Beat* self) { GET_SERVER }; static PyObject * Beat_getStream(Beat* self) { GET_STREAM }; static PyObject * Beat_setMul(Beat *self, PyObject *arg) { SET_MUL }; static PyObject * Beat_setAdd(Beat *self, PyObject *arg) { SET_ADD }; static PyObject * Beat_setSub(Beat *self, PyObject *arg) { SET_SUB }; static PyObject * Beat_setDiv(Beat *self, PyObject *arg) { SET_DIV }; static PyObject * Beat_play(Beat *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Beat_out(Beat *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Beat_stop(Beat *self) { STOP }; static PyObject * Beat_multiply(Beat *self, PyObject *arg) { MULTIPLY }; static PyObject * Beat_inplace_multiply(Beat *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Beat_add(Beat *self, PyObject *arg) { ADD }; static PyObject * Beat_inplace_add(Beat *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Beat_sub(Beat *self, PyObject *arg) { SUB }; static PyObject * Beat_inplace_sub(Beat *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Beat_div(Beat *self, PyObject *arg) { DIV }; static PyObject * Beat_inplace_div(Beat *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Beat_members[] = { {"server", T_OBJECT_EX, offsetof(Beat, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Beat, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Beat, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Beat, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Beat_methods[] = { {"getServer", (PyCFunction)Beat_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Beat_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Beat_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Beat_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Beat_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Beat_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Beat_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Beat_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Beat_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Beat_as_number = { (binaryfunc)Beat_add, /*nb_add*/ (binaryfunc)Beat_sub, /*nb_subtract*/ (binaryfunc)Beat_multiply, /*nb_multiply*/ (binaryfunc)Beat_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Beat_inplace_add, /*inplace_add*/ (binaryfunc)Beat_inplace_sub, /*inplace_subtract*/ (binaryfunc)Beat_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Beat_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject BeatType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Beat_base", /*tp_name*/ sizeof(Beat), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Beat_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Beat_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Beat objects. Reads a channel from a Beater.", /* tp_doc */ (traverseproc)Beat_traverse, /* tp_traverse */ (inquiry)Beat_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Beat_methods, /* tp_methods */ Beat_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Beat_new, /* tp_new */ }; /************************************************************************************************/ /* BeatTapStream object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD Beater *mainPlayer; int chnl; int modebuffer[2]; } BeatTapStream; static void BeatTapStream_postprocessing_ii(BeatTapStream *self) { POST_PROCESSING_II }; static void BeatTapStream_postprocessing_ai(BeatTapStream *self) { POST_PROCESSING_AI }; static void BeatTapStream_postprocessing_ia(BeatTapStream *self) { POST_PROCESSING_IA }; static void BeatTapStream_postprocessing_aa(BeatTapStream *self) { POST_PROCESSING_AA }; static void BeatTapStream_postprocessing_ireva(BeatTapStream *self) { POST_PROCESSING_IREVA }; static void BeatTapStream_postprocessing_areva(BeatTapStream *self) { POST_PROCESSING_AREVA }; static void BeatTapStream_postprocessing_revai(BeatTapStream *self) { POST_PROCESSING_REVAI }; static void BeatTapStream_postprocessing_revaa(BeatTapStream *self) { POST_PROCESSING_REVAA }; static void BeatTapStream_postprocessing_revareva(BeatTapStream *self) { POST_PROCESSING_REVAREVA }; static void BeatTapStream_setProcMode(BeatTapStream *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = BeatTapStream_postprocessing_ii; break; case 1: self->muladd_func_ptr = BeatTapStream_postprocessing_ai; break; case 2: self->muladd_func_ptr = BeatTapStream_postprocessing_revai; break; case 10: self->muladd_func_ptr = BeatTapStream_postprocessing_ia; break; case 11: self->muladd_func_ptr = BeatTapStream_postprocessing_aa; break; case 12: self->muladd_func_ptr = BeatTapStream_postprocessing_revaa; break; case 20: self->muladd_func_ptr = BeatTapStream_postprocessing_ireva; break; case 21: self->muladd_func_ptr = BeatTapStream_postprocessing_areva; break; case 22: self->muladd_func_ptr = BeatTapStream_postprocessing_revareva; break; } } static void BeatTapStream_compute_next_data_frame(BeatTapStream *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = Beater_getTapBuffer((Beater *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int BeatTapStream_traverse(BeatTapStream *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int BeatTapStream_clear(BeatTapStream *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void BeatTapStream_dealloc(BeatTapStream* self) { pyo_DEALLOC BeatTapStream_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * BeatTapStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; BeatTapStream *self; self = (BeatTapStream *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, BeatTapStream_compute_next_data_frame); self->mode_func_ptr = BeatTapStream_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (Beater *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * BeatTapStream_getServer(BeatTapStream* self) { GET_SERVER }; static PyObject * BeatTapStream_getStream(BeatTapStream* self) { GET_STREAM }; static PyObject * BeatTapStream_setMul(BeatTapStream *self, PyObject *arg) { SET_MUL }; static PyObject * BeatTapStream_setAdd(BeatTapStream *self, PyObject *arg) { SET_ADD }; static PyObject * BeatTapStream_setSub(BeatTapStream *self, PyObject *arg) { SET_SUB }; static PyObject * BeatTapStream_setDiv(BeatTapStream *self, PyObject *arg) { SET_DIV }; static PyObject * BeatTapStream_play(BeatTapStream *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * BeatTapStream_out(BeatTapStream *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * BeatTapStream_stop(BeatTapStream *self) { STOP }; static PyObject * BeatTapStream_multiply(BeatTapStream *self, PyObject *arg) { MULTIPLY }; static PyObject * BeatTapStream_inplace_multiply(BeatTapStream *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * BeatTapStream_add(BeatTapStream *self, PyObject *arg) { ADD }; static PyObject * BeatTapStream_inplace_add(BeatTapStream *self, PyObject *arg) { INPLACE_ADD }; static PyObject * BeatTapStream_sub(BeatTapStream *self, PyObject *arg) { SUB }; static PyObject * BeatTapStream_inplace_sub(BeatTapStream *self, PyObject *arg) { INPLACE_SUB }; static PyObject * BeatTapStream_div(BeatTapStream *self, PyObject *arg) { DIV }; static PyObject * BeatTapStream_inplace_div(BeatTapStream *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef BeatTapStream_members[] = { {"server", T_OBJECT_EX, offsetof(BeatTapStream, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(BeatTapStream, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(BeatTapStream, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(BeatTapStream, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef BeatTapStream_methods[] = { {"getServer", (PyCFunction)BeatTapStream_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)BeatTapStream_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)BeatTapStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)BeatTapStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)BeatTapStream_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)BeatTapStream_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)BeatTapStream_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)BeatTapStream_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)BeatTapStream_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods BeatTapStream_as_number = { (binaryfunc)BeatTapStream_add, /*nb_add*/ (binaryfunc)BeatTapStream_sub, /*nb_subtract*/ (binaryfunc)BeatTapStream_multiply, /*nb_multiply*/ (binaryfunc)BeatTapStream_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)BeatTapStream_inplace_add, /*inplace_add*/ (binaryfunc)BeatTapStream_inplace_sub, /*inplace_subtract*/ (binaryfunc)BeatTapStream_inplace_multiply, /*inplace_multiply*/ (binaryfunc)BeatTapStream_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject BeatTapStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.BeatTapStream_base", /*tp_name*/ sizeof(BeatTapStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)BeatTapStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &BeatTapStream_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "BeatTapStream objects. Reads the current tap from a Beater object.", /* tp_doc */ (traverseproc)BeatTapStream_traverse, /* tp_traverse */ (inquiry)BeatTapStream_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ BeatTapStream_methods, /* tp_methods */ BeatTapStream_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ BeatTapStream_new, /* tp_new */ }; /************************************************************************************************/ /* BeatAmpStream object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD Beater *mainPlayer; int chnl; int modebuffer[2]; } BeatAmpStream; static void BeatAmpStream_postprocessing_ii(BeatAmpStream *self) { POST_PROCESSING_II }; static void BeatAmpStream_postprocessing_ai(BeatAmpStream *self) { POST_PROCESSING_AI }; static void BeatAmpStream_postprocessing_ia(BeatAmpStream *self) { POST_PROCESSING_IA }; static void BeatAmpStream_postprocessing_aa(BeatAmpStream *self) { POST_PROCESSING_AA }; static void BeatAmpStream_postprocessing_ireva(BeatAmpStream *self) { POST_PROCESSING_IREVA }; static void BeatAmpStream_postprocessing_areva(BeatAmpStream *self) { POST_PROCESSING_AREVA }; static void BeatAmpStream_postprocessing_revai(BeatAmpStream *self) { POST_PROCESSING_REVAI }; static void BeatAmpStream_postprocessing_revaa(BeatAmpStream *self) { POST_PROCESSING_REVAA }; static void BeatAmpStream_postprocessing_revareva(BeatAmpStream *self) { POST_PROCESSING_REVAREVA }; static void BeatAmpStream_setProcMode(BeatAmpStream *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = BeatAmpStream_postprocessing_ii; break; case 1: self->muladd_func_ptr = BeatAmpStream_postprocessing_ai; break; case 2: self->muladd_func_ptr = BeatAmpStream_postprocessing_revai; break; case 10: self->muladd_func_ptr = BeatAmpStream_postprocessing_ia; break; case 11: self->muladd_func_ptr = BeatAmpStream_postprocessing_aa; break; case 12: self->muladd_func_ptr = BeatAmpStream_postprocessing_revaa; break; case 20: self->muladd_func_ptr = BeatAmpStream_postprocessing_ireva; break; case 21: self->muladd_func_ptr = BeatAmpStream_postprocessing_areva; break; case 22: self->muladd_func_ptr = BeatAmpStream_postprocessing_revareva; break; } } static void BeatAmpStream_compute_next_data_frame(BeatAmpStream *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = Beater_getAmpBuffer((Beater *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int BeatAmpStream_traverse(BeatAmpStream *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int BeatAmpStream_clear(BeatAmpStream *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void BeatAmpStream_dealloc(BeatAmpStream* self) { pyo_DEALLOC BeatAmpStream_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * BeatAmpStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; BeatAmpStream *self; self = (BeatAmpStream *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, BeatAmpStream_compute_next_data_frame); self->mode_func_ptr = BeatAmpStream_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (Beater *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * BeatAmpStream_getServer(BeatAmpStream* self) { GET_SERVER }; static PyObject * BeatAmpStream_getStream(BeatAmpStream* self) { GET_STREAM }; static PyObject * BeatAmpStream_setMul(BeatAmpStream *self, PyObject *arg) { SET_MUL }; static PyObject * BeatAmpStream_setAdd(BeatAmpStream *self, PyObject *arg) { SET_ADD }; static PyObject * BeatAmpStream_setSub(BeatAmpStream *self, PyObject *arg) { SET_SUB }; static PyObject * BeatAmpStream_setDiv(BeatAmpStream *self, PyObject *arg) { SET_DIV }; static PyObject * BeatAmpStream_play(BeatAmpStream *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * BeatAmpStream_out(BeatAmpStream *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * BeatAmpStream_stop(BeatAmpStream *self) { STOP }; static PyObject * BeatAmpStream_multiply(BeatAmpStream *self, PyObject *arg) { MULTIPLY }; static PyObject * BeatAmpStream_inplace_multiply(BeatAmpStream *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * BeatAmpStream_add(BeatAmpStream *self, PyObject *arg) { ADD }; static PyObject * BeatAmpStream_inplace_add(BeatAmpStream *self, PyObject *arg) { INPLACE_ADD }; static PyObject * BeatAmpStream_sub(BeatAmpStream *self, PyObject *arg) { SUB }; static PyObject * BeatAmpStream_inplace_sub(BeatAmpStream *self, PyObject *arg) { INPLACE_SUB }; static PyObject * BeatAmpStream_div(BeatAmpStream *self, PyObject *arg) { DIV }; static PyObject * BeatAmpStream_inplace_div(BeatAmpStream *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef BeatAmpStream_members[] = { {"server", T_OBJECT_EX, offsetof(BeatAmpStream, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(BeatAmpStream, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(BeatAmpStream, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(BeatAmpStream, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef BeatAmpStream_methods[] = { {"getServer", (PyCFunction)BeatAmpStream_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)BeatAmpStream_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)BeatAmpStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)BeatAmpStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)BeatAmpStream_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)BeatAmpStream_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)BeatAmpStream_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)BeatAmpStream_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)BeatAmpStream_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods BeatAmpStream_as_number = { (binaryfunc)BeatAmpStream_add, /*nb_add*/ (binaryfunc)BeatAmpStream_sub, /*nb_subtract*/ (binaryfunc)BeatAmpStream_multiply, /*nb_multiply*/ (binaryfunc)BeatAmpStream_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)BeatAmpStream_inplace_add, /*inplace_add*/ (binaryfunc)BeatAmpStream_inplace_sub, /*inplace_subtract*/ (binaryfunc)BeatAmpStream_inplace_multiply, /*inplace_multiply*/ (binaryfunc)BeatAmpStream_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject BeatAmpStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.BeatAmpStream_base", /*tp_name*/ sizeof(BeatAmpStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)BeatAmpStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &BeatAmpStream_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "BeatAmpStream objects. Reads a amplitude channel from a Beater object.", /* tp_doc */ (traverseproc)BeatAmpStream_traverse, /* tp_traverse */ (inquiry)BeatAmpStream_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ BeatAmpStream_methods, /* tp_methods */ BeatAmpStream_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ BeatAmpStream_new, /* tp_new */ }; /************************************************************************************************/ /* BeatDurStream object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD Beater *mainPlayer; int chnl; int modebuffer[2]; } BeatDurStream; static void BeatDurStream_postprocessing_ii(BeatDurStream *self) { POST_PROCESSING_II }; static void BeatDurStream_postprocessing_ai(BeatDurStream *self) { POST_PROCESSING_AI }; static void BeatDurStream_postprocessing_ia(BeatDurStream *self) { POST_PROCESSING_IA }; static void BeatDurStream_postprocessing_aa(BeatDurStream *self) { POST_PROCESSING_AA }; static void BeatDurStream_postprocessing_ireva(BeatDurStream *self) { POST_PROCESSING_IREVA }; static void BeatDurStream_postprocessing_areva(BeatDurStream *self) { POST_PROCESSING_AREVA }; static void BeatDurStream_postprocessing_revai(BeatDurStream *self) { POST_PROCESSING_REVAI }; static void BeatDurStream_postprocessing_revaa(BeatDurStream *self) { POST_PROCESSING_REVAA }; static void BeatDurStream_postprocessing_revareva(BeatDurStream *self) { POST_PROCESSING_REVAREVA }; static void BeatDurStream_setProcMode(BeatDurStream *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = BeatDurStream_postprocessing_ii; break; case 1: self->muladd_func_ptr = BeatDurStream_postprocessing_ai; break; case 2: self->muladd_func_ptr = BeatDurStream_postprocessing_revai; break; case 10: self->muladd_func_ptr = BeatDurStream_postprocessing_ia; break; case 11: self->muladd_func_ptr = BeatDurStream_postprocessing_aa; break; case 12: self->muladd_func_ptr = BeatDurStream_postprocessing_revaa; break; case 20: self->muladd_func_ptr = BeatDurStream_postprocessing_ireva; break; case 21: self->muladd_func_ptr = BeatDurStream_postprocessing_areva; break; case 22: self->muladd_func_ptr = BeatDurStream_postprocessing_revareva; break; } } static void BeatDurStream_compute_next_data_frame(BeatDurStream *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = Beater_getDurBuffer((Beater *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int BeatDurStream_traverse(BeatDurStream *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int BeatDurStream_clear(BeatDurStream *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void BeatDurStream_dealloc(BeatDurStream* self) { pyo_DEALLOC BeatDurStream_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * BeatDurStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; BeatDurStream *self; self = (BeatDurStream *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, BeatDurStream_compute_next_data_frame); self->mode_func_ptr = BeatDurStream_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (Beater *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * BeatDurStream_getServer(BeatDurStream* self) { GET_SERVER }; static PyObject * BeatDurStream_getStream(BeatDurStream* self) { GET_STREAM }; static PyObject * BeatDurStream_setMul(BeatDurStream *self, PyObject *arg) { SET_MUL }; static PyObject * BeatDurStream_setAdd(BeatDurStream *self, PyObject *arg) { SET_ADD }; static PyObject * BeatDurStream_setSub(BeatDurStream *self, PyObject *arg) { SET_SUB }; static PyObject * BeatDurStream_setDiv(BeatDurStream *self, PyObject *arg) { SET_DIV }; static PyObject * BeatDurStream_play(BeatDurStream *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * BeatDurStream_out(BeatDurStream *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * BeatDurStream_stop(BeatDurStream *self) { STOP }; static PyObject * BeatDurStream_multiply(BeatDurStream *self, PyObject *arg) { MULTIPLY }; static PyObject * BeatDurStream_inplace_multiply(BeatDurStream *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * BeatDurStream_add(BeatDurStream *self, PyObject *arg) { ADD }; static PyObject * BeatDurStream_inplace_add(BeatDurStream *self, PyObject *arg) { INPLACE_ADD }; static PyObject * BeatDurStream_sub(BeatDurStream *self, PyObject *arg) { SUB }; static PyObject * BeatDurStream_inplace_sub(BeatDurStream *self, PyObject *arg) { INPLACE_SUB }; static PyObject * BeatDurStream_div(BeatDurStream *self, PyObject *arg) { DIV }; static PyObject * BeatDurStream_inplace_div(BeatDurStream *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef BeatDurStream_members[] = { {"server", T_OBJECT_EX, offsetof(BeatDurStream, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(BeatDurStream, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(BeatDurStream, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(BeatDurStream, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef BeatDurStream_methods[] = { {"getServer", (PyCFunction)BeatDurStream_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)BeatDurStream_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)BeatDurStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)BeatDurStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)BeatDurStream_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)BeatDurStream_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)BeatDurStream_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)BeatDurStream_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)BeatDurStream_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods BeatDurStream_as_number = { (binaryfunc)BeatDurStream_add, /*nb_add*/ (binaryfunc)BeatDurStream_sub, /*nb_subtract*/ (binaryfunc)BeatDurStream_multiply, /*nb_multiply*/ (binaryfunc)BeatDurStream_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)BeatDurStream_inplace_add, /*inplace_add*/ (binaryfunc)BeatDurStream_inplace_sub, /*inplace_subtract*/ (binaryfunc)BeatDurStream_inplace_multiply, /*inplace_multiply*/ (binaryfunc)BeatDurStream_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject BeatDurStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.BeatDurStream_base", /*tp_name*/ sizeof(BeatDurStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)BeatDurStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &BeatDurStream_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "BeatDurStream objects. Reads a duration channel from a Beater object.", /* tp_doc */ (traverseproc)BeatDurStream_traverse, /* tp_traverse */ (inquiry)BeatDurStream_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ BeatDurStream_methods, /* tp_methods */ BeatDurStream_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ BeatDurStream_new, /* tp_new */ }; /************************************************************************************************/ /* BeatEndStream object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD Beater *mainPlayer; int chnl; int modebuffer[2]; } BeatEndStream; static void BeatEndStream_postprocessing_ii(BeatEndStream *self) { POST_PROCESSING_II }; static void BeatEndStream_postprocessing_ai(BeatEndStream *self) { POST_PROCESSING_AI }; static void BeatEndStream_postprocessing_ia(BeatEndStream *self) { POST_PROCESSING_IA }; static void BeatEndStream_postprocessing_aa(BeatEndStream *self) { POST_PROCESSING_AA }; static void BeatEndStream_postprocessing_ireva(BeatEndStream *self) { POST_PROCESSING_IREVA }; static void BeatEndStream_postprocessing_areva(BeatEndStream *self) { POST_PROCESSING_AREVA }; static void BeatEndStream_postprocessing_revai(BeatEndStream *self) { POST_PROCESSING_REVAI }; static void BeatEndStream_postprocessing_revaa(BeatEndStream *self) { POST_PROCESSING_REVAA }; static void BeatEndStream_postprocessing_revareva(BeatEndStream *self) { POST_PROCESSING_REVAREVA }; static void BeatEndStream_setProcMode(BeatEndStream *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = BeatEndStream_postprocessing_ii; break; case 1: self->muladd_func_ptr = BeatEndStream_postprocessing_ai; break; case 2: self->muladd_func_ptr = BeatEndStream_postprocessing_revai; break; case 10: self->muladd_func_ptr = BeatEndStream_postprocessing_ia; break; case 11: self->muladd_func_ptr = BeatEndStream_postprocessing_aa; break; case 12: self->muladd_func_ptr = BeatEndStream_postprocessing_revaa; break; case 20: self->muladd_func_ptr = BeatEndStream_postprocessing_ireva; break; case 21: self->muladd_func_ptr = BeatEndStream_postprocessing_areva; break; case 22: self->muladd_func_ptr = BeatEndStream_postprocessing_revareva; break; } } static void BeatEndStream_compute_next_data_frame(BeatEndStream *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = Beater_getEndBuffer((Beater *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int BeatEndStream_traverse(BeatEndStream *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int BeatEndStream_clear(BeatEndStream *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void BeatEndStream_dealloc(BeatEndStream* self) { pyo_DEALLOC BeatEndStream_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * BeatEndStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; BeatEndStream *self; self = (BeatEndStream *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, BeatEndStream_compute_next_data_frame); self->mode_func_ptr = BeatEndStream_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (Beater *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * BeatEndStream_getServer(BeatEndStream* self) { GET_SERVER }; static PyObject * BeatEndStream_getStream(BeatEndStream* self) { GET_STREAM }; static PyObject * BeatEndStream_setMul(BeatEndStream *self, PyObject *arg) { SET_MUL }; static PyObject * BeatEndStream_setAdd(BeatEndStream *self, PyObject *arg) { SET_ADD }; static PyObject * BeatEndStream_setSub(BeatEndStream *self, PyObject *arg) { SET_SUB }; static PyObject * BeatEndStream_setDiv(BeatEndStream *self, PyObject *arg) { SET_DIV }; static PyObject * BeatEndStream_play(BeatEndStream *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * BeatEndStream_out(BeatEndStream *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * BeatEndStream_stop(BeatEndStream *self) { STOP }; static PyObject * BeatEndStream_multiply(BeatEndStream *self, PyObject *arg) { MULTIPLY }; static PyObject * BeatEndStream_inplace_multiply(BeatEndStream *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * BeatEndStream_add(BeatEndStream *self, PyObject *arg) { ADD }; static PyObject * BeatEndStream_inplace_add(BeatEndStream *self, PyObject *arg) { INPLACE_ADD }; static PyObject * BeatEndStream_sub(BeatEndStream *self, PyObject *arg) { SUB }; static PyObject * BeatEndStream_inplace_sub(BeatEndStream *self, PyObject *arg) { INPLACE_SUB }; static PyObject * BeatEndStream_div(BeatEndStream *self, PyObject *arg) { DIV }; static PyObject * BeatEndStream_inplace_div(BeatEndStream *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef BeatEndStream_members[] = { {"server", T_OBJECT_EX, offsetof(BeatEndStream, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(BeatEndStream, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(BeatEndStream, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(BeatEndStream, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef BeatEndStream_methods[] = { {"getServer", (PyCFunction)BeatEndStream_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)BeatEndStream_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)BeatEndStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)BeatEndStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)BeatEndStream_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)BeatEndStream_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)BeatEndStream_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)BeatEndStream_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)BeatEndStream_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods BeatEndStream_as_number = { (binaryfunc)BeatEndStream_add, /*nb_add*/ (binaryfunc)BeatEndStream_sub, /*nb_subtract*/ (binaryfunc)BeatEndStream_multiply, /*nb_multiply*/ (binaryfunc)BeatEndStream_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)BeatEndStream_inplace_add, /*inplace_add*/ (binaryfunc)BeatEndStream_inplace_sub, /*inplace_subtract*/ (binaryfunc)BeatEndStream_inplace_multiply, /*inplace_multiply*/ (binaryfunc)BeatEndStream_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject BeatEndStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.BeatEndStream_base", /*tp_name*/ sizeof(BeatEndStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)BeatEndStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &BeatEndStream_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "BeatEndStream objects. Reads a duration channel from a Beater object.", /* tp_doc */ (traverseproc)BeatEndStream_traverse, /* tp_traverse */ (inquiry)BeatEndStream_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ BeatEndStream_methods, /* tp_methods */ BeatEndStream_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ BeatEndStream_new, /* tp_new */ }; /****************/ /**** TrigBurster *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[1]; int poly; int voiceCount; MYFLT time; MYFLT a_time; int count; int a_count; MYFLT expand; MYFLT a_expand; MYFLT ampfade; MYFLT a_ampfade; int flag; double sampleToSec; double currentTime; double targetTime; int currentCount; int *currentTap; MYFLT *currentAmp; MYFLT *currentDur; MYFLT *buffer_streams; MYFLT *tap_buffer_streams; MYFLT *amp_buffer_streams; MYFLT *dur_buffer_streams; MYFLT *end_buffer_streams; } TrigBurster; static void TrigBurster_generate_i(TrigBurster *self) { int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; i<(self->poly*self->bufsize); i++) { self->buffer_streams[i] = self->end_buffer_streams[i] = 0.0; } for (i=0; ibufsize; i++) { if (in[i] == 1.0) { self->flag = 1; self->currentCount = 0; self->a_time = self->targetTime = self->currentTime = self->time; self->a_count = self->count; self->a_expand = self->expand; self->a_ampfade = self->ampfade; } if (self->flag == 1) { if (self->currentTime >= self->targetTime) { self->currentTime -= self->targetTime; self->targetTime = self->a_time * MYPOW(self->a_expand, self->currentCount); self->currentTap[self->voiceCount] = self->currentCount; self->currentAmp[self->voiceCount] = MYPOW(self->a_ampfade, self->currentCount); self->currentDur[self->voiceCount] = self->targetTime; self->buffer_streams[i + self->voiceCount * self->bufsize] = 1.0; self->currentCount++; if (self->currentCount == (self->a_count - 1)) self->end_buffer_streams[i + self->voiceCount * self->bufsize] = 1.0; if (self->currentCount == self->a_count) self->flag = 0; self->voiceCount++; if (self->voiceCount == self->poly) self->voiceCount = 0; } self->currentTime += self->sampleToSec; } for (j=0; jpoly; j++) { self->tap_buffer_streams[i + j * self->bufsize] = (MYFLT)self->currentTap[j]; self->amp_buffer_streams[i + j * self->bufsize] = self->currentAmp[j]; self->dur_buffer_streams[i + j * self->bufsize] = self->currentDur[j]; } } } MYFLT * TrigBurster_getSamplesBuffer(TrigBurster *self) { return (MYFLT *)self->buffer_streams; } MYFLT * TrigBurster_getTapBuffer(TrigBurster *self) { return (MYFLT *)self->tap_buffer_streams; } MYFLT * TrigBurster_getAmpBuffer(TrigBurster *self) { return (MYFLT *)self->amp_buffer_streams; } MYFLT * TrigBurster_getDurBuffer(TrigBurster *self) { return (MYFLT *)self->dur_buffer_streams; } MYFLT * TrigBurster_getEndBuffer(TrigBurster *self) { return (MYFLT *)self->end_buffer_streams; } static void TrigBurster_setProcMode(TrigBurster *self) { self->proc_func_ptr = TrigBurster_generate_i; } static void TrigBurster_compute_next_data_frame(TrigBurster *self) { (*self->proc_func_ptr)(self); } static int TrigBurster_traverse(TrigBurster *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int TrigBurster_clear(TrigBurster *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void TrigBurster_dealloc(TrigBurster* self) { pyo_DEALLOC free(self->buffer_streams); free(self->tap_buffer_streams); free(self->amp_buffer_streams); free(self->dur_buffer_streams); free(self->end_buffer_streams); free(self->currentTap); free(self->currentAmp); free(self->currentDur); TrigBurster_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigBurster_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp; TrigBurster *self; self = (TrigBurster *)type->tp_alloc(type, 0); self->poly = 1; self->voiceCount = 0; self->time = self->a_time = 0.25; self->count = self->a_count = 10; self->expand = self->a_expand = 1.0; self->ampfade = self->a_ampfade = 1.0; self->currentCount = 0; self->targetTime = 0.0; self->currentTime = -1.0; self->flag = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigBurster_compute_next_data_frame); self->mode_func_ptr = TrigBurster_setProcMode; self->sampleToSec = 1. / self->sr; Stream_setStreamActive(self->stream, 1); static char *kwlist[] = {"input", "time", "count", "expand", "ampfade", "poly", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FIFFI, kwlist, &inputtmp, &self->time, &self->count, &self->expand, &self->ampfade, &self->poly)) Py_RETURN_NONE; INIT_INPUT_STREAM PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->poly * self->bufsize * sizeof(MYFLT)); self->tap_buffer_streams = (MYFLT *)realloc(self->tap_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT)); self->amp_buffer_streams = (MYFLT *)realloc(self->amp_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT)); self->dur_buffer_streams = (MYFLT *)realloc(self->dur_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT)); self->end_buffer_streams = (MYFLT *)realloc(self->end_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT)); for (i=0; i<(self->poly*self->bufsize); i++) { self->buffer_streams[i] = self->tap_buffer_streams[i] = self->amp_buffer_streams[i] = self->dur_buffer_streams[i] = self->end_buffer_streams[i] = 0.0; } self->currentTap = (int *)realloc(self->currentTap, self->poly * sizeof(int)); self->currentAmp = (MYFLT *)realloc(self->currentAmp, self->poly * sizeof(MYFLT)); self->currentDur = (MYFLT *)realloc(self->currentDur, self->poly * sizeof(MYFLT)); for (i=0; i<(self->poly); i++) { self->currentTap[i] = 0; self->currentAmp[i] = self->currentDur[i] = 0.0; } return (PyObject *)self; } static PyObject * TrigBurster_getServer(TrigBurster* self) { GET_SERVER }; static PyObject * TrigBurster_getStream(TrigBurster* self) { GET_STREAM }; static PyObject * TrigBurster_play(TrigBurster *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigBurster_stop(TrigBurster *self) { STOP }; static PyObject * TrigBurster_setTime(TrigBurster *self, PyObject *arg) { if (PyNumber_Check(arg)) self->time = PyFloat_AsDouble(arg); if (self->time <= 0.01) self->time = 0.01; Py_INCREF(Py_None); return Py_None; } static PyObject * TrigBurster_setCount(TrigBurster *self, PyObject *arg) { if (PyInt_Check(arg)) self->count = PyInt_AS_LONG(arg); if (self->count < 1) self->count = 1; Py_INCREF(Py_None); return Py_None; } static PyObject * TrigBurster_setExpand(TrigBurster *self, PyObject *arg) { if (PyNumber_Check(arg)) self->expand = PyFloat_AsDouble(arg); if (self->expand <= 0.1) self->expand = 0.1; Py_INCREF(Py_None); return Py_None; } static PyObject * TrigBurster_setAmpfade(TrigBurster *self, PyObject *arg) { if (PyNumber_Check(arg)) self->ampfade = PyFloat_AsDouble(arg); if (self->ampfade <= 0.1) self->ampfade = 0.1; Py_INCREF(Py_None); return Py_None; } static PyMemberDef TrigBurster_members[] = { {"server", T_OBJECT_EX, offsetof(TrigBurster, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigBurster, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(TrigBurster, input), 0, "Input sound object."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigBurster_methods[] = { {"getServer", (PyCFunction)TrigBurster_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigBurster_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigBurster_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)TrigBurster_stop, METH_NOARGS, "Stops computing."}, {"setTime", (PyCFunction)TrigBurster_setTime, METH_O, "Sets the base time of the serie."}, {"setCount", (PyCFunction)TrigBurster_setCount, METH_O, "Sets the number of trigs in the serie."}, {"setExpand", (PyCFunction)TrigBurster_setExpand, METH_O, "Sets the time's expansion factor of the serie."}, {"setAmpfade", (PyCFunction)TrigBurster_setAmpfade, METH_O, "Sets the amplitude's expansion factor of the serie."}, {NULL} /* Sentinel */ }; PyTypeObject TrigBursterType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigBurster_base", /*tp_name*/ sizeof(TrigBurster), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigBurster_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigBurster objects. Create an algorithmic beat sequence.", /* tp_doc */ (traverseproc)TrigBurster_traverse, /* tp_traverse */ (inquiry)TrigBurster_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigBurster_methods, /* tp_methods */ TrigBurster_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigBurster_new, /* tp_new */ }; /************************************************************************************************/ /* TrigBurst streamer object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD TrigBurster *mainPlayer; int chnl; int modebuffer[2]; } TrigBurst; static void TrigBurst_postprocessing_ii(TrigBurst *self) { POST_PROCESSING_II }; static void TrigBurst_postprocessing_ai(TrigBurst *self) { POST_PROCESSING_AI }; static void TrigBurst_postprocessing_ia(TrigBurst *self) { POST_PROCESSING_IA }; static void TrigBurst_postprocessing_aa(TrigBurst *self) { POST_PROCESSING_AA }; static void TrigBurst_postprocessing_ireva(TrigBurst *self) { POST_PROCESSING_IREVA }; static void TrigBurst_postprocessing_areva(TrigBurst *self) { POST_PROCESSING_AREVA }; static void TrigBurst_postprocessing_revai(TrigBurst *self) { POST_PROCESSING_REVAI }; static void TrigBurst_postprocessing_revaa(TrigBurst *self) { POST_PROCESSING_REVAA }; static void TrigBurst_postprocessing_revareva(TrigBurst *self) { POST_PROCESSING_REVAREVA }; static void TrigBurst_setProcMode(TrigBurst *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = TrigBurst_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigBurst_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigBurst_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigBurst_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigBurst_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigBurst_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigBurst_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigBurst_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigBurst_postprocessing_revareva; break; } } static void TrigBurst_compute_next_data_frame(TrigBurst *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = TrigBurster_getSamplesBuffer((TrigBurster *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int TrigBurst_traverse(TrigBurst *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int TrigBurst_clear(TrigBurst *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void TrigBurst_dealloc(TrigBurst* self) { pyo_DEALLOC TrigBurst_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigBurst_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; TrigBurst *self; self = (TrigBurst *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigBurst_compute_next_data_frame); self->mode_func_ptr = TrigBurst_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (TrigBurster *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigBurst_getServer(TrigBurst* self) { GET_SERVER }; static PyObject * TrigBurst_getStream(TrigBurst* self) { GET_STREAM }; static PyObject * TrigBurst_setMul(TrigBurst *self, PyObject *arg) { SET_MUL }; static PyObject * TrigBurst_setAdd(TrigBurst *self, PyObject *arg) { SET_ADD }; static PyObject * TrigBurst_setSub(TrigBurst *self, PyObject *arg) { SET_SUB }; static PyObject * TrigBurst_setDiv(TrigBurst *self, PyObject *arg) { SET_DIV }; static PyObject * TrigBurst_play(TrigBurst *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigBurst_out(TrigBurst *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrigBurst_stop(TrigBurst *self) { STOP }; static PyObject * TrigBurst_multiply(TrigBurst *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigBurst_inplace_multiply(TrigBurst *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigBurst_add(TrigBurst *self, PyObject *arg) { ADD }; static PyObject * TrigBurst_inplace_add(TrigBurst *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigBurst_sub(TrigBurst *self, PyObject *arg) { SUB }; static PyObject * TrigBurst_inplace_sub(TrigBurst *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigBurst_div(TrigBurst *self, PyObject *arg) { DIV }; static PyObject * TrigBurst_inplace_div(TrigBurst *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef TrigBurst_members[] = { {"server", T_OBJECT_EX, offsetof(TrigBurst, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigBurst, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(TrigBurst, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigBurst, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigBurst_methods[] = { {"getServer", (PyCFunction)TrigBurst_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigBurst_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigBurst_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrigBurst_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrigBurst_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)TrigBurst_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TrigBurst_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TrigBurst_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigBurst_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigBurst_as_number = { (binaryfunc)TrigBurst_add, /*nb_add*/ (binaryfunc)TrigBurst_sub, /*nb_subtract*/ (binaryfunc)TrigBurst_multiply, /*nb_multiply*/ (binaryfunc)TrigBurst_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigBurst_inplace_add, /*inplace_add*/ (binaryfunc)TrigBurst_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigBurst_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigBurst_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigBurstType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigBurst_base", /*tp_name*/ sizeof(TrigBurst), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigBurst_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigBurst_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigBurst objects. Reads a channel from a TrigBurster.", /* tp_doc */ (traverseproc)TrigBurst_traverse, /* tp_traverse */ (inquiry)TrigBurst_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigBurst_methods, /* tp_methods */ TrigBurst_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigBurst_new, /* tp_new */ }; /************************************************************************************************/ /* TrigBurstTapStream object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD TrigBurster *mainPlayer; int chnl; int modebuffer[2]; } TrigBurstTapStream; static void TrigBurstTapStream_postprocessing_ii(TrigBurstTapStream *self) { POST_PROCESSING_II }; static void TrigBurstTapStream_postprocessing_ai(TrigBurstTapStream *self) { POST_PROCESSING_AI }; static void TrigBurstTapStream_postprocessing_ia(TrigBurstTapStream *self) { POST_PROCESSING_IA }; static void TrigBurstTapStream_postprocessing_aa(TrigBurstTapStream *self) { POST_PROCESSING_AA }; static void TrigBurstTapStream_postprocessing_ireva(TrigBurstTapStream *self) { POST_PROCESSING_IREVA }; static void TrigBurstTapStream_postprocessing_areva(TrigBurstTapStream *self) { POST_PROCESSING_AREVA }; static void TrigBurstTapStream_postprocessing_revai(TrigBurstTapStream *self) { POST_PROCESSING_REVAI }; static void TrigBurstTapStream_postprocessing_revaa(TrigBurstTapStream *self) { POST_PROCESSING_REVAA }; static void TrigBurstTapStream_postprocessing_revareva(TrigBurstTapStream *self) { POST_PROCESSING_REVAREVA }; static void TrigBurstTapStream_setProcMode(TrigBurstTapStream *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = TrigBurstTapStream_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigBurstTapStream_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigBurstTapStream_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigBurstTapStream_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigBurstTapStream_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigBurstTapStream_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigBurstTapStream_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigBurstTapStream_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigBurstTapStream_postprocessing_revareva; break; } } static void TrigBurstTapStream_compute_next_data_frame(TrigBurstTapStream *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = TrigBurster_getTapBuffer((TrigBurster *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int TrigBurstTapStream_traverse(TrigBurstTapStream *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int TrigBurstTapStream_clear(TrigBurstTapStream *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void TrigBurstTapStream_dealloc(TrigBurstTapStream* self) { pyo_DEALLOC TrigBurstTapStream_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigBurstTapStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; TrigBurstTapStream *self; self = (TrigBurstTapStream *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigBurstTapStream_compute_next_data_frame); self->mode_func_ptr = TrigBurstTapStream_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (TrigBurster *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigBurstTapStream_getServer(TrigBurstTapStream* self) { GET_SERVER }; static PyObject * TrigBurstTapStream_getStream(TrigBurstTapStream* self) { GET_STREAM }; static PyObject * TrigBurstTapStream_setMul(TrigBurstTapStream *self, PyObject *arg) { SET_MUL }; static PyObject * TrigBurstTapStream_setAdd(TrigBurstTapStream *self, PyObject *arg) { SET_ADD }; static PyObject * TrigBurstTapStream_setSub(TrigBurstTapStream *self, PyObject *arg) { SET_SUB }; static PyObject * TrigBurstTapStream_setDiv(TrigBurstTapStream *self, PyObject *arg) { SET_DIV }; static PyObject * TrigBurstTapStream_play(TrigBurstTapStream *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigBurstTapStream_out(TrigBurstTapStream *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrigBurstTapStream_stop(TrigBurstTapStream *self) { STOP }; static PyObject * TrigBurstTapStream_multiply(TrigBurstTapStream *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigBurstTapStream_inplace_multiply(TrigBurstTapStream *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigBurstTapStream_add(TrigBurstTapStream *self, PyObject *arg) { ADD }; static PyObject * TrigBurstTapStream_inplace_add(TrigBurstTapStream *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigBurstTapStream_sub(TrigBurstTapStream *self, PyObject *arg) { SUB }; static PyObject * TrigBurstTapStream_inplace_sub(TrigBurstTapStream *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigBurstTapStream_div(TrigBurstTapStream *self, PyObject *arg) { DIV }; static PyObject * TrigBurstTapStream_inplace_div(TrigBurstTapStream *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef TrigBurstTapStream_members[] = { {"server", T_OBJECT_EX, offsetof(TrigBurstTapStream, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigBurstTapStream, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(TrigBurstTapStream, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigBurstTapStream, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigBurstTapStream_methods[] = { {"getServer", (PyCFunction)TrigBurstTapStream_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigBurstTapStream_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigBurstTapStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrigBurstTapStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrigBurstTapStream_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)TrigBurstTapStream_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TrigBurstTapStream_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TrigBurstTapStream_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigBurstTapStream_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigBurstTapStream_as_number = { (binaryfunc)TrigBurstTapStream_add, /*nb_add*/ (binaryfunc)TrigBurstTapStream_sub, /*nb_subtract*/ (binaryfunc)TrigBurstTapStream_multiply, /*nb_multiply*/ (binaryfunc)TrigBurstTapStream_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigBurstTapStream_inplace_add, /*inplace_add*/ (binaryfunc)TrigBurstTapStream_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigBurstTapStream_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigBurstTapStream_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigBurstTapStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigBurstTapStream_base", /*tp_name*/ sizeof(TrigBurstTapStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigBurstTapStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigBurstTapStream_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigBurstTapStream objects. Reads the current tap from a TrigBurster object.", /* tp_doc */ (traverseproc)TrigBurstTapStream_traverse, /* tp_traverse */ (inquiry)TrigBurstTapStream_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigBurstTapStream_methods, /* tp_methods */ TrigBurstTapStream_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigBurstTapStream_new, /* tp_new */ }; /************************************************************************************************/ /* TrigBurstAmpStream object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD TrigBurster *mainPlayer; int chnl; int modebuffer[2]; } TrigBurstAmpStream; static void TrigBurstAmpStream_postprocessing_ii(TrigBurstAmpStream *self) { POST_PROCESSING_II }; static void TrigBurstAmpStream_postprocessing_ai(TrigBurstAmpStream *self) { POST_PROCESSING_AI }; static void TrigBurstAmpStream_postprocessing_ia(TrigBurstAmpStream *self) { POST_PROCESSING_IA }; static void TrigBurstAmpStream_postprocessing_aa(TrigBurstAmpStream *self) { POST_PROCESSING_AA }; static void TrigBurstAmpStream_postprocessing_ireva(TrigBurstAmpStream *self) { POST_PROCESSING_IREVA }; static void TrigBurstAmpStream_postprocessing_areva(TrigBurstAmpStream *self) { POST_PROCESSING_AREVA }; static void TrigBurstAmpStream_postprocessing_revai(TrigBurstAmpStream *self) { POST_PROCESSING_REVAI }; static void TrigBurstAmpStream_postprocessing_revaa(TrigBurstAmpStream *self) { POST_PROCESSING_REVAA }; static void TrigBurstAmpStream_postprocessing_revareva(TrigBurstAmpStream *self) { POST_PROCESSING_REVAREVA }; static void TrigBurstAmpStream_setProcMode(TrigBurstAmpStream *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_revareva; break; } } static void TrigBurstAmpStream_compute_next_data_frame(TrigBurstAmpStream *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = TrigBurster_getAmpBuffer((TrigBurster *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int TrigBurstAmpStream_traverse(TrigBurstAmpStream *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int TrigBurstAmpStream_clear(TrigBurstAmpStream *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void TrigBurstAmpStream_dealloc(TrigBurstAmpStream* self) { pyo_DEALLOC TrigBurstAmpStream_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigBurstAmpStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; TrigBurstAmpStream *self; self = (TrigBurstAmpStream *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigBurstAmpStream_compute_next_data_frame); self->mode_func_ptr = TrigBurstAmpStream_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (TrigBurster *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigBurstAmpStream_getServer(TrigBurstAmpStream* self) { GET_SERVER }; static PyObject * TrigBurstAmpStream_getStream(TrigBurstAmpStream* self) { GET_STREAM }; static PyObject * TrigBurstAmpStream_setMul(TrigBurstAmpStream *self, PyObject *arg) { SET_MUL }; static PyObject * TrigBurstAmpStream_setAdd(TrigBurstAmpStream *self, PyObject *arg) { SET_ADD }; static PyObject * TrigBurstAmpStream_setSub(TrigBurstAmpStream *self, PyObject *arg) { SET_SUB }; static PyObject * TrigBurstAmpStream_setDiv(TrigBurstAmpStream *self, PyObject *arg) { SET_DIV }; static PyObject * TrigBurstAmpStream_play(TrigBurstAmpStream *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigBurstAmpStream_out(TrigBurstAmpStream *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrigBurstAmpStream_stop(TrigBurstAmpStream *self) { STOP }; static PyObject * TrigBurstAmpStream_multiply(TrigBurstAmpStream *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigBurstAmpStream_inplace_multiply(TrigBurstAmpStream *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigBurstAmpStream_add(TrigBurstAmpStream *self, PyObject *arg) { ADD }; static PyObject * TrigBurstAmpStream_inplace_add(TrigBurstAmpStream *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigBurstAmpStream_sub(TrigBurstAmpStream *self, PyObject *arg) { SUB }; static PyObject * TrigBurstAmpStream_inplace_sub(TrigBurstAmpStream *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigBurstAmpStream_div(TrigBurstAmpStream *self, PyObject *arg) { DIV }; static PyObject * TrigBurstAmpStream_inplace_div(TrigBurstAmpStream *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef TrigBurstAmpStream_members[] = { {"server", T_OBJECT_EX, offsetof(TrigBurstAmpStream, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigBurstAmpStream, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(TrigBurstAmpStream, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigBurstAmpStream, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigBurstAmpStream_methods[] = { {"getServer", (PyCFunction)TrigBurstAmpStream_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigBurstAmpStream_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigBurstAmpStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrigBurstAmpStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrigBurstAmpStream_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)TrigBurstAmpStream_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TrigBurstAmpStream_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TrigBurstAmpStream_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigBurstAmpStream_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigBurstAmpStream_as_number = { (binaryfunc)TrigBurstAmpStream_add, /*nb_add*/ (binaryfunc)TrigBurstAmpStream_sub, /*nb_subtract*/ (binaryfunc)TrigBurstAmpStream_multiply, /*nb_multiply*/ (binaryfunc)TrigBurstAmpStream_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigBurstAmpStream_inplace_add, /*inplace_add*/ (binaryfunc)TrigBurstAmpStream_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigBurstAmpStream_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigBurstAmpStream_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigBurstAmpStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigBurstAmpStream_base", /*tp_name*/ sizeof(TrigBurstAmpStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigBurstAmpStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigBurstAmpStream_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigBurstAmpStream objects. Reads a amplitude channel from a TrigBurster object.", /* tp_doc */ (traverseproc)TrigBurstAmpStream_traverse, /* tp_traverse */ (inquiry)TrigBurstAmpStream_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigBurstAmpStream_methods, /* tp_methods */ TrigBurstAmpStream_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigBurstAmpStream_new, /* tp_new */ }; /************************************************************************************************/ /* TrigBurstDurStream object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD TrigBurster *mainPlayer; int chnl; int modebuffer[2]; } TrigBurstDurStream; static void TrigBurstDurStream_postprocessing_ii(TrigBurstDurStream *self) { POST_PROCESSING_II }; static void TrigBurstDurStream_postprocessing_ai(TrigBurstDurStream *self) { POST_PROCESSING_AI }; static void TrigBurstDurStream_postprocessing_ia(TrigBurstDurStream *self) { POST_PROCESSING_IA }; static void TrigBurstDurStream_postprocessing_aa(TrigBurstDurStream *self) { POST_PROCESSING_AA }; static void TrigBurstDurStream_postprocessing_ireva(TrigBurstDurStream *self) { POST_PROCESSING_IREVA }; static void TrigBurstDurStream_postprocessing_areva(TrigBurstDurStream *self) { POST_PROCESSING_AREVA }; static void TrigBurstDurStream_postprocessing_revai(TrigBurstDurStream *self) { POST_PROCESSING_REVAI }; static void TrigBurstDurStream_postprocessing_revaa(TrigBurstDurStream *self) { POST_PROCESSING_REVAA }; static void TrigBurstDurStream_postprocessing_revareva(TrigBurstDurStream *self) { POST_PROCESSING_REVAREVA }; static void TrigBurstDurStream_setProcMode(TrigBurstDurStream *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = TrigBurstDurStream_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigBurstDurStream_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigBurstDurStream_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigBurstDurStream_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigBurstDurStream_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigBurstDurStream_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigBurstDurStream_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigBurstDurStream_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigBurstDurStream_postprocessing_revareva; break; } } static void TrigBurstDurStream_compute_next_data_frame(TrigBurstDurStream *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = TrigBurster_getDurBuffer((TrigBurster *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int TrigBurstDurStream_traverse(TrigBurstDurStream *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int TrigBurstDurStream_clear(TrigBurstDurStream *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void TrigBurstDurStream_dealloc(TrigBurstDurStream* self) { pyo_DEALLOC TrigBurstDurStream_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigBurstDurStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; TrigBurstDurStream *self; self = (TrigBurstDurStream *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigBurstDurStream_compute_next_data_frame); self->mode_func_ptr = TrigBurstDurStream_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (TrigBurster *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigBurstDurStream_getServer(TrigBurstDurStream* self) { GET_SERVER }; static PyObject * TrigBurstDurStream_getStream(TrigBurstDurStream* self) { GET_STREAM }; static PyObject * TrigBurstDurStream_setMul(TrigBurstDurStream *self, PyObject *arg) { SET_MUL }; static PyObject * TrigBurstDurStream_setAdd(TrigBurstDurStream *self, PyObject *arg) { SET_ADD }; static PyObject * TrigBurstDurStream_setSub(TrigBurstDurStream *self, PyObject *arg) { SET_SUB }; static PyObject * TrigBurstDurStream_setDiv(TrigBurstDurStream *self, PyObject *arg) { SET_DIV }; static PyObject * TrigBurstDurStream_play(TrigBurstDurStream *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigBurstDurStream_out(TrigBurstDurStream *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrigBurstDurStream_stop(TrigBurstDurStream *self) { STOP }; static PyObject * TrigBurstDurStream_multiply(TrigBurstDurStream *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigBurstDurStream_inplace_multiply(TrigBurstDurStream *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigBurstDurStream_add(TrigBurstDurStream *self, PyObject *arg) { ADD }; static PyObject * TrigBurstDurStream_inplace_add(TrigBurstDurStream *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigBurstDurStream_sub(TrigBurstDurStream *self, PyObject *arg) { SUB }; static PyObject * TrigBurstDurStream_inplace_sub(TrigBurstDurStream *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigBurstDurStream_div(TrigBurstDurStream *self, PyObject *arg) { DIV }; static PyObject * TrigBurstDurStream_inplace_div(TrigBurstDurStream *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef TrigBurstDurStream_members[] = { {"server", T_OBJECT_EX, offsetof(TrigBurstDurStream, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigBurstDurStream, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(TrigBurstDurStream, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigBurstDurStream, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigBurstDurStream_methods[] = { {"getServer", (PyCFunction)TrigBurstDurStream_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigBurstDurStream_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigBurstDurStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrigBurstDurStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrigBurstDurStream_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)TrigBurstDurStream_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TrigBurstDurStream_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TrigBurstDurStream_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigBurstDurStream_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigBurstDurStream_as_number = { (binaryfunc)TrigBurstDurStream_add, /*nb_add*/ (binaryfunc)TrigBurstDurStream_sub, /*nb_subtract*/ (binaryfunc)TrigBurstDurStream_multiply, /*nb_multiply*/ (binaryfunc)TrigBurstDurStream_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigBurstDurStream_inplace_add, /*inplace_add*/ (binaryfunc)TrigBurstDurStream_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigBurstDurStream_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigBurstDurStream_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigBurstDurStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigBurstDurStream_base", /*tp_name*/ sizeof(TrigBurstDurStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigBurstDurStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigBurstDurStream_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigBurstDurStream objects. Reads a duration channel from a TrigBurster object.", /* tp_doc */ (traverseproc)TrigBurstDurStream_traverse, /* tp_traverse */ (inquiry)TrigBurstDurStream_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigBurstDurStream_methods, /* tp_methods */ TrigBurstDurStream_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigBurstDurStream_new, /* tp_new */ }; /************************************************************************************************/ /* TrigBurstEndStream object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD TrigBurster *mainPlayer; int chnl; int modebuffer[2]; } TrigBurstEndStream; static void TrigBurstEndStream_postprocessing_ii(TrigBurstEndStream *self) { POST_PROCESSING_II }; static void TrigBurstEndStream_postprocessing_ai(TrigBurstEndStream *self) { POST_PROCESSING_AI }; static void TrigBurstEndStream_postprocessing_ia(TrigBurstEndStream *self) { POST_PROCESSING_IA }; static void TrigBurstEndStream_postprocessing_aa(TrigBurstEndStream *self) { POST_PROCESSING_AA }; static void TrigBurstEndStream_postprocessing_ireva(TrigBurstEndStream *self) { POST_PROCESSING_IREVA }; static void TrigBurstEndStream_postprocessing_areva(TrigBurstEndStream *self) { POST_PROCESSING_AREVA }; static void TrigBurstEndStream_postprocessing_revai(TrigBurstEndStream *self) { POST_PROCESSING_REVAI }; static void TrigBurstEndStream_postprocessing_revaa(TrigBurstEndStream *self) { POST_PROCESSING_REVAA }; static void TrigBurstEndStream_postprocessing_revareva(TrigBurstEndStream *self) { POST_PROCESSING_REVAREVA }; static void TrigBurstEndStream_setProcMode(TrigBurstEndStream *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = TrigBurstEndStream_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigBurstEndStream_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigBurstEndStream_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigBurstEndStream_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigBurstEndStream_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigBurstEndStream_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigBurstEndStream_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigBurstEndStream_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigBurstEndStream_postprocessing_revareva; break; } } static void TrigBurstEndStream_compute_next_data_frame(TrigBurstEndStream *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = TrigBurster_getEndBuffer((TrigBurster *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int TrigBurstEndStream_traverse(TrigBurstEndStream *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int TrigBurstEndStream_clear(TrigBurstEndStream *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void TrigBurstEndStream_dealloc(TrigBurstEndStream* self) { pyo_DEALLOC TrigBurstEndStream_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigBurstEndStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL; TrigBurstEndStream *self; self = (TrigBurstEndStream *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigBurstEndStream_compute_next_data_frame); self->mode_func_ptr = TrigBurstEndStream_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (TrigBurster *)maintmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigBurstEndStream_getServer(TrigBurstEndStream* self) { GET_SERVER }; static PyObject * TrigBurstEndStream_getStream(TrigBurstEndStream* self) { GET_STREAM }; static PyObject * TrigBurstEndStream_setMul(TrigBurstEndStream *self, PyObject *arg) { SET_MUL }; static PyObject * TrigBurstEndStream_setAdd(TrigBurstEndStream *self, PyObject *arg) { SET_ADD }; static PyObject * TrigBurstEndStream_setSub(TrigBurstEndStream *self, PyObject *arg) { SET_SUB }; static PyObject * TrigBurstEndStream_setDiv(TrigBurstEndStream *self, PyObject *arg) { SET_DIV }; static PyObject * TrigBurstEndStream_play(TrigBurstEndStream *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigBurstEndStream_out(TrigBurstEndStream *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrigBurstEndStream_stop(TrigBurstEndStream *self) { STOP }; static PyObject * TrigBurstEndStream_multiply(TrigBurstEndStream *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigBurstEndStream_inplace_multiply(TrigBurstEndStream *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigBurstEndStream_add(TrigBurstEndStream *self, PyObject *arg) { ADD }; static PyObject * TrigBurstEndStream_inplace_add(TrigBurstEndStream *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigBurstEndStream_sub(TrigBurstEndStream *self, PyObject *arg) { SUB }; static PyObject * TrigBurstEndStream_inplace_sub(TrigBurstEndStream *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigBurstEndStream_div(TrigBurstEndStream *self, PyObject *arg) { DIV }; static PyObject * TrigBurstEndStream_inplace_div(TrigBurstEndStream *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef TrigBurstEndStream_members[] = { {"server", T_OBJECT_EX, offsetof(TrigBurstEndStream, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigBurstEndStream, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(TrigBurstEndStream, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigBurstEndStream, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigBurstEndStream_methods[] = { {"getServer", (PyCFunction)TrigBurstEndStream_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigBurstEndStream_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigBurstEndStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrigBurstEndStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrigBurstEndStream_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)TrigBurstEndStream_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TrigBurstEndStream_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TrigBurstEndStream_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigBurstEndStream_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigBurstEndStream_as_number = { (binaryfunc)TrigBurstEndStream_add, /*nb_add*/ (binaryfunc)TrigBurstEndStream_sub, /*nb_subtract*/ (binaryfunc)TrigBurstEndStream_multiply, /*nb_multiply*/ (binaryfunc)TrigBurstEndStream_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigBurstEndStream_inplace_add, /*inplace_add*/ (binaryfunc)TrigBurstEndStream_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigBurstEndStream_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigBurstEndStream_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigBurstEndStreamType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigBurstEndStream_base", /*tp_name*/ sizeof(TrigBurstEndStream), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigBurstEndStream_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigBurstEndStream_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigBurstEndStream objects. Reads a duration channel from a TrigBurster object.", /* tp_doc */ (traverseproc)TrigBurstEndStream_traverse, /* tp_traverse */ (inquiry)TrigBurstEndStream_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigBurstEndStream_methods, /* tp_methods */ TrigBurstEndStream_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigBurstEndStream_new, /* tp_new */ };pyo/src/objects/inputmodule.c0000644000175000017500000002546312652732202015621 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD int chnl; int modebuffer[2]; } Input; static void Input_postprocessing_ii(Input *self) { POST_PROCESSING_II }; static void Input_postprocessing_ai(Input *self) { POST_PROCESSING_AI }; static void Input_postprocessing_ia(Input *self) { POST_PROCESSING_IA }; static void Input_postprocessing_aa(Input *self) { POST_PROCESSING_AA }; static void Input_postprocessing_ireva(Input *self) { POST_PROCESSING_IREVA }; static void Input_postprocessing_areva(Input *self) { POST_PROCESSING_AREVA }; static void Input_postprocessing_revai(Input *self) { POST_PROCESSING_REVAI }; static void Input_postprocessing_revaa(Input *self) { POST_PROCESSING_REVAA }; static void Input_postprocessing_revareva(Input *self) { POST_PROCESSING_REVAREVA }; static void Input_setProcMode(Input *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Input_postprocessing_ii; break; case 1: self->muladd_func_ptr = Input_postprocessing_ai; break; case 2: self->muladd_func_ptr = Input_postprocessing_revai; break; case 10: self->muladd_func_ptr = Input_postprocessing_ia; break; case 11: self->muladd_func_ptr = Input_postprocessing_aa; break; case 12: self->muladd_func_ptr = Input_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Input_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Input_postprocessing_areva; break; case 22: self->muladd_func_ptr = Input_postprocessing_revareva; break; } } static void Input_compute_next_data_frame(Input *self) { int i; MYFLT *tmp; tmp = Server_getInputBuffer((Server *)self->server); for (i=0; ibufsize*self->ichnls; i++) { if ((i % self->ichnls) == self->chnl) self->data[(int)(i/self->ichnls)] = tmp[i]; } (*self->muladd_func_ptr)(self); } static int Input_traverse(Input *self, visitproc visit, void *arg) { pyo_VISIT return 0; } static int Input_clear(Input *self) { pyo_CLEAR return 0; } static void Input_dealloc(Input* self) { pyo_DEALLOC Input_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Input_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *multmp=NULL, *addtmp=NULL; Input *self; self = (Input *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Input_compute_next_data_frame); self->mode_func_ptr = Input_setProcMode; static char *kwlist[] = {"chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iOO", kwlist, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Input_getServer(Input* self) { GET_SERVER }; static PyObject * Input_getStream(Input* self) { GET_STREAM }; static PyObject * Input_setMul(Input *self, PyObject *arg) { SET_MUL }; static PyObject * Input_setAdd(Input *self, PyObject *arg) { SET_ADD }; static PyObject * Input_setSub(Input *self, PyObject *arg) { SET_SUB }; static PyObject * Input_setDiv(Input *self, PyObject *arg) { SET_DIV }; static PyObject * Input_play(Input *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Input_out(Input *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Input_stop(Input *self) { STOP }; static PyObject * Input_multiply(Input *self, PyObject *arg) { MULTIPLY }; static PyObject * Input_inplace_multiply(Input *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Input_add(Input *self, PyObject *arg) { ADD }; static PyObject * Input_inplace_add(Input *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Input_sub(Input *self, PyObject *arg) { SUB }; static PyObject * Input_inplace_sub(Input *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Input_div(Input *self, PyObject *arg) { DIV }; static PyObject * Input_inplace_div(Input *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Input_members[] = { {"server", T_OBJECT_EX, offsetof(Input, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Input, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Input, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Input, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Input_methods[] = { {"getServer", (PyCFunction)Input_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Input_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Input_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Input_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Input_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Input_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Input_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Input_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Input_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Input_as_number = { (binaryfunc)Input_add, /*nb_add*/ (binaryfunc)Input_sub, /*nb_subtract*/ (binaryfunc)Input_multiply, /*nb_multiply*/ (binaryfunc)Input_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Input_inplace_add, /*inplace_add*/ (binaryfunc)Input_inplace_sub, /*inplace_subtract*/ (binaryfunc)Input_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Input_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject InputType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Input_base", /*tp_name*/ sizeof(Input), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Input_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Input_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Input objects. Retreive audio from an input channel.", /* tp_doc */ (traverseproc)Input_traverse, /* tp_traverse */ (inquiry)Input_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Input_methods, /* tp_methods */ Input_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Input_new, /* tp_new */ }; pyo/src/objects/oscmodule.c0000644000175000017500000017141012652732202015240 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "lo/lo.h" static void error(int num, const char *msg, const char *path) { printf("liblo server error %d in path %s: %s\n", num, path, msg); } /* main OSC receiver */ typedef struct { pyo_audio_HEAD lo_server osc_server; int port; PyObject *dict; PyObject *address_path; } OscReceiver; int OscReceiver_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { OscReceiver *self = user_data; PyDict_SetItem(self->dict, PyString_FromString(path), PyFloat_FromDouble(argv[0]->FLOAT_VALUE)); return 0; } MYFLT OscReceiver_getValue(OscReceiver *self, PyObject *path) { PyObject *tmp; tmp = PyDict_GetItem(self->dict, path); return PyFloat_AsDouble(tmp); } static void OscReceiver_compute_next_data_frame(OscReceiver *self) { while (lo_server_recv_noblock(self->osc_server, 0) != 0) {}; } static int OscReceiver_traverse(OscReceiver *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->dict); Py_VISIT(self->address_path); return 0; } static int OscReceiver_clear(OscReceiver *self) { pyo_CLEAR Py_CLEAR(self->dict); Py_CLEAR(self->address_path); return 0; } static void OscReceiver_dealloc(OscReceiver* self) { lo_server_free(self->osc_server); pyo_DEALLOC OscReceiver_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * OscReceiver_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *pathtmp; OscReceiver *self; self = (OscReceiver *)type->tp_alloc(type, 0); INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, OscReceiver_compute_next_data_frame); static char *kwlist[] = {"port", "address", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "iO", kwlist, &self->port, &pathtmp)) Py_RETURN_NONE; PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->dict = PyDict_New(); if (PyList_Check(pathtmp)) { Py_INCREF(pathtmp); Py_XDECREF(self->address_path); self->address_path = pathtmp; } else { PyErr_SetString(PyExc_TypeError, "The OscReceiver_base 'address' attributes must be a list of strings and/or unicodes."); Py_RETURN_NONE; } int lsize = PyList_Size(self->address_path); for (i=0; idict, PyList_GET_ITEM(self->address_path, i), PyFloat_FromDouble(0.)); } char buf[20]; sprintf(buf, "%i", self->port); self->osc_server = lo_server_new(buf, error); lo_server_add_method(self->osc_server, NULL, TYPE_F, OscReceiver_handler, self); return (PyObject *)self; } static PyObject * OscReceiver_addAddress(OscReceiver *self, PyObject *arg) { int i; if (PyString_Check(arg) || PyUnicode_Check(arg)) { PyDict_SetItem(self->dict, arg, PyFloat_FromDouble(0.)); } else if (PyList_Check(arg)) { Py_ssize_t lsize = PyList_Size(arg); for (i=0; idict, PyList_GET_ITEM(arg, i), PyFloat_FromDouble(0.)); } } Py_INCREF(Py_None); return Py_None; } static PyObject * OscReceiver_delAddress(OscReceiver *self, PyObject *arg) { int i; if (PyString_Check(arg) || PyUnicode_Check(arg)) { PyDict_DelItem(self->dict, arg); } else if (PyList_Check(arg)) { Py_ssize_t lsize = PyList_Size(arg); for (i=0; idict, PyList_GET_ITEM(arg, i)); } } Py_INCREF(Py_None); return Py_None; } static PyObject * OscReceiver_setValue(OscReceiver *self, PyObject *args, PyObject *kwds) { PyObject *address, *value; static char *kwlist[] = {"address", "value", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &address, &value)) Py_RETURN_NONE; PyDict_SetItem(self->dict, address, value); Py_RETURN_NONE; } static PyObject * OscReceiver_getServer(OscReceiver* self) { GET_SERVER }; static PyObject * OscReceiver_getStream(OscReceiver* self) { GET_STREAM }; static PyMemberDef OscReceiver_members[] = { {"server", T_OBJECT_EX, offsetof(OscReceiver, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(OscReceiver, stream), 0, "Stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef OscReceiver_methods[] = { {"getServer", (PyCFunction)OscReceiver_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)OscReceiver_getStream, METH_NOARGS, "Returns stream object."}, {"addAddress", (PyCFunction)OscReceiver_addAddress, METH_O, "Add a new address to the dictionary."}, {"delAddress", (PyCFunction)OscReceiver_delAddress, METH_O, "Remove an address from the dictionary."}, {"setValue", (PyCFunction)OscReceiver_setValue, METH_VARARGS|METH_KEYWORDS, "Sets value for a specified address."}, {NULL} /* Sentinel */ }; PyTypeObject OscReceiverType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.OscReceiver_base", /*tp_name*/ sizeof(OscReceiver), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)OscReceiver_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "OscReceiver objects. Receive values via Open Sound Control protocol.", /* tp_doc */ (traverseproc)OscReceiver_traverse, /* tp_traverse */ (inquiry)OscReceiver_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ OscReceiver_methods, /* tp_methods */ OscReceiver_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ OscReceiver_new, /* tp_new */ }; /* OSC receiver stream object */ typedef struct { pyo_audio_HEAD PyObject *input; PyObject *address_path; MYFLT value; MYFLT factor; int interpolation; int modebuffer[2]; } OscReceive; static void OscReceive_postprocessing_ii(OscReceive *self) { POST_PROCESSING_II }; static void OscReceive_postprocessing_ai(OscReceive *self) { POST_PROCESSING_AI }; static void OscReceive_postprocessing_ia(OscReceive *self) { POST_PROCESSING_IA }; static void OscReceive_postprocessing_aa(OscReceive *self) { POST_PROCESSING_AA }; static void OscReceive_postprocessing_ireva(OscReceive *self) { POST_PROCESSING_IREVA }; static void OscReceive_postprocessing_areva(OscReceive *self) { POST_PROCESSING_AREVA }; static void OscReceive_postprocessing_revai(OscReceive *self) { POST_PROCESSING_REVAI }; static void OscReceive_postprocessing_revaa(OscReceive *self) { POST_PROCESSING_REVAA }; static void OscReceive_postprocessing_revareva(OscReceive *self) { POST_PROCESSING_REVAREVA }; static void OscReceive_setProcMode(OscReceive *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = OscReceive_postprocessing_ii; break; case 1: self->muladd_func_ptr = OscReceive_postprocessing_ai; break; case 2: self->muladd_func_ptr = OscReceive_postprocessing_revai; break; case 10: self->muladd_func_ptr = OscReceive_postprocessing_ia; break; case 11: self->muladd_func_ptr = OscReceive_postprocessing_aa; break; case 12: self->muladd_func_ptr = OscReceive_postprocessing_revaa; break; case 20: self->muladd_func_ptr = OscReceive_postprocessing_ireva; break; case 21: self->muladd_func_ptr = OscReceive_postprocessing_areva; break; case 22: self->muladd_func_ptr = OscReceive_postprocessing_revareva; break; } } static void OscReceive_compute_next_data_frame(OscReceive *self) { int i; MYFLT val = OscReceiver_getValue((OscReceiver *)self->input, self->address_path); if (self->interpolation == 1) { for (i=0; ibufsize; i++) { self->data[i] = self->value = self->value + (val - self->value) * self->factor; } } else { for (i=0; ibufsize; i++) { self->data[i] = self->value = val; } } (*self->muladd_func_ptr)(self); } static int OscReceive_traverse(OscReceive *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->address_path); return 0; } static int OscReceive_clear(OscReceive *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->address_path); return 0; } static void OscReceive_dealloc(OscReceive* self) { pyo_DEALLOC OscReceive_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * OscReceive_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp=NULL, *pathtmp=NULL, *multmp=NULL, *addtmp=NULL;; OscReceive *self; self = (OscReceive *)type->tp_alloc(type, 0); self->value = 0.; self->interpolation = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON self->factor = 1. / (0.01 * self->sr); Stream_setFunctionPtr(self->stream, OscReceive_compute_next_data_frame); self->mode_func_ptr = OscReceive_setProcMode; static char *kwlist[] = {"input", "address", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &inputtmp, &pathtmp, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->input); Py_INCREF(inputtmp); self->input = inputtmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (!PyString_Check(pathtmp) && !PyUnicode_Check(pathtmp)) { PyErr_SetString(PyExc_TypeError, "The address attributes must be a string or a unicode."); Py_RETURN_NONE; } Py_INCREF(pathtmp); Py_XDECREF(self->address_path); self->address_path = pathtmp; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * OscReceive_setInterpolation(OscReceive *self, PyObject *arg) { ASSERT_ARG_NOT_NULL self->interpolation = PyInt_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * OscReceive_getServer(OscReceive* self) { GET_SERVER }; static PyObject * OscReceive_getStream(OscReceive* self) { GET_STREAM }; static PyObject * OscReceive_setMul(OscReceive *self, PyObject *arg) { SET_MUL }; static PyObject * OscReceive_setAdd(OscReceive *self, PyObject *arg) { SET_ADD }; static PyObject * OscReceive_setSub(OscReceive *self, PyObject *arg) { SET_SUB }; static PyObject * OscReceive_setDiv(OscReceive *self, PyObject *arg) { SET_DIV }; static PyObject * OscReceive_play(OscReceive *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * OscReceive_stop(OscReceive *self) { STOP }; static PyObject * OscReceive_multiply(OscReceive *self, PyObject *arg) { MULTIPLY }; static PyObject * OscReceive_inplace_multiply(OscReceive *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * OscReceive_add(OscReceive *self, PyObject *arg) { ADD }; static PyObject * OscReceive_inplace_add(OscReceive *self, PyObject *arg) { INPLACE_ADD }; static PyObject * OscReceive_sub(OscReceive *self, PyObject *arg) { SUB }; static PyObject * OscReceive_inplace_sub(OscReceive *self, PyObject *arg) { INPLACE_SUB }; static PyObject * OscReceive_div(OscReceive *self, PyObject *arg) { DIV }; static PyObject * OscReceive_inplace_div(OscReceive *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef OscReceive_members[] = { {"server", T_OBJECT_EX, offsetof(OscReceive, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(OscReceive, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(OscReceive, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(OscReceive, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef OscReceive_methods[] = { {"getServer", (PyCFunction)OscReceive_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)OscReceive_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)OscReceive_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)OscReceive_stop, METH_NOARGS, "Stops computing."}, {"setInterpolation", (PyCFunction)OscReceive_setInterpolation, METH_O, "Sets interpolation on or off."}, {"setMul", (PyCFunction)OscReceive_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)OscReceive_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)OscReceive_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)OscReceive_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods OscReceive_as_number = { (binaryfunc)OscReceive_add, /*nb_add*/ (binaryfunc)OscReceive_sub, /*nb_subtract*/ (binaryfunc)OscReceive_multiply, /*nb_multiply*/ (binaryfunc)OscReceive_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)OscReceive_inplace_add, /*inplace_add*/ (binaryfunc)OscReceive_inplace_sub, /*inplace_subtract*/ (binaryfunc)OscReceive_inplace_multiply, /*inplace_multiply*/ (binaryfunc)OscReceive_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject OscReceiveType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.OscReceive_base", /*tp_name*/ sizeof(OscReceive), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)OscReceive_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &OscReceive_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "OscReceive objects. Receive values via Open Sound Control protocol.", /* tp_doc */ (traverseproc)OscReceive_traverse, /* tp_traverse */ (inquiry)OscReceive_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ OscReceive_methods, /* tp_methods */ OscReceive_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ OscReceive_new, /* tp_new */ }; /* OSC send object */ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *address_path; lo_address address; char *host; int port; int count; int bufrate; } OscSend; static void OscSend_compute_next_data_frame(OscSend *self) { char *path=NULL; self->count++; if (self->count >= self->bufrate) { self->count = 0; MYFLT *in = Stream_getData((Stream *)self->input_stream); float value = (float)in[0]; if (PyString_Check(self->address_path)) path = PyString_AsString(self->address_path); else path = PyString_AsString(PyUnicode_AsASCIIString(self->address_path)); if (lo_send(self->address, path, "f", value) == -1) { printf("OSC error %d: %s\n", lo_address_errno(self->address), lo_address_errstr(self->address)); } } } static int OscSend_traverse(OscSend *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->address_path); Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int OscSend_clear(OscSend *self) { pyo_CLEAR Py_CLEAR(self->address_path); Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void OscSend_dealloc(OscSend* self) { pyo_DEALLOC OscSend_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * OscSend_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *pathtmp; OscSend *self; self = (OscSend *)type->tp_alloc(type, 0); self->host = NULL; self->count = 0; self->bufrate = 1; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, OscSend_compute_next_data_frame); static char *kwlist[] = {"input", "port", "address", "host", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OiO|s", kwlist, &inputtmp, &self->port, &pathtmp, &self->host)) Py_RETURN_NONE; INIT_INPUT_STREAM PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (!PyString_Check(pathtmp) && !PyUnicode_Check(pathtmp)) { PyErr_SetString(PyExc_TypeError, "The address attributes must be a string or a unicode."); Py_RETURN_NONE; } Py_INCREF(pathtmp); Py_XDECREF(self->address_path); self->address_path = pathtmp; char buf[20]; sprintf(buf, "%i", self->port); self->address = lo_address_new(self->host, buf); return (PyObject *)self; } static PyObject * OscSend_setBufferRate(OscSend *self, PyObject *arg) { ASSERT_ARG_NOT_NULL self->bufrate = PyInt_AsLong(arg); if (self->bufrate < 1) self->bufrate = 1; Py_INCREF(Py_None); return Py_None; } static PyObject * OscSend_getServer(OscSend* self) { GET_SERVER }; static PyObject * OscSend_getStream(OscSend* self) { GET_STREAM }; static PyObject * OscSend_play(OscSend *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * OscSend_stop(OscSend *self) { STOP }; static PyMemberDef OscSend_members[] = { {"server", T_OBJECT_EX, offsetof(OscSend, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(OscSend, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(OscSend, input), 0, "Input sound object."}, {NULL} /* Sentinel */ }; static PyMethodDef OscSend_methods[] = { {"getServer", (PyCFunction)OscSend_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)OscSend_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)OscSend_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)OscSend_stop, METH_NOARGS, "Stops computing."}, {"setBufferRate", (PyCFunction)OscSend_setBufferRate, METH_O, "Set how many buffers to wait before sending a new value."}, {NULL} /* Sentinel */ }; PyTypeObject OscSendType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.OscSend_base", /*tp_name*/ sizeof(OscSend), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)OscSend_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "OscSend objects. Send values via Open Sound Control protocol.", /* tp_doc */ (traverseproc)OscSend_traverse, /* tp_traverse */ (inquiry)OscSend_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ OscSend_methods, /* tp_methods */ OscSend_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ OscSend_new, /* tp_new */ }; /* OscDataSend object */ typedef struct { pyo_audio_HEAD PyObject *value; PyObject *address_path; lo_address address; char *host; char *types; int port; int something_to_send; int num_items; } OscDataSend; static void OscDataSend_compute_next_data_frame(OscDataSend *self) { int i, j = 0; Py_ssize_t blobsize = 0; PyObject *datalist = NULL; char *blobdata = NULL; uint8_t midi[4]; lo_blob *blob = NULL; char *path=NULL; lo_message *msg; if (self->something_to_send == 1) { if (PyString_Check(self->address_path)) path = PyString_AsString(self->address_path); else path = PyString_AsString(PyUnicode_AsASCIIString(self->address_path)); msg = lo_message_new(); for (i=0; inum_items; i++) { switch (self->types[i]) { case LO_INT32: lo_message_add_int32(msg, PyInt_AS_LONG(PyList_GET_ITEM(self->value, i))); break; case LO_INT64: lo_message_add_int64(msg, (long)PyLong_AsLong(PyList_GET_ITEM(self->value, i))); break; case LO_FLOAT: lo_message_add_float(msg, (float)PyFloat_AsDouble(PyList_GET_ITEM(self->value, i))); break; case LO_DOUBLE: lo_message_add_double(msg, (double)PyFloat_AsDouble(PyList_GET_ITEM(self->value, i))); break; case LO_STRING: lo_message_add_string(msg, PyString_AsString(PyList_GET_ITEM(self->value, i))); break; case LO_CHAR: lo_message_add_char(msg, (char)PyString_AsString(PyList_GET_ITEM(self->value, i))[0]); break; case LO_BLOB: datalist = PyList_GET_ITEM(self->value, i); blobsize = PyList_Size(datalist); blobdata = (char *)malloc(blobsize * sizeof(char)); for (j=0; jvalue, i); for (j=0; j<4; j++) { midi[j] = (uint8_t)PyInt_AS_LONG(PyList_GET_ITEM(datalist, j)); } lo_message_add_midi(msg, midi); break; case LO_NIL: lo_message_add_nil(msg); break; case LO_TRUE: lo_message_add_true(msg); break; case LO_FALSE: lo_message_add_false(msg); break; default: break; } } if (lo_send_message(self->address, path, msg) == -1) { printf("OSC error %d: %s\n", lo_address_errno(self->address), lo_address_errstr(self->address)); } self->something_to_send = 0; lo_message_free(msg); if (blob != NULL) lo_blob_free(blob); if (blobdata != NULL) free(blobdata); } } static int OscDataSend_traverse(OscDataSend *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->value); Py_VISIT(self->address_path); return 0; } static int OscDataSend_clear(OscDataSend *self) { pyo_CLEAR Py_CLEAR(self->value); Py_CLEAR(self->address_path); return 0; } static void OscDataSend_dealloc(OscDataSend* self) { pyo_DEALLOC OscDataSend_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * OscDataSend_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *pathtmp; OscDataSend *self; self = (OscDataSend *)type->tp_alloc(type, 0); self->host = NULL; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, OscDataSend_compute_next_data_frame); static char *kwlist[] = {"types", "port", "address", "host", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "siO|s", kwlist, &self->types, &self->port, &pathtmp, &self->host)) Py_RETURN_NONE; PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (!PyString_Check(pathtmp) && !PyUnicode_Check(pathtmp)) { PyErr_SetString(PyExc_TypeError, "The address attributes must be of type string or unicode."); Py_RETURN_NONE; } self->num_items = strlen(self->types); Py_INCREF(pathtmp); Py_XDECREF(self->address_path); self->address_path = pathtmp; char buf[20]; sprintf(buf, "%i", self->port); self->address = lo_address_new(self->host, buf); return (PyObject *)self; } static PyObject * OscDataSend_getServer(OscDataSend* self) { GET_SERVER }; static PyObject * OscDataSend_getStream(OscDataSend* self) { GET_STREAM }; static PyObject * OscDataSend_play(OscDataSend *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * OscDataSend_stop(OscDataSend *self) { STOP }; static PyObject * OscDataSend_send(OscDataSend *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL if (PyList_Check(arg)) { tmp = arg; Py_XDECREF(self->value); Py_INCREF(tmp); self->value = tmp; self->something_to_send = 1; } else printf("OscDataSend: argument to send() method must be a list of values.\n"); Py_INCREF(Py_None); return Py_None; } static PyMemberDef OscDataSend_members[] = { {"server", T_OBJECT_EX, offsetof(OscDataSend, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(OscDataSend, stream), 0, "Stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef OscDataSend_methods[] = { {"getServer", (PyCFunction)OscDataSend_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)OscDataSend_getStream, METH_NOARGS, "Returns stream object."}, {"send", (PyCFunction)OscDataSend_send, METH_O, "Sets values to be sent."}, {"play", (PyCFunction)OscDataSend_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)OscDataSend_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject OscDataSendType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.OscDataSend_base", /*tp_name*/ sizeof(OscDataSend), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)OscDataSend_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "OscDataSend objects. Send data values via Open Sound Control protocol.", /* tp_doc */ (traverseproc)OscDataSend_traverse, /* tp_traverse */ (inquiry)OscDataSend_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ OscDataSend_methods, /* tp_methods */ OscDataSend_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ OscDataSend_new, /* tp_new */ }; /* main OscDataReceive */ typedef struct { pyo_audio_HEAD lo_server osc_server; PyObject *address_path; PyObject *callable; int port; } OscDataReceive; int OscDataReceive_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { OscDataReceive *self = user_data; PyObject *tup, *result=NULL, *address=NULL; lo_blob *blob = NULL; char *blobdata = NULL; uint32_t blobsize = 0; PyObject *charlist = NULL; tup = PyTuple_New(argc+1); int i, ok = 0, j = 0; Py_ssize_t lsize = PyList_Size(self->address_path); for (i=0; iaddress_path, i))) address = PyList_GET_ITEM(self->address_path, i); else address = PyUnicode_AsASCIIString(PyList_GET_ITEM(self->address_path, i)); if (lo_pattern_match(path, PyString_AsString(address))) { ok = 1; break; } } if (ok) { PyTuple_SET_ITEM(tup, 0, PyString_FromString(path)); for (i=0; ii)); break; case LO_INT64: PyTuple_SET_ITEM(tup, i+1, PyLong_FromLong(argv[i]->h)); break; case LO_FLOAT: PyTuple_SET_ITEM(tup, i+1, PyFloat_FromDouble(argv[i]->f)); break; case LO_DOUBLE: PyTuple_SET_ITEM(tup, i+1, PyFloat_FromDouble(argv[i]->d)); break; case LO_STRING: PyTuple_SET_ITEM(tup, i+1, PyString_FromString(&argv[i]->s)); break; case LO_CHAR: PyTuple_SET_ITEM(tup, i+1, PyString_FromFormat("%c", argv[i]->c)); break; case LO_BLOB: blob = (lo_blob)argv[i]; blobsize = lo_blob_datasize(blob); blobdata = lo_blob_dataptr(blob); charlist = PyList_New(blobsize); for (j=0; jm[j])); } PyTuple_SET_ITEM(tup, i+1, charlist); break; case LO_NIL: Py_INCREF(Py_None); PyTuple_SET_ITEM(tup, i+1, Py_None); break; case LO_TRUE: Py_INCREF(Py_True); PyTuple_SET_ITEM(tup, i+1, Py_True); break; case LO_FALSE: Py_INCREF(Py_False); PyTuple_SET_ITEM(tup, i+1, Py_False); break; default: break; } } result = PyObject_Call(self->callable, tup, NULL); if (result == NULL) PyErr_Print(); } Py_XDECREF(tup); Py_XDECREF(result); Py_XDECREF(charlist); Py_XDECREF(address); return 0; } static void OscDataReceive_compute_next_data_frame(OscDataReceive *self) { while (lo_server_recv_noblock(self->osc_server, 0) != 0) {}; } static int OscDataReceive_traverse(OscDataReceive *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->address_path); Py_VISIT(self->callable); return 0; } static int OscDataReceive_clear(OscDataReceive *self) { pyo_CLEAR Py_CLEAR(self->address_path); Py_CLEAR(self->callable); return 0; } static void OscDataReceive_dealloc(OscDataReceive* self) { lo_server_free(self->osc_server); pyo_DEALLOC OscDataReceive_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * OscDataReceive_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *pathtmp, *calltmp; OscDataReceive *self; self = (OscDataReceive *)type->tp_alloc(type, 0); INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, OscDataReceive_compute_next_data_frame); static char *kwlist[] = {"port", "address", "callable", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "iOO", kwlist, &self->port, &pathtmp, &calltmp)) Py_RETURN_NONE; PyObject_CallMethod(self->server, "addStream", "O", self->stream); Py_XDECREF(self->callable); self->callable = calltmp; if (PyList_Check(pathtmp)) { Py_INCREF(pathtmp); Py_XDECREF(self->address_path); self->address_path = pathtmp; } else { PyErr_SetString(PyExc_TypeError, "The address attributes must be a list of strings and/or unicodes."); Py_RETURN_NONE; } char buf[20]; sprintf(buf, "%i", self->port); self->osc_server = lo_server_new(buf, error); lo_server_add_method(self->osc_server, NULL, NULL, OscDataReceive_handler, self); return (PyObject *)self; } static PyObject * OscDataReceive_getServer(OscDataReceive* self) { GET_SERVER }; static PyObject * OscDataReceive_getStream(OscDataReceive* self) { GET_STREAM }; static PyObject * OscDataReceive_play(OscDataReceive *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * OscDataReceive_stop(OscDataReceive *self) { STOP }; static PyObject * OscDataReceive_addAddress(OscDataReceive *self, PyObject *arg) { int i; if (arg != NULL) { if (PyString_Check(arg) || PyUnicode_Check(arg)) PyList_Append(self->address_path, arg); else if (PyList_Check(arg)) { Py_ssize_t len = PyList_Size(arg); for (i=0; iaddress_path, PyList_GET_ITEM(arg, i)); } } } Py_INCREF(Py_None); return Py_None; } static PyObject * OscDataReceive_delAddress(OscDataReceive *self, PyObject *arg) { if (arg != NULL) { if (PyInt_Check(arg)) { PySequence_DelItem(self->address_path, PyInt_AsLong(arg)); } } Py_INCREF(Py_None); return Py_None; } static PyMemberDef OscDataReceive_members[] = { {"server", T_OBJECT_EX, offsetof(OscDataReceive, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(OscDataReceive, stream), 0, "Stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef OscDataReceive_methods[] = { {"getServer", (PyCFunction)OscDataReceive_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)OscDataReceive_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)OscDataReceive_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)OscDataReceive_stop, METH_NOARGS, "Stops computing."}, {"addAddress", (PyCFunction)OscDataReceive_addAddress, METH_O, "Add new paths to the object."}, {"delAddress", (PyCFunction)OscDataReceive_delAddress, METH_O, "Remove path from the object."}, {NULL} /* Sentinel */ }; PyTypeObject OscDataReceiveType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.OscDataReceive_base", /*tp_name*/ sizeof(OscDataReceive), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)OscDataReceive_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "OscDataReceive objects. Receive values via Open Sound Control protocol.", /* tp_doc */ (traverseproc)OscDataReceive_traverse, /* tp_traverse */ (inquiry)OscDataReceive_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ OscDataReceive_methods, /* tp_methods */ OscDataReceive_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ OscDataReceive_new, /* tp_new */ }; /* main OSC list receiver */ typedef struct { pyo_audio_HEAD lo_server osc_server; PyObject *dict; PyObject *address_path; int port; int num; } OscListReceiver; int OscListReceiver_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { OscListReceiver *self = user_data; int i; PyObject *flist; flist = PyList_New(self->num); for (i=0; inum; i++) { PyList_SET_ITEM(flist, i, PyFloat_FromDouble(argv[i]->FLOAT_VALUE)); } PyDict_SetItem(self->dict, PyString_FromString(path), flist); return 0; } PyObject * OscListReceiver_getValue(OscListReceiver *self, PyObject *path) { PyObject *tmp; tmp = PyDict_GetItem(self->dict, path); return tmp; } static void OscListReceiver_compute_next_data_frame(OscListReceiver *self) { while (lo_server_recv_noblock(self->osc_server, 0) != 0) {}; } static int OscListReceiver_traverse(OscListReceiver *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->dict); Py_VISIT(self->address_path); return 0; } static int OscListReceiver_clear(OscListReceiver *self) { pyo_CLEAR Py_CLEAR(self->dict); Py_CLEAR(self->address_path); return 0; } static void OscListReceiver_dealloc(OscListReceiver* self) { lo_server_free(self->osc_server); pyo_DEALLOC OscListReceiver_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * OscListReceiver_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, j; PyObject *pathtmp, *flist; OscListReceiver *self; self = (OscListReceiver *)type->tp_alloc(type, 0); self->num = 8; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, OscListReceiver_compute_next_data_frame); static char *kwlist[] = {"port", "address", "num", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "iO|i", kwlist, &self->port, &pathtmp, &self->num)) Py_RETURN_NONE; PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->dict = PyDict_New(); if (PyList_Check(pathtmp)) { Py_INCREF(pathtmp); Py_XDECREF(self->address_path); self->address_path = pathtmp; } else { PyErr_SetString(PyExc_TypeError, "The address attributes must be a list of strings and/or unicodes."); Py_RETURN_NONE; } int lsize = PyList_Size(self->address_path); for (i=0; inum); for (j=0; jnum; j++) { PyList_SET_ITEM(flist, j, PyFloat_FromDouble(0.)); } PyDict_SetItem(self->dict, PyList_GET_ITEM(self->address_path, i), flist); } char buf[20]; sprintf(buf, "%i", self->port); self->osc_server = lo_server_new(buf, error); lo_server_add_method(self->osc_server, NULL, NULL, OscListReceiver_handler, self); return (PyObject *)self; } static PyObject * OscListReceiver_addAddress(OscListReceiver *self, PyObject *arg) { PyObject *flist; int i, j; if (PyString_Check(arg) || PyUnicode_Check(arg)) { flist = PyList_New(self->num); for (j=0; jnum; j++) { PyList_SET_ITEM(flist, j, PyFloat_FromDouble(0.)); } PyDict_SetItem(self->dict, arg, flist); } else if (PyList_Check(arg)) { Py_ssize_t lsize = PyList_Size(arg); for (i=0; inum); for (j=0; jnum; j++) { PyList_SET_ITEM(flist, j, PyFloat_FromDouble(0.)); } PyDict_SetItem(self->dict, PyList_GET_ITEM(arg, i), flist); } } Py_INCREF(Py_None); return Py_None; } static PyObject * OscListReceiver_delAddress(OscListReceiver *self, PyObject *arg) { int i; if (PyString_Check(arg) || PyUnicode_Check(arg)) { PyDict_DelItem(self->dict, arg); } else if (PyList_Check(arg)) { Py_ssize_t lsize = PyList_Size(arg); for (i=0; idict, PyList_GET_ITEM(arg, i))) PyDict_DelItem(self->dict, PyList_GET_ITEM(arg, i)); } } Py_INCREF(Py_None); return Py_None; } static PyObject * OscListReceiver_setValue(OscListReceiver *self, PyObject *args, PyObject *kwds) { PyObject *address, *value; static char *kwlist[] = {"address", "value", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &address, &value)) Py_RETURN_NONE; PyDict_SetItem(self->dict, address, value); Py_RETURN_NONE; } static PyObject * OscListReceiver_getServer(OscListReceiver* self) { GET_SERVER }; static PyObject * OscListReceiver_getStream(OscListReceiver* self) { GET_STREAM }; static PyMemberDef OscListReceiver_members[] = { {"server", T_OBJECT_EX, offsetof(OscListReceiver, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(OscListReceiver, stream), 0, "Stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef OscListReceiver_methods[] = { {"getServer", (PyCFunction)OscListReceiver_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)OscListReceiver_getStream, METH_NOARGS, "Returns stream object."}, {"addAddress", (PyCFunction)OscListReceiver_addAddress, METH_O, "Add a new address to the dictionary."}, {"delAddress", (PyCFunction)OscListReceiver_delAddress, METH_O, "Remove an address from the dictionary."}, {"setValue", (PyCFunction)OscListReceiver_setValue, METH_VARARGS|METH_KEYWORDS, "Sets value for a specified address."}, {NULL} /* Sentinel */ }; PyTypeObject OscListReceiverType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.OscListReceiver_base", /*tp_name*/ sizeof(OscListReceiver), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)OscListReceiver_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "OscListReceiver objects. Receive list of values via Open Sound Control protocol.", /* tp_doc */ (traverseproc)OscListReceiver_traverse, /* tp_traverse */ (inquiry)OscListReceiver_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ OscListReceiver_methods, /* tp_methods */ OscListReceiver_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ OscListReceiver_new, /* tp_new */ }; /* OSC list receiver stream object */ typedef struct { pyo_audio_HEAD PyObject *input; PyObject *address_path; MYFLT value; MYFLT factor; int order; int interpolation; int modebuffer[2]; } OscListReceive; static void OscListReceive_postprocessing_ii(OscListReceive *self) { POST_PROCESSING_II }; static void OscListReceive_postprocessing_ai(OscListReceive *self) { POST_PROCESSING_AI }; static void OscListReceive_postprocessing_ia(OscListReceive *self) { POST_PROCESSING_IA }; static void OscListReceive_postprocessing_aa(OscListReceive *self) { POST_PROCESSING_AA }; static void OscListReceive_postprocessing_ireva(OscListReceive *self) { POST_PROCESSING_IREVA }; static void OscListReceive_postprocessing_areva(OscListReceive *self) { POST_PROCESSING_AREVA }; static void OscListReceive_postprocessing_revai(OscListReceive *self) { POST_PROCESSING_REVAI }; static void OscListReceive_postprocessing_revaa(OscListReceive *self) { POST_PROCESSING_REVAA }; static void OscListReceive_postprocessing_revareva(OscListReceive *self) { POST_PROCESSING_REVAREVA }; static void OscListReceive_setProcMode(OscListReceive *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = OscListReceive_postprocessing_ii; break; case 1: self->muladd_func_ptr = OscListReceive_postprocessing_ai; break; case 2: self->muladd_func_ptr = OscListReceive_postprocessing_revai; break; case 10: self->muladd_func_ptr = OscListReceive_postprocessing_ia; break; case 11: self->muladd_func_ptr = OscListReceive_postprocessing_aa; break; case 12: self->muladd_func_ptr = OscListReceive_postprocessing_revaa; break; case 20: self->muladd_func_ptr = OscListReceive_postprocessing_ireva; break; case 21: self->muladd_func_ptr = OscListReceive_postprocessing_areva; break; case 22: self->muladd_func_ptr = OscListReceive_postprocessing_revareva; break; } } static void OscListReceive_compute_next_data_frame(OscListReceive *self) { int i; PyObject *flist = OscListReceiver_getValue((OscListReceiver *)self->input, self->address_path); MYFLT val = PyFloat_AsDouble(PyList_GET_ITEM(flist, self->order)); if (self->interpolation == 1) { for (i=0; ibufsize; i++) { self->data[i] = self->value = self->value + (val - self->value) * self->factor; } } else { for (i=0; ibufsize; i++) { self->data[i] = self->value = val; } } (*self->muladd_func_ptr)(self); } static int OscListReceive_traverse(OscListReceive *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->address_path); return 0; } static int OscListReceive_clear(OscListReceive *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->address_path); return 0; } static void OscListReceive_dealloc(OscListReceive* self) { pyo_DEALLOC OscListReceive_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * OscListReceive_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp=NULL, *pathtmp=NULL, *multmp=NULL, *addtmp=NULL;; OscListReceive *self; self = (OscListReceive *)type->tp_alloc(type, 0); self->order = 0; self->value = 0.; self->interpolation = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON self->factor = 1. / (0.01 * self->sr); Stream_setFunctionPtr(self->stream, OscListReceive_compute_next_data_frame); self->mode_func_ptr = OscListReceive_setProcMode; static char *kwlist[] = {"input", "address", "order", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOi|OO", kwlist, &inputtmp, &pathtmp, &self->order, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->input); Py_INCREF(inputtmp); self->input = inputtmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (!PyString_Check(pathtmp) && !PyUnicode_Check(pathtmp)) { PyErr_SetString(PyExc_TypeError, "OscListReceive: the address attributes must be a string or a unicode."); Py_RETURN_NONE; } Py_INCREF(pathtmp); Py_XDECREF(self->address_path); self->address_path = pathtmp; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * OscListReceive_setInterpolation(OscListReceive *self, PyObject *arg) { ASSERT_ARG_NOT_NULL self->interpolation = PyInt_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * OscListReceive_getServer(OscListReceive* self) { GET_SERVER }; static PyObject * OscListReceive_getStream(OscListReceive* self) { GET_STREAM }; static PyObject * OscListReceive_setMul(OscListReceive *self, PyObject *arg) { SET_MUL }; static PyObject * OscListReceive_setAdd(OscListReceive *self, PyObject *arg) { SET_ADD }; static PyObject * OscListReceive_setSub(OscListReceive *self, PyObject *arg) { SET_SUB }; static PyObject * OscListReceive_setDiv(OscListReceive *self, PyObject *arg) { SET_DIV }; static PyObject * OscListReceive_play(OscListReceive *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * OscListReceive_stop(OscListReceive *self) { STOP }; static PyObject * OscListReceive_multiply(OscListReceive *self, PyObject *arg) { MULTIPLY }; static PyObject * OscListReceive_inplace_multiply(OscListReceive *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * OscListReceive_add(OscListReceive *self, PyObject *arg) { ADD }; static PyObject * OscListReceive_inplace_add(OscListReceive *self, PyObject *arg) { INPLACE_ADD }; static PyObject * OscListReceive_sub(OscListReceive *self, PyObject *arg) { SUB }; static PyObject * OscListReceive_inplace_sub(OscListReceive *self, PyObject *arg) { INPLACE_SUB }; static PyObject * OscListReceive_div(OscListReceive *self, PyObject *arg) { DIV }; static PyObject * OscListReceive_inplace_div(OscListReceive *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef OscListReceive_members[] = { {"server", T_OBJECT_EX, offsetof(OscListReceive, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(OscListReceive, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(OscListReceive, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(OscListReceive, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef OscListReceive_methods[] = { {"getServer", (PyCFunction)OscListReceive_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)OscListReceive_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)OscListReceive_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)OscListReceive_stop, METH_NOARGS, "Stops computing."}, {"setInterpolation", (PyCFunction)OscListReceive_setInterpolation, METH_O, "Sets interpolation on or off."}, {"setMul", (PyCFunction)OscListReceive_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)OscListReceive_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)OscListReceive_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)OscListReceive_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods OscListReceive_as_number = { (binaryfunc)OscListReceive_add, /*nb_add*/ (binaryfunc)OscListReceive_sub, /*nb_subtract*/ (binaryfunc)OscListReceive_multiply, /*nb_multiply*/ (binaryfunc)OscListReceive_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)OscListReceive_inplace_add, /*inplace_add*/ (binaryfunc)OscListReceive_inplace_sub, /*inplace_subtract*/ (binaryfunc)OscListReceive_inplace_multiply, /*inplace_multiply*/ (binaryfunc)OscListReceive_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject OscListReceiveType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.OscListReceive_base", /*tp_name*/ sizeof(OscListReceive), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)OscListReceive_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &OscListReceive_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "OscListReceive objects. Receive one value from a list of floats via Open Sound Control protocol.", /* tp_doc */ (traverseproc)OscListReceive_traverse, /* tp_traverse */ (inquiry)OscListReceive_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ OscListReceive_methods, /* tp_methods */ OscListReceive_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ OscListReceive_new, /* tp_new */ };pyo/src/objects/matrixprocessmodule.c0000644000175000017500000003541212652732202017360 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "matrixmodule.h" /**************/ /* MatrixPointer object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *matrix; PyObject *x; Stream *x_stream; PyObject *y; Stream *y_stream; int modebuffer[2]; } MatrixPointer; static void MatrixPointer_readframes(MatrixPointer *self) { int i; MYFLT *x = Stream_getData((Stream *)self->x_stream); MYFLT *y = Stream_getData((Stream *)self->y_stream); for (i=0; ibufsize; i++) { self->data[i] = MatrixStream_getInterpPointFromPos(self->matrix, x[i], y[i]); } } static void MatrixPointer_postprocessing_ii(MatrixPointer *self) { POST_PROCESSING_II }; static void MatrixPointer_postprocessing_ai(MatrixPointer *self) { POST_PROCESSING_AI }; static void MatrixPointer_postprocessing_ia(MatrixPointer *self) { POST_PROCESSING_IA }; static void MatrixPointer_postprocessing_aa(MatrixPointer *self) { POST_PROCESSING_AA }; static void MatrixPointer_postprocessing_ireva(MatrixPointer *self) { POST_PROCESSING_IREVA }; static void MatrixPointer_postprocessing_areva(MatrixPointer *self) { POST_PROCESSING_AREVA }; static void MatrixPointer_postprocessing_revai(MatrixPointer *self) { POST_PROCESSING_REVAI }; static void MatrixPointer_postprocessing_revaa(MatrixPointer *self) { POST_PROCESSING_REVAA }; static void MatrixPointer_postprocessing_revareva(MatrixPointer *self) { POST_PROCESSING_REVAREVA }; static void MatrixPointer_setProcMode(MatrixPointer *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = MatrixPointer_readframes; switch (muladdmode) { case 0: self->muladd_func_ptr = MatrixPointer_postprocessing_ii; break; case 1: self->muladd_func_ptr = MatrixPointer_postprocessing_ai; break; case 2: self->muladd_func_ptr = MatrixPointer_postprocessing_revai; break; case 10: self->muladd_func_ptr = MatrixPointer_postprocessing_ia; break; case 11: self->muladd_func_ptr = MatrixPointer_postprocessing_aa; break; case 12: self->muladd_func_ptr = MatrixPointer_postprocessing_revaa; break; case 20: self->muladd_func_ptr = MatrixPointer_postprocessing_ireva; break; case 21: self->muladd_func_ptr = MatrixPointer_postprocessing_areva; break; case 22: self->muladd_func_ptr = MatrixPointer_postprocessing_revareva; break; } } static void MatrixPointer_compute_next_data_frame(MatrixPointer *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int MatrixPointer_traverse(MatrixPointer *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->matrix); Py_VISIT(self->x); Py_VISIT(self->x_stream); Py_VISIT(self->y); Py_VISIT(self->y_stream); return 0; } static int MatrixPointer_clear(MatrixPointer *self) { pyo_CLEAR Py_CLEAR(self->matrix); Py_CLEAR(self->x); Py_CLEAR(self->x_stream); Py_CLEAR(self->y); Py_CLEAR(self->y_stream); return 0; } static void MatrixPointer_dealloc(MatrixPointer* self) { pyo_DEALLOC MatrixPointer_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * MatrixPointer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *matrixtmp, *xtmp, *ytmp, *multmp=NULL, *addtmp=NULL; MatrixPointer *self; self = (MatrixPointer *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, MatrixPointer_compute_next_data_frame); self->mode_func_ptr = MatrixPointer_setProcMode; static char *kwlist[] = {"matrix", "x", "y", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOO|OO", kwlist, &matrixtmp, &xtmp, &ytmp, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)matrixtmp, "getMatrixStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"matrix\" argument of MatrixPointer must be a PyoMatrixObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->matrix); self->matrix = PyObject_CallMethod((PyObject *)matrixtmp, "getMatrixStream", ""); if (xtmp) { PyObject_CallMethod((PyObject *)self, "setX", "O", xtmp); } if (ytmp) { PyObject_CallMethod((PyObject *)self, "setY", "O", ytmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); return (PyObject *)self; } static PyObject * MatrixPointer_getServer(MatrixPointer* self) { GET_SERVER }; static PyObject * MatrixPointer_getStream(MatrixPointer* self) { GET_STREAM }; static PyObject * MatrixPointer_setMul(MatrixPointer *self, PyObject *arg) { SET_MUL }; static PyObject * MatrixPointer_setAdd(MatrixPointer *self, PyObject *arg) { SET_ADD }; static PyObject * MatrixPointer_setSub(MatrixPointer *self, PyObject *arg) { SET_SUB }; static PyObject * MatrixPointer_setDiv(MatrixPointer *self, PyObject *arg) { SET_DIV }; static PyObject * MatrixPointer_play(MatrixPointer *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * MatrixPointer_out(MatrixPointer *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * MatrixPointer_stop(MatrixPointer *self) { STOP }; static PyObject * MatrixPointer_multiply(MatrixPointer *self, PyObject *arg) { MULTIPLY }; static PyObject * MatrixPointer_inplace_multiply(MatrixPointer *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * MatrixPointer_add(MatrixPointer *self, PyObject *arg) { ADD }; static PyObject * MatrixPointer_inplace_add(MatrixPointer *self, PyObject *arg) { INPLACE_ADD }; static PyObject * MatrixPointer_sub(MatrixPointer *self, PyObject *arg) { SUB }; static PyObject * MatrixPointer_inplace_sub(MatrixPointer *self, PyObject *arg) { INPLACE_SUB }; static PyObject * MatrixPointer_div(MatrixPointer *self, PyObject *arg) { DIV }; static PyObject * MatrixPointer_inplace_div(MatrixPointer *self, PyObject *arg) { INPLACE_DIV }; static PyObject * MatrixPointer_getMatrix(MatrixPointer* self) { Py_INCREF(self->matrix); return self->matrix; }; static PyObject * MatrixPointer_setMatrix(MatrixPointer *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; if ( PyObject_HasAttrString((PyObject *)tmp, "getMatrixStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"matrix\" argument of MatrixPointer must be a PyoMatrixObject.\n"); Py_RETURN_NONE; } Py_DECREF(self->matrix); self->matrix = PyObject_CallMethod((PyObject *)tmp, "getMatrixStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * MatrixPointer_setX(MatrixPointer *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL tmp = arg; if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) { PyErr_SetString(PyExc_TypeError, "\"x\" attribute of MatrixPointer must be a PyoObject.\n"); Py_RETURN_NONE; } Py_INCREF(tmp); Py_XDECREF(self->x); self->x = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->x, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->x_stream); self->x_stream = (Stream *)streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * MatrixPointer_setY(MatrixPointer *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL tmp = arg; if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) { PyErr_SetString(PyExc_TypeError, "\"y\" attribute of MatrixPointer must be a PyoObject.\n"); Py_RETURN_NONE; } Py_INCREF(tmp); Py_XDECREF(self->y); self->y = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->y, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->y_stream); self->y_stream = (Stream *)streamtmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef MatrixPointer_members[] = { {"server", T_OBJECT_EX, offsetof(MatrixPointer, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(MatrixPointer, stream), 0, "Stream object."}, {"matrix", T_OBJECT_EX, offsetof(MatrixPointer, matrix), 0, "Waveform matrix."}, {"x", T_OBJECT_EX, offsetof(MatrixPointer, x), 0, "Reader x."}, {"y", T_OBJECT_EX, offsetof(MatrixPointer, y), 0, "Reader y."}, {"mul", T_OBJECT_EX, offsetof(MatrixPointer, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(MatrixPointer, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef MatrixPointer_methods[] = { {"getMatrix", (PyCFunction)MatrixPointer_getMatrix, METH_NOARGS, "Returns waveform matrix object."}, {"getServer", (PyCFunction)MatrixPointer_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)MatrixPointer_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)MatrixPointer_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)MatrixPointer_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)MatrixPointer_stop, METH_NOARGS, "Stops computing."}, {"setMatrix", (PyCFunction)MatrixPointer_setMatrix, METH_O, "Sets oscillator matrix."}, {"setX", (PyCFunction)MatrixPointer_setX, METH_O, "Sets reader x."}, {"setY", (PyCFunction)MatrixPointer_setY, METH_O, "Sets reader y."}, {"setMul", (PyCFunction)MatrixPointer_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)MatrixPointer_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)MatrixPointer_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)MatrixPointer_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods MatrixPointer_as_number = { (binaryfunc)MatrixPointer_add, /*nb_add*/ (binaryfunc)MatrixPointer_sub, /*nb_subtract*/ (binaryfunc)MatrixPointer_multiply, /*nb_multiply*/ (binaryfunc)MatrixPointer_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)MatrixPointer_inplace_add, /*inplace_add*/ (binaryfunc)MatrixPointer_inplace_sub, /*inplace_subtract*/ (binaryfunc)MatrixPointer_inplace_multiply, /*inplace_multiply*/ (binaryfunc)MatrixPointer_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_x */ }; PyTypeObject MatrixPointerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.MatrixPointer_base", /*tp_name*/ sizeof(MatrixPointer), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)MatrixPointer_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &MatrixPointer_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "MatrixPointer objects. Read a waveform matrix with a pointer x.", /* tp_doc */ (traverseproc)MatrixPointer_traverse, /* tp_traverse */ (inquiry)MatrixPointer_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ MatrixPointer_methods, /* tp_methods */ MatrixPointer_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MatrixPointer_new, /* tp_new */ };pyo/src/objects/distomodule.c0000644000175000017500000031066612652732202015606 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *drive; Stream *drive_stream; PyObject *slope; Stream *slope_stream; int init; int modebuffer[4]; MYFLT y1; // sample memory } Disto; static MYFLT _clip(MYFLT x) { if (x < 0) return 0; else if (x > 1) return 1; else return x; } static void Disto_transform_ii(Disto *self) { MYFLT val, coeff; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT drv = .4 - _clip(PyFloat_AS_DOUBLE(self->drive)) * .3999; MYFLT slp = _clip(PyFloat_AS_DOUBLE(self->slope)); for (i=0; ibufsize; i++) { val = MYATAN2(in[i], drv); self->data[i] = val; } coeff = 1.0 - slp; for (i=0; ibufsize; i++) { val = self->data[i] * coeff + self->y1 * slp; self->y1 = val; self->data[i] = val; } } static void Disto_transform_ai(Disto *self) { MYFLT val, drv, coeff; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *drive = Stream_getData((Stream *)self->drive_stream); MYFLT slp = _clip(PyFloat_AS_DOUBLE(self->slope)); for (i=0; ibufsize; i++) { drv = .4 - _clip(drive[i]) * .3999; val = MYATAN2(in[i], drv); self->data[i] = val; } coeff = 1.0 - slp; for (i=0; ibufsize; i++) { val = self->data[i] * coeff + self->y1 * slp; self->y1 = val; self->data[i] = val; } } static void Disto_transform_ia(Disto *self) { MYFLT val, coeff, slp; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT drv = .4 - _clip(PyFloat_AS_DOUBLE(self->drive)) * .3999; MYFLT *slope = Stream_getData((Stream *)self->slope_stream); for (i=0; ibufsize; i++) { val = MYATAN2(in[i], drv); self->data[i] = val; } for (i=0; ibufsize; i++) { slp = _clip(slope[i]); coeff = 1.0 - slp; val = self->data[i] * coeff + self->y1 * slp; self->y1 = val; self->data[i] = val; } } static void Disto_transform_aa(Disto *self) { MYFLT val, drv, coeff, slp; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *drive = Stream_getData((Stream *)self->drive_stream); MYFLT *slope = Stream_getData((Stream *)self->slope_stream); for (i=0; ibufsize; i++) { drv = .4 - _clip(drive[i]) * .3999; val = MYATAN2(in[i], drv); self->data[i] = val; } for (i=0; ibufsize; i++) { slp = _clip(slope[i]); coeff = 1.0 - slp; val = self->data[i] * coeff + self->y1 * slp; self->y1 = val; self->data[i] = val; } } static void Disto_postprocessing_ii(Disto *self) { POST_PROCESSING_II }; static void Disto_postprocessing_ai(Disto *self) { POST_PROCESSING_AI }; static void Disto_postprocessing_ia(Disto *self) { POST_PROCESSING_IA }; static void Disto_postprocessing_aa(Disto *self) { POST_PROCESSING_AA }; static void Disto_postprocessing_ireva(Disto *self) { POST_PROCESSING_IREVA }; static void Disto_postprocessing_areva(Disto *self) { POST_PROCESSING_AREVA }; static void Disto_postprocessing_revai(Disto *self) { POST_PROCESSING_REVAI }; static void Disto_postprocessing_revaa(Disto *self) { POST_PROCESSING_REVAA }; static void Disto_postprocessing_revareva(Disto *self) { POST_PROCESSING_REVAREVA }; static void Disto_setProcMode(Disto *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Disto_transform_ii; break; case 1: self->proc_func_ptr = Disto_transform_ai; break; case 10: self->proc_func_ptr = Disto_transform_ia; break; case 11: self->proc_func_ptr = Disto_transform_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Disto_postprocessing_ii; break; case 1: self->muladd_func_ptr = Disto_postprocessing_ai; break; case 2: self->muladd_func_ptr = Disto_postprocessing_revai; break; case 10: self->muladd_func_ptr = Disto_postprocessing_ia; break; case 11: self->muladd_func_ptr = Disto_postprocessing_aa; break; case 12: self->muladd_func_ptr = Disto_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Disto_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Disto_postprocessing_areva; break; case 22: self->muladd_func_ptr = Disto_postprocessing_revareva; break; } } static void Disto_compute_next_data_frame(Disto *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Disto_traverse(Disto *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->drive); Py_VISIT(self->drive_stream); Py_VISIT(self->slope); Py_VISIT(self->slope_stream); return 0; } static int Disto_clear(Disto *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->drive); Py_CLEAR(self->drive_stream); Py_CLEAR(self->slope); Py_CLEAR(self->slope_stream); return 0; } static void Disto_dealloc(Disto* self) { pyo_DEALLOC Disto_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Disto_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *drivetmp=NULL, *slopetmp=NULL, *multmp=NULL, *addtmp=NULL; Disto *self; self = (Disto *)type->tp_alloc(type, 0); self->drive = PyFloat_FromDouble(.75); self->slope = PyFloat_FromDouble(.5); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->y1 = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Disto_compute_next_data_frame); self->mode_func_ptr = Disto_setProcMode; static char *kwlist[] = {"input", "drive", "slope", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &drivetmp, &slopetmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (drivetmp) { PyObject_CallMethod((PyObject *)self, "setDrive", "O", drivetmp); } if (slopetmp) { PyObject_CallMethod((PyObject *)self, "setSlope", "O", slopetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Disto_getServer(Disto* self) { GET_SERVER }; static PyObject * Disto_getStream(Disto* self) { GET_STREAM }; static PyObject * Disto_setMul(Disto *self, PyObject *arg) { SET_MUL }; static PyObject * Disto_setAdd(Disto *self, PyObject *arg) { SET_ADD }; static PyObject * Disto_setSub(Disto *self, PyObject *arg) { SET_SUB }; static PyObject * Disto_setDiv(Disto *self, PyObject *arg) { SET_DIV }; static PyObject * Disto_play(Disto *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Disto_out(Disto *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Disto_stop(Disto *self) { STOP }; static PyObject * Disto_multiply(Disto *self, PyObject *arg) { MULTIPLY }; static PyObject * Disto_inplace_multiply(Disto *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Disto_add(Disto *self, PyObject *arg) { ADD }; static PyObject * Disto_inplace_add(Disto *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Disto_sub(Disto *self, PyObject *arg) { SUB }; static PyObject * Disto_inplace_sub(Disto *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Disto_div(Disto *self, PyObject *arg) { DIV }; static PyObject * Disto_inplace_div(Disto *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Disto_setDrive(Disto *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->drive); if (isNumber == 1) { self->drive = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->drive = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->drive, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->drive_stream); self->drive_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Disto_setSlope(Disto *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->slope); if (isNumber == 1) { self->slope = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->slope = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->slope, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->slope_stream); self->slope_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Disto_members[] = { {"server", T_OBJECT_EX, offsetof(Disto, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Disto, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Disto, input), 0, "Input sound object."}, {"drive", T_OBJECT_EX, offsetof(Disto, drive), 0, "Cutoff driveuency in cycle per second."}, {"slope", T_OBJECT_EX, offsetof(Disto, slope), 0, "Lowpass filter slope factor."}, {"mul", T_OBJECT_EX, offsetof(Disto, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Disto, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Disto_methods[] = { {"getServer", (PyCFunction)Disto_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Disto_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Disto_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Disto_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Disto_stop, METH_NOARGS, "Stops computing."}, {"setDrive", (PyCFunction)Disto_setDrive, METH_O, "Sets distortion drive factor (0 -> 1)."}, {"setSlope", (PyCFunction)Disto_setSlope, METH_O, "Sets lowpass filter slope factor."}, {"setMul", (PyCFunction)Disto_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Disto_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Disto_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Disto_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Disto_as_number = { (binaryfunc)Disto_add, /*nb_add*/ (binaryfunc)Disto_sub, /*nb_subtract*/ (binaryfunc)Disto_multiply, /*nb_multiply*/ (binaryfunc)Disto_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Disto_inplace_add, /*inplace_add*/ (binaryfunc)Disto_inplace_sub, /*inplace_subtract*/ (binaryfunc)Disto_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Disto_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject DistoType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Disto_base", /*tp_name*/ sizeof(Disto), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Disto_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Disto_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Disto objects. Arctan distortion.", /* tp_doc */ (traverseproc)Disto_traverse, /* tp_traverse */ (inquiry)Disto_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Disto_methods, /* tp_methods */ Disto_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Disto_new, /* tp_new */ }; /*****************/ /** Clip object **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *min; Stream *min_stream; PyObject *max; Stream *max_stream; int modebuffer[4]; } Clip; static void Clip_transform_ii(Clip *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT ma = PyFloat_AS_DOUBLE(self->max); for (i=0; ibufsize; i++) { val = in[i]; if(val < mi) self->data[i] = mi; else if(val > ma) self->data[i] = ma; else self->data[i] = val; } } static void Clip_transform_ai(Clip *self) { MYFLT val, mini; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT ma = PyFloat_AS_DOUBLE(self->max); for (i=0; ibufsize; i++) { val = in[i]; mini = mi[i]; if(val < mini) self->data[i] = mini; else if(val > ma) self->data[i] = ma; else self->data[i] = val; } } static void Clip_transform_ia(Clip *self) { MYFLT val, maxi; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT *ma = Stream_getData((Stream *)self->max_stream); for (i=0; ibufsize; i++) { val = in[i]; maxi = ma[i]; if(val < mi) self->data[i] = mi; else if(val > maxi) self->data[i] = maxi; else self->data[i] = val; } } static void Clip_transform_aa(Clip *self) { MYFLT val, mini, maxi; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT *ma = Stream_getData((Stream *)self->max_stream); for (i=0; ibufsize; i++) { val = in[i]; mini = mi[i]; maxi = ma[i]; if(val < mini) self->data[i] = mini; else if(val > maxi) self->data[i] = maxi; else self->data[i] = val; } } static void Clip_postprocessing_ii(Clip *self) { POST_PROCESSING_II }; static void Clip_postprocessing_ai(Clip *self) { POST_PROCESSING_AI }; static void Clip_postprocessing_ia(Clip *self) { POST_PROCESSING_IA }; static void Clip_postprocessing_aa(Clip *self) { POST_PROCESSING_AA }; static void Clip_postprocessing_ireva(Clip *self) { POST_PROCESSING_IREVA }; static void Clip_postprocessing_areva(Clip *self) { POST_PROCESSING_AREVA }; static void Clip_postprocessing_revai(Clip *self) { POST_PROCESSING_REVAI }; static void Clip_postprocessing_revaa(Clip *self) { POST_PROCESSING_REVAA }; static void Clip_postprocessing_revareva(Clip *self) { POST_PROCESSING_REVAREVA }; static void Clip_setProcMode(Clip *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Clip_transform_ii; break; case 1: self->proc_func_ptr = Clip_transform_ai; break; case 10: self->proc_func_ptr = Clip_transform_ia; break; case 11: self->proc_func_ptr = Clip_transform_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Clip_postprocessing_ii; break; case 1: self->muladd_func_ptr = Clip_postprocessing_ai; break; case 2: self->muladd_func_ptr = Clip_postprocessing_revai; break; case 10: self->muladd_func_ptr = Clip_postprocessing_ia; break; case 11: self->muladd_func_ptr = Clip_postprocessing_aa; break; case 12: self->muladd_func_ptr = Clip_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Clip_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Clip_postprocessing_areva; break; case 22: self->muladd_func_ptr = Clip_postprocessing_revareva; break; } } static void Clip_compute_next_data_frame(Clip *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Clip_traverse(Clip *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->min); Py_VISIT(self->min_stream); Py_VISIT(self->max); Py_VISIT(self->max_stream); return 0; } static int Clip_clear(Clip *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->min); Py_CLEAR(self->min_stream); Py_CLEAR(self->max); Py_CLEAR(self->max_stream); return 0; } static void Clip_dealloc(Clip* self) { pyo_DEALLOC Clip_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Clip_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL; Clip *self; self = (Clip *)type->tp_alloc(type, 0); self->min = PyFloat_FromDouble(-1.0); self->max = PyFloat_FromDouble(1.0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Clip_compute_next_data_frame); self->mode_func_ptr = Clip_setProcMode; static char *kwlist[] = {"input", "min", "max", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &mintmp, &maxtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (mintmp) { PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp); } if (maxtmp) { PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Clip_getServer(Clip* self) { GET_SERVER }; static PyObject * Clip_getStream(Clip* self) { GET_STREAM }; static PyObject * Clip_setMul(Clip *self, PyObject *arg) { SET_MUL }; static PyObject * Clip_setAdd(Clip *self, PyObject *arg) { SET_ADD }; static PyObject * Clip_setSub(Clip *self, PyObject *arg) { SET_SUB }; static PyObject * Clip_setDiv(Clip *self, PyObject *arg) { SET_DIV }; static PyObject * Clip_play(Clip *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Clip_out(Clip *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Clip_stop(Clip *self) { STOP }; static PyObject * Clip_multiply(Clip *self, PyObject *arg) { MULTIPLY }; static PyObject * Clip_inplace_multiply(Clip *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Clip_add(Clip *self, PyObject *arg) { ADD }; static PyObject * Clip_inplace_add(Clip *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Clip_sub(Clip *self, PyObject *arg) { SUB }; static PyObject * Clip_inplace_sub(Clip *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Clip_div(Clip *self, PyObject *arg) { DIV }; static PyObject * Clip_inplace_div(Clip *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Clip_setMin(Clip *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->min); if (isNumber == 1) { self->min = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->min = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->min, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->min_stream); self->min_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Clip_setMax(Clip *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->max); if (isNumber == 1) { self->max = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->max = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->max_stream); self->max_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Clip_members[] = { {"server", T_OBJECT_EX, offsetof(Clip, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Clip, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Clip, input), 0, "Input sound object."}, {"min", T_OBJECT_EX, offsetof(Clip, min), 0, "Minimum possible value."}, {"max", T_OBJECT_EX, offsetof(Clip, max), 0, "Maximum possible value."}, {"mul", T_OBJECT_EX, offsetof(Clip, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Clip, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Clip_methods[] = { {"getServer", (PyCFunction)Clip_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Clip_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Clip_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Clip_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Clip_stop, METH_NOARGS, "Stops computing."}, {"setMin", (PyCFunction)Clip_setMin, METH_O, "Sets the minimum value."}, {"setMax", (PyCFunction)Clip_setMax, METH_O, "Sets the maximum value."}, {"setMul", (PyCFunction)Clip_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Clip_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Clip_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Clip_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Clip_as_number = { (binaryfunc)Clip_add, /*nb_add*/ (binaryfunc)Clip_sub, /*nb_subtract*/ (binaryfunc)Clip_multiply, /*nb_multiply*/ (binaryfunc)Clip_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Clip_inplace_add, /*inplace_add*/ (binaryfunc)Clip_inplace_sub, /*inplace_subtract*/ (binaryfunc)Clip_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Clip_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ClipType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Clip_base", /*tp_name*/ sizeof(Clip), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Clip_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Clip_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Clip objects. Clips a signal to a predefined limit.", /* tp_doc */ (traverseproc)Clip_traverse, /* tp_traverse */ (inquiry)Clip_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Clip_methods, /* tp_methods */ Clip_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Clip_new, /* tp_new */ }; /*****************/ /* Mirror object */ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *min; Stream *min_stream; PyObject *max; Stream *max_stream; int modebuffer[4]; } Mirror; static void Mirror_transform_ii(Mirror *self) { MYFLT val, avg; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT ma = PyFloat_AS_DOUBLE(self->max); if (mi >= ma) { avg = (mi + ma) * 0.5; for (i=0; ibufsize; i++) { self->data[i] = avg; } } else { for (i=0; ibufsize; i++) { val = in[i]; while ((val > ma) || (val < mi)) { if (val > ma) val = ma + ma - val; else val = mi + mi - val; } self->data[i] = val; } } } static void Mirror_transform_ai(Mirror *self) { MYFLT val, avg, mi; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *mini = Stream_getData((Stream *)self->min_stream); MYFLT ma = PyFloat_AS_DOUBLE(self->max); for (i=0; ibufsize; i++) { val = in[i]; mi = mini[i]; if (mi >= ma) { avg = (mi + ma) * 0.5; self->data[i] = avg; } else { while ((val > ma) || (val < mi)) { if (val > ma) val = ma + ma - val; else val = mi + mi - val; } self->data[i] = val; } } } static void Mirror_transform_ia(Mirror *self) { MYFLT val, avg, ma; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT *maxi = Stream_getData((Stream *)self->max_stream); for (i=0; ibufsize; i++) { val = in[i]; ma = maxi[i]; if (mi >= ma) { avg = (mi + ma) * 0.5; self->data[i] = avg; } else { while ((val > ma) || (val < mi)) { if (val > ma) val = ma + ma - val; else val = mi + mi - val; } self->data[i] = val; } } } static void Mirror_transform_aa(Mirror *self) { MYFLT val, avg, mi, ma; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *mini = Stream_getData((Stream *)self->min_stream); MYFLT *maxi = Stream_getData((Stream *)self->max_stream); for (i=0; ibufsize; i++) { val = in[i]; mi = mini[i]; ma = maxi[i]; if (mi >= ma) { avg = (mi + ma) * 0.5; self->data[i] = avg; } else { while ((val > ma) || (val < mi)) { if (val > ma) val = ma + ma - val; else val = mi + mi - val; } self->data[i] = val; } } } static void Mirror_postprocessing_ii(Mirror *self) { POST_PROCESSING_II }; static void Mirror_postprocessing_ai(Mirror *self) { POST_PROCESSING_AI }; static void Mirror_postprocessing_ia(Mirror *self) { POST_PROCESSING_IA }; static void Mirror_postprocessing_aa(Mirror *self) { POST_PROCESSING_AA }; static void Mirror_postprocessing_ireva(Mirror *self) { POST_PROCESSING_IREVA }; static void Mirror_postprocessing_areva(Mirror *self) { POST_PROCESSING_AREVA }; static void Mirror_postprocessing_revai(Mirror *self) { POST_PROCESSING_REVAI }; static void Mirror_postprocessing_revaa(Mirror *self) { POST_PROCESSING_REVAA }; static void Mirror_postprocessing_revareva(Mirror *self) { POST_PROCESSING_REVAREVA }; static void Mirror_setProcMode(Mirror *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Mirror_transform_ii; break; case 1: self->proc_func_ptr = Mirror_transform_ai; break; case 10: self->proc_func_ptr = Mirror_transform_ia; break; case 11: self->proc_func_ptr = Mirror_transform_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Mirror_postprocessing_ii; break; case 1: self->muladd_func_ptr = Mirror_postprocessing_ai; break; case 2: self->muladd_func_ptr = Mirror_postprocessing_revai; break; case 10: self->muladd_func_ptr = Mirror_postprocessing_ia; break; case 11: self->muladd_func_ptr = Mirror_postprocessing_aa; break; case 12: self->muladd_func_ptr = Mirror_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Mirror_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Mirror_postprocessing_areva; break; case 22: self->muladd_func_ptr = Mirror_postprocessing_revareva; break; } } static void Mirror_compute_next_data_frame(Mirror *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Mirror_traverse(Mirror *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->min); Py_VISIT(self->min_stream); Py_VISIT(self->max); Py_VISIT(self->max_stream); return 0; } static int Mirror_clear(Mirror *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->min); Py_CLEAR(self->min_stream); Py_CLEAR(self->max); Py_CLEAR(self->max_stream); return 0; } static void Mirror_dealloc(Mirror* self) { pyo_DEALLOC Mirror_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Mirror_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL; Mirror *self; self = (Mirror *)type->tp_alloc(type, 0); self->min = PyFloat_FromDouble(0.0); self->max = PyFloat_FromDouble(1.0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Mirror_compute_next_data_frame); self->mode_func_ptr = Mirror_setProcMode; static char *kwlist[] = {"input", "min", "max", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &mintmp, &maxtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (mintmp) { PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp); } if (maxtmp) { PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Mirror_getServer(Mirror* self) { GET_SERVER }; static PyObject * Mirror_getStream(Mirror* self) { GET_STREAM }; static PyObject * Mirror_setMul(Mirror *self, PyObject *arg) { SET_MUL }; static PyObject * Mirror_setAdd(Mirror *self, PyObject *arg) { SET_ADD }; static PyObject * Mirror_setSub(Mirror *self, PyObject *arg) { SET_SUB }; static PyObject * Mirror_setDiv(Mirror *self, PyObject *arg) { SET_DIV }; static PyObject * Mirror_play(Mirror *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Mirror_out(Mirror *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Mirror_stop(Mirror *self) { STOP }; static PyObject * Mirror_multiply(Mirror *self, PyObject *arg) { MULTIPLY }; static PyObject * Mirror_inplace_multiply(Mirror *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Mirror_add(Mirror *self, PyObject *arg) { ADD }; static PyObject * Mirror_inplace_add(Mirror *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Mirror_sub(Mirror *self, PyObject *arg) { SUB }; static PyObject * Mirror_inplace_sub(Mirror *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Mirror_div(Mirror *self, PyObject *arg) { DIV }; static PyObject * Mirror_inplace_div(Mirror *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Mirror_setMin(Mirror *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->min); if (isNumber == 1) { self->min = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->min = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->min, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->min_stream); self->min_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Mirror_setMax(Mirror *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->max); if (isNumber == 1) { self->max = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->max = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->max_stream); self->max_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Mirror_members[] = { {"server", T_OBJECT_EX, offsetof(Mirror, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Mirror, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Mirror, input), 0, "Input sound object."}, {"min", T_OBJECT_EX, offsetof(Mirror, min), 0, "Minimum possible value."}, {"max", T_OBJECT_EX, offsetof(Mirror, max), 0, "Maximum possible value."}, {"mul", T_OBJECT_EX, offsetof(Mirror, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Mirror, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Mirror_methods[] = { {"getServer", (PyCFunction)Mirror_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Mirror_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Mirror_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Mirror_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Mirror_stop, METH_NOARGS, "Stops computing."}, {"setMin", (PyCFunction)Mirror_setMin, METH_O, "Sets the minimum value."}, {"setMax", (PyCFunction)Mirror_setMax, METH_O, "Sets the maximum value."}, {"setMul", (PyCFunction)Mirror_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Mirror_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Mirror_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Mirror_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Mirror_as_number = { (binaryfunc)Mirror_add, /*nb_add*/ (binaryfunc)Mirror_sub, /*nb_subtract*/ (binaryfunc)Mirror_multiply, /*nb_multiply*/ (binaryfunc)Mirror_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Mirror_inplace_add, /*inplace_add*/ (binaryfunc)Mirror_inplace_sub, /*inplace_subtract*/ (binaryfunc)Mirror_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Mirror_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject MirrorType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Mirror_base", /*tp_name*/ sizeof(Mirror), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Mirror_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Mirror_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Mirror objects. Reflects the signal that exceeds the min and max thresholds.", /* tp_doc */ (traverseproc)Mirror_traverse, /* tp_traverse */ (inquiry)Mirror_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Mirror_methods, /* tp_methods */ Mirror_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Mirror_new, /* tp_new */ }; /*****************/ /** Wrap object **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *min; Stream *min_stream; PyObject *max; Stream *max_stream; int modebuffer[4]; } Wrap; static void Wrap_transform_ii(Wrap *self) { MYFLT val, avg, rng, tmp; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT ma = PyFloat_AS_DOUBLE(self->max); if (mi >= ma) { avg = (mi + ma) * 0.5; for (i=0; ibufsize; i++) { self->data[i] = avg; } } else { rng = ma - mi; for (i=0; ibufsize; i++) { val = in[i]; tmp = (val - mi) / rng; if (tmp >= 1.0) { tmp -= (int)tmp; val = tmp * rng + mi; } else if (tmp < 0) { tmp += (int)(-tmp) + 1; val = tmp * rng + mi; if (val == ma) val = mi; } self->data[i] = val; } } } static void Wrap_transform_ai(Wrap *self) { MYFLT val, avg, rng, tmp, mi; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *mini = Stream_getData((Stream *)self->min_stream); MYFLT ma = PyFloat_AS_DOUBLE(self->max); for (i=0; ibufsize; i++) { val = in[i]; mi = mini[i]; if (mi >= ma) { avg = (mi + ma) * 0.5; self->data[i] = avg; } else { rng = ma - mi; tmp = (val - mi) / rng; if (tmp >= 1.0) { tmp -= (int)tmp; val = tmp * rng + mi; } else if (tmp < 0) { tmp += (int)(-tmp) + 1; val = tmp * rng + mi; if (val == ma) val = mi; } self->data[i] = val; } } } static void Wrap_transform_ia(Wrap *self) { MYFLT val, avg, rng, tmp, ma; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT *maxi = Stream_getData((Stream *)self->max_stream); for (i=0; ibufsize; i++) { val = in[i]; ma = maxi[i]; if (mi >= ma) { avg = (mi + ma) * 0.5; self->data[i] = avg; } else { rng = ma - mi; tmp = (val - mi) / rng; if (tmp >= 1.0) { tmp -= (int)tmp; val = tmp * rng + mi; } else if (tmp < 0) { tmp += (int)(-tmp) + 1; val = tmp * rng + mi; if (val == ma) val = mi; } self->data[i] = val; } } } static void Wrap_transform_aa(Wrap *self) { MYFLT val, avg, rng, tmp, mi, ma; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *mini = Stream_getData((Stream *)self->min_stream); MYFLT *maxi = Stream_getData((Stream *)self->max_stream); for (i=0; ibufsize; i++) { val = in[i]; mi = mini[i]; ma = maxi[i]; if (mi >= ma) { avg = (mi + ma) * 0.5; self->data[i] = avg; } else { rng = ma - mi; tmp = (val - mi) / rng; if (tmp >= 1.0) { tmp -= (int)tmp; val = tmp * rng + mi; } else if (tmp < 0) { tmp += (int)(-tmp) + 1; val = tmp * rng + mi; if (val == ma) val = mi; } self->data[i] = val; } } } static void Wrap_postprocessing_ii(Wrap *self) { POST_PROCESSING_II }; static void Wrap_postprocessing_ai(Wrap *self) { POST_PROCESSING_AI }; static void Wrap_postprocessing_ia(Wrap *self) { POST_PROCESSING_IA }; static void Wrap_postprocessing_aa(Wrap *self) { POST_PROCESSING_AA }; static void Wrap_postprocessing_ireva(Wrap *self) { POST_PROCESSING_IREVA }; static void Wrap_postprocessing_areva(Wrap *self) { POST_PROCESSING_AREVA }; static void Wrap_postprocessing_revai(Wrap *self) { POST_PROCESSING_REVAI }; static void Wrap_postprocessing_revaa(Wrap *self) { POST_PROCESSING_REVAA }; static void Wrap_postprocessing_revareva(Wrap *self) { POST_PROCESSING_REVAREVA }; static void Wrap_setProcMode(Wrap *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Wrap_transform_ii; break; case 1: self->proc_func_ptr = Wrap_transform_ai; break; case 10: self->proc_func_ptr = Wrap_transform_ia; break; case 11: self->proc_func_ptr = Wrap_transform_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Wrap_postprocessing_ii; break; case 1: self->muladd_func_ptr = Wrap_postprocessing_ai; break; case 2: self->muladd_func_ptr = Wrap_postprocessing_revai; break; case 10: self->muladd_func_ptr = Wrap_postprocessing_ia; break; case 11: self->muladd_func_ptr = Wrap_postprocessing_aa; break; case 12: self->muladd_func_ptr = Wrap_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Wrap_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Wrap_postprocessing_areva; break; case 22: self->muladd_func_ptr = Wrap_postprocessing_revareva; break; } } static void Wrap_compute_next_data_frame(Wrap *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Wrap_traverse(Wrap *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->min); Py_VISIT(self->min_stream); Py_VISIT(self->max); Py_VISIT(self->max_stream); return 0; } static int Wrap_clear(Wrap *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->min); Py_CLEAR(self->min_stream); Py_CLEAR(self->max); Py_CLEAR(self->max_stream); return 0; } static void Wrap_dealloc(Wrap* self) { pyo_DEALLOC Wrap_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Wrap_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL; Wrap *self; self = (Wrap *)type->tp_alloc(type, 0); self->min = PyFloat_FromDouble(0.0); self->max = PyFloat_FromDouble(1.0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Wrap_compute_next_data_frame); self->mode_func_ptr = Wrap_setProcMode; static char *kwlist[] = {"input", "min", "max", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &mintmp, &maxtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (mintmp) { PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp); } if (maxtmp) { PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Wrap_getServer(Wrap* self) { GET_SERVER }; static PyObject * Wrap_getStream(Wrap* self) { GET_STREAM }; static PyObject * Wrap_setMul(Wrap *self, PyObject *arg) { SET_MUL }; static PyObject * Wrap_setAdd(Wrap *self, PyObject *arg) { SET_ADD }; static PyObject * Wrap_setSub(Wrap *self, PyObject *arg) { SET_SUB }; static PyObject * Wrap_setDiv(Wrap *self, PyObject *arg) { SET_DIV }; static PyObject * Wrap_play(Wrap *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Wrap_out(Wrap *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Wrap_stop(Wrap *self) { STOP }; static PyObject * Wrap_multiply(Wrap *self, PyObject *arg) { MULTIPLY }; static PyObject * Wrap_inplace_multiply(Wrap *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Wrap_add(Wrap *self, PyObject *arg) { ADD }; static PyObject * Wrap_inplace_add(Wrap *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Wrap_sub(Wrap *self, PyObject *arg) { SUB }; static PyObject * Wrap_inplace_sub(Wrap *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Wrap_div(Wrap *self, PyObject *arg) { DIV }; static PyObject * Wrap_inplace_div(Wrap *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Wrap_setMin(Wrap *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->min); if (isNumber == 1) { self->min = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->min = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->min, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->min_stream); self->min_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Wrap_setMax(Wrap *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->max); if (isNumber == 1) { self->max = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->max = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->max_stream); self->max_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Wrap_members[] = { {"server", T_OBJECT_EX, offsetof(Wrap, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Wrap, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Wrap, input), 0, "Input sound object."}, {"min", T_OBJECT_EX, offsetof(Wrap, min), 0, "Minimum possible value."}, {"max", T_OBJECT_EX, offsetof(Wrap, max), 0, "Maximum possible value."}, {"mul", T_OBJECT_EX, offsetof(Wrap, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Wrap, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Wrap_methods[] = { {"getServer", (PyCFunction)Wrap_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Wrap_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Wrap_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Wrap_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Wrap_stop, METH_NOARGS, "Stops computing."}, {"setMin", (PyCFunction)Wrap_setMin, METH_O, "Sets the minimum value."}, {"setMax", (PyCFunction)Wrap_setMax, METH_O, "Sets the maximum value."}, {"setMul", (PyCFunction)Wrap_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Wrap_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Wrap_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Wrap_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Wrap_as_number = { (binaryfunc)Wrap_add, /*nb_add*/ (binaryfunc)Wrap_sub, /*nb_subtract*/ (binaryfunc)Wrap_multiply, /*nb_multiply*/ (binaryfunc)Wrap_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Wrap_inplace_add, /*inplace_add*/ (binaryfunc)Wrap_inplace_sub, /*inplace_subtract*/ (binaryfunc)Wrap_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Wrap_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject WrapType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Wrap_base", /*tp_name*/ sizeof(Wrap), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Wrap_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Wrap_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Wrap objects. Wraps-around the signal that exceeds the min and max thresholds.", /* tp_doc */ (traverseproc)Wrap_traverse, /* tp_traverse */ (inquiry)Wrap_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Wrap_methods, /* tp_methods */ Wrap_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Wrap_new, /* tp_new */ }; /*****************/ /** Degrade object **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *bitdepth; Stream *bitdepth_stream; PyObject *srscale; Stream *srscale_stream; MYFLT value; int sampsCount; int modebuffer[4]; } Degrade; static MYFLT _bit_clip(MYFLT x) { if (x < 1.0) return 1.0; else if (x > 32.0) return 32.0; else return x; } static MYFLT _sr_clip(MYFLT x) { // half sr ten times if (x <= 0.0009765625) return 0.0009765625; else if (x > 1.0) return 1.0; else return x; } static void Degrade_transform_ii(Degrade *self) { MYFLT bitscl, ibitscl, newsr; int i, nsamps, tmp; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT bitdepth = _bit_clip(PyFloat_AS_DOUBLE(self->bitdepth)); MYFLT srscale = _sr_clip(PyFloat_AS_DOUBLE(self->srscale)); bitscl = MYPOW(2.0, bitdepth-1); ibitscl = 1.0 / bitscl; newsr = self->sr * srscale; nsamps = (int)(self->sr / newsr); for (i=0; ibufsize; i++) { self->sampsCount++; if (self->sampsCount >= nsamps) { self->sampsCount = 0; tmp = (int)(in[i] * bitscl + 0.5); self->value = tmp * ibitscl; } self->data[i] = self->value; } } static void Degrade_transform_ai(Degrade *self) { MYFLT bitscl, ibitscl, newsr; int i, nsamps, tmp; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *bitdepth = Stream_getData((Stream *)self->bitdepth_stream); MYFLT srscale = _sr_clip(PyFloat_AS_DOUBLE(self->srscale)); newsr = self->sr * srscale; nsamps = (int)(self->sr / newsr); for (i=0; ibufsize; i++) { self->sampsCount++; if (self->sampsCount >= nsamps) { self->sampsCount = 0; bitscl = MYPOW(2.0, _bit_clip(bitdepth[i])-1); ibitscl = 1.0 / bitscl; tmp = (int)(in[i] * bitscl + 0.5); self->value = tmp * ibitscl; } self->data[i] = self->value; } } static void Degrade_transform_ia(Degrade *self) { MYFLT bitscl, ibitscl, newsr; int i, nsamps, tmp; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT bitdepth = _bit_clip(PyFloat_AS_DOUBLE(self->bitdepth)); MYFLT *srscale = Stream_getData((Stream *)self->srscale_stream); bitscl = MYPOW(2.0, bitdepth-1); ibitscl = 1.0 / bitscl; for (i=0; ibufsize; i++) { newsr = self->sr * _sr_clip(srscale[i]); nsamps = (int)(self->sr / newsr); self->sampsCount++; if (self->sampsCount >= nsamps) { self->sampsCount = 0; tmp = (int)(in[i] * bitscl + 0.5); self->value = tmp * ibitscl; } self->data[i] = self->value; } } static void Degrade_transform_aa(Degrade *self) { MYFLT bitscl, ibitscl, newsr; int i, nsamps, tmp; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *bitdepth = Stream_getData((Stream *)self->bitdepth_stream); MYFLT *srscale = Stream_getData((Stream *)self->srscale_stream); for (i=0; ibufsize; i++) { newsr = self->sr * _sr_clip(srscale[i]); nsamps = (int)(self->sr / newsr); self->sampsCount++; if (self->sampsCount >= nsamps) { self->sampsCount = 0; bitscl = MYPOW(2.0, _bit_clip(bitdepth[i])-1); ibitscl = 1.0 / bitscl; tmp = (int)(in[i] * bitscl + 0.5); self->value = tmp * ibitscl; } self->data[i] = self->value; } } static void Degrade_postprocessing_ii(Degrade *self) { POST_PROCESSING_II }; static void Degrade_postprocessing_ai(Degrade *self) { POST_PROCESSING_AI }; static void Degrade_postprocessing_ia(Degrade *self) { POST_PROCESSING_IA }; static void Degrade_postprocessing_aa(Degrade *self) { POST_PROCESSING_AA }; static void Degrade_postprocessing_ireva(Degrade *self) { POST_PROCESSING_IREVA }; static void Degrade_postprocessing_areva(Degrade *self) { POST_PROCESSING_AREVA }; static void Degrade_postprocessing_revai(Degrade *self) { POST_PROCESSING_REVAI }; static void Degrade_postprocessing_revaa(Degrade *self) { POST_PROCESSING_REVAA }; static void Degrade_postprocessing_revareva(Degrade *self) { POST_PROCESSING_REVAREVA }; static void Degrade_setProcMode(Degrade *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Degrade_transform_ii; break; case 1: self->proc_func_ptr = Degrade_transform_ai; break; case 10: self->proc_func_ptr = Degrade_transform_ia; break; case 11: self->proc_func_ptr = Degrade_transform_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Degrade_postprocessing_ii; break; case 1: self->muladd_func_ptr = Degrade_postprocessing_ai; break; case 2: self->muladd_func_ptr = Degrade_postprocessing_revai; break; case 10: self->muladd_func_ptr = Degrade_postprocessing_ia; break; case 11: self->muladd_func_ptr = Degrade_postprocessing_aa; break; case 12: self->muladd_func_ptr = Degrade_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Degrade_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Degrade_postprocessing_areva; break; case 22: self->muladd_func_ptr = Degrade_postprocessing_revareva; break; } } static void Degrade_compute_next_data_frame(Degrade *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Degrade_traverse(Degrade *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->bitdepth); Py_VISIT(self->bitdepth_stream); Py_VISIT(self->srscale); Py_VISIT(self->srscale_stream); return 0; } static int Degrade_clear(Degrade *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->bitdepth); Py_CLEAR(self->bitdepth_stream); Py_CLEAR(self->srscale); Py_CLEAR(self->srscale_stream); return 0; } static void Degrade_dealloc(Degrade* self) { pyo_DEALLOC Degrade_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Degrade_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *bitdepthtmp=NULL, *srscaletmp=NULL, *multmp=NULL, *addtmp=NULL; Degrade *self; self = (Degrade *)type->tp_alloc(type, 0); self->bitdepth = PyFloat_FromDouble(16); self->srscale = PyFloat_FromDouble(1.0); self->value = 0.0; self->sampsCount = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Degrade_compute_next_data_frame); self->mode_func_ptr = Degrade_setProcMode; static char *kwlist[] = {"input", "bitdepth", "srscale", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &bitdepthtmp, &srscaletmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (bitdepthtmp) { PyObject_CallMethod((PyObject *)self, "setBitdepth", "O", bitdepthtmp); } if (srscaletmp) { PyObject_CallMethod((PyObject *)self, "setSrscale", "O", srscaletmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Degrade_getServer(Degrade* self) { GET_SERVER }; static PyObject * Degrade_getStream(Degrade* self) { GET_STREAM }; static PyObject * Degrade_setMul(Degrade *self, PyObject *arg) { SET_MUL }; static PyObject * Degrade_setAdd(Degrade *self, PyObject *arg) { SET_ADD }; static PyObject * Degrade_setSub(Degrade *self, PyObject *arg) { SET_SUB }; static PyObject * Degrade_setDiv(Degrade *self, PyObject *arg) { SET_DIV }; static PyObject * Degrade_play(Degrade *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Degrade_out(Degrade *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Degrade_stop(Degrade *self) { STOP }; static PyObject * Degrade_multiply(Degrade *self, PyObject *arg) { MULTIPLY }; static PyObject * Degrade_inplace_multiply(Degrade *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Degrade_add(Degrade *self, PyObject *arg) { ADD }; static PyObject * Degrade_inplace_add(Degrade *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Degrade_sub(Degrade *self, PyObject *arg) { SUB }; static PyObject * Degrade_inplace_sub(Degrade *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Degrade_div(Degrade *self, PyObject *arg) { DIV }; static PyObject * Degrade_inplace_div(Degrade *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Degrade_setBitdepth(Degrade *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->bitdepth); if (isNumber == 1) { self->bitdepth = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->bitdepth = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->bitdepth, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->bitdepth_stream); self->bitdepth_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Degrade_setSrscale(Degrade *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->srscale); if (isNumber == 1) { self->srscale = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->srscale = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->srscale, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->srscale_stream); self->srscale_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Degrade_members[] = { {"server", T_OBJECT_EX, offsetof(Degrade, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Degrade, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Degrade, input), 0, "Input sound object."}, {"bitdepth", T_OBJECT_EX, offsetof(Degrade, bitdepth), 0, "Number of bits for amplitude values."}, {"srscale", T_OBJECT_EX, offsetof(Degrade, srscale), 0, "Sampling depth factor."}, {"mul", T_OBJECT_EX, offsetof(Degrade, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Degrade, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Degrade_methods[] = { {"getServer", (PyCFunction)Degrade_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Degrade_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Degrade_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Degrade_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Degrade_stop, METH_NOARGS, "Stops computing."}, {"setBitdepth", (PyCFunction)Degrade_setBitdepth, METH_O, "Sets the bitdepth value."}, {"setSrscale", (PyCFunction)Degrade_setSrscale, METH_O, "Sets the srscale value."}, {"setMul", (PyCFunction)Degrade_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Degrade_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Degrade_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Degrade_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Degrade_as_number = { (binaryfunc)Degrade_add, /*nb_add*/ (binaryfunc)Degrade_sub, /*nb_subtract*/ (binaryfunc)Degrade_multiply, /*nb_multiply*/ (binaryfunc)Degrade_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Degrade_inplace_add, /*inplace_add*/ (binaryfunc)Degrade_inplace_sub, /*inplace_subtract*/ (binaryfunc)Degrade_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Degrade_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject DegradeType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Degrade_base", /*tp_name*/ sizeof(Degrade), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Degrade_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Degrade_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Degrade objects. Applies different bitdepth and sr on a signal.", /* tp_doc */ (traverseproc)Degrade_traverse, /* tp_traverse */ (inquiry)Degrade_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Degrade_methods, /* tp_methods */ Degrade_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Degrade_new, /* tp_new */ }; /************/ /* Min */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *comp; Stream *comp_stream; int modebuffer[3]; // need at least 2 slots for mul & add } Min; static void Min_process_i(Min *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT cp = PyFloat_AS_DOUBLE(self->comp); for (i=0; ibufsize; i++) { self->data[i] = in[i] < cp ? in[i] : cp; } } static void Min_process_a(Min *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *cp = Stream_getData((Stream *)self->comp_stream); for (i=0; ibufsize; i++) { self->data[i] = in[i] < cp[i] ? in[i] : cp[i]; } } static void Min_postprocessing_ii(Min *self) { POST_PROCESSING_II }; static void Min_postprocessing_ai(Min *self) { POST_PROCESSING_AI }; static void Min_postprocessing_ia(Min *self) { POST_PROCESSING_IA }; static void Min_postprocessing_aa(Min *self) { POST_PROCESSING_AA }; static void Min_postprocessing_ireva(Min *self) { POST_PROCESSING_IREVA }; static void Min_postprocessing_areva(Min *self) { POST_PROCESSING_AREVA }; static void Min_postprocessing_revai(Min *self) { POST_PROCESSING_REVAI }; static void Min_postprocessing_revaa(Min *self) { POST_PROCESSING_REVAA }; static void Min_postprocessing_revareva(Min *self) { POST_PROCESSING_REVAREVA }; static void Min_setProcMode(Min *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Min_process_i; break; case 1: self->proc_func_ptr = Min_process_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Min_postprocessing_ii; break; case 1: self->muladd_func_ptr = Min_postprocessing_ai; break; case 2: self->muladd_func_ptr = Min_postprocessing_revai; break; case 10: self->muladd_func_ptr = Min_postprocessing_ia; break; case 11: self->muladd_func_ptr = Min_postprocessing_aa; break; case 12: self->muladd_func_ptr = Min_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Min_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Min_postprocessing_areva; break; case 22: self->muladd_func_ptr = Min_postprocessing_revareva; break; } } static void Min_compute_next_data_frame(Min *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Min_traverse(Min *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->comp); Py_VISIT(self->comp_stream); return 0; } static int Min_clear(Min *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->comp); Py_CLEAR(self->comp_stream); return 0; } static void Min_dealloc(Min* self) { pyo_DEALLOC Min_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Min_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *comptmp=NULL, *multmp=NULL, *addtmp=NULL; Min *self; self = (Min *)type->tp_alloc(type, 0); self->comp = PyFloat_FromDouble(0.5); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Min_compute_next_data_frame); self->mode_func_ptr = Min_setProcMode; static char *kwlist[] = {"input", "comp", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &comptmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (comptmp) { PyObject_CallMethod((PyObject *)self, "setComp", "O", comptmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Min_getServer(Min* self) { GET_SERVER }; static PyObject * Min_getStream(Min* self) { GET_STREAM }; static PyObject * Min_setMul(Min *self, PyObject *arg) { SET_MUL }; static PyObject * Min_setAdd(Min *self, PyObject *arg) { SET_ADD }; static PyObject * Min_setSub(Min *self, PyObject *arg) { SET_SUB }; static PyObject * Min_setDiv(Min *self, PyObject *arg) { SET_DIV }; static PyObject * Min_play(Min *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Min_out(Min *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Min_stop(Min *self) { STOP }; static PyObject * Min_multiply(Min *self, PyObject *arg) { MULTIPLY }; static PyObject * Min_inplace_multiply(Min *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Min_add(Min *self, PyObject *arg) { ADD }; static PyObject * Min_inplace_add(Min *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Min_sub(Min *self, PyObject *arg) { SUB }; static PyObject * Min_inplace_sub(Min *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Min_div(Min *self, PyObject *arg) { DIV }; static PyObject * Min_inplace_div(Min *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Min_setComp(Min *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->comp); if (isNumber == 1) { self->comp = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->comp = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->comp, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->comp_stream); self->comp_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Min_members[] = { {"server", T_OBJECT_EX, offsetof(Min, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Min, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Min, input), 0, "Input sound object."}, {"comp", T_OBJECT_EX, offsetof(Min, comp), 0, "Comparator."}, {"mul", T_OBJECT_EX, offsetof(Min, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Min, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Min_methods[] = { {"getServer", (PyCFunction)Min_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Min_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Min_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Min_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Min_stop, METH_NOARGS, "Stops computing."}, {"setComp", (PyCFunction)Min_setComp, METH_O, "Sets comparator."}, {"setMul", (PyCFunction)Min_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Min_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Min_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Min_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Min_as_number = { (binaryfunc)Min_add, /*nb_add*/ (binaryfunc)Min_sub, /*nb_subtract*/ (binaryfunc)Min_multiply, /*nb_multiply*/ (binaryfunc)Min_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Min_inplace_add, /*inplace_add*/ (binaryfunc)Min_inplace_sub, /*inplace_subtract*/ (binaryfunc)Min_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Min_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject MinType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Min_base", /*tp_name*/ sizeof(Min), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Min_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Min_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Min objects. Outputs the minimum of two values.", /* tp_doc */ (traverseproc)Min_traverse, /* tp_traverse */ (inquiry)Min_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Min_methods, /* tp_methods */ Min_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Min_new, /* tp_new */ }; /************/ /* Max */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *comp; Stream *comp_stream; int modebuffer[3]; // need at least 2 slots for mul & add } Max; static void Max_process_i(Max *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT cp = PyFloat_AS_DOUBLE(self->comp); for (i=0; ibufsize; i++) { self->data[i] = in[i] > cp ? in[i] : cp; } } static void Max_process_a(Max *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *cp = Stream_getData((Stream *)self->comp_stream); for (i=0; ibufsize; i++) { self->data[i] = in[i] > cp[i] ? in[i] : cp[i]; } } static void Max_postprocessing_ii(Max *self) { POST_PROCESSING_II }; static void Max_postprocessing_ai(Max *self) { POST_PROCESSING_AI }; static void Max_postprocessing_ia(Max *self) { POST_PROCESSING_IA }; static void Max_postprocessing_aa(Max *self) { POST_PROCESSING_AA }; static void Max_postprocessing_ireva(Max *self) { POST_PROCESSING_IREVA }; static void Max_postprocessing_areva(Max *self) { POST_PROCESSING_AREVA }; static void Max_postprocessing_revai(Max *self) { POST_PROCESSING_REVAI }; static void Max_postprocessing_revaa(Max *self) { POST_PROCESSING_REVAA }; static void Max_postprocessing_revareva(Max *self) { POST_PROCESSING_REVAREVA }; static void Max_setProcMode(Max *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Max_process_i; break; case 1: self->proc_func_ptr = Max_process_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Max_postprocessing_ii; break; case 1: self->muladd_func_ptr = Max_postprocessing_ai; break; case 2: self->muladd_func_ptr = Max_postprocessing_revai; break; case 10: self->muladd_func_ptr = Max_postprocessing_ia; break; case 11: self->muladd_func_ptr = Max_postprocessing_aa; break; case 12: self->muladd_func_ptr = Max_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Max_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Max_postprocessing_areva; break; case 22: self->muladd_func_ptr = Max_postprocessing_revareva; break; } } static void Max_compute_next_data_frame(Max *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Max_traverse(Max *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->comp); Py_VISIT(self->comp_stream); return 0; } static int Max_clear(Max *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->comp); Py_CLEAR(self->comp_stream); return 0; } static void Max_dealloc(Max* self) { pyo_DEALLOC Max_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Max_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *comptmp=NULL, *multmp=NULL, *addtmp=NULL; Max *self; self = (Max *)type->tp_alloc(type, 0); self->comp = PyFloat_FromDouble(0.5); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Max_compute_next_data_frame); self->mode_func_ptr = Max_setProcMode; static char *kwlist[] = {"input", "comp", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &comptmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (comptmp) { PyObject_CallMethod((PyObject *)self, "setComp", "O", comptmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Max_getServer(Max* self) { GET_SERVER }; static PyObject * Max_getStream(Max* self) { GET_STREAM }; static PyObject * Max_setMul(Max *self, PyObject *arg) { SET_MUL }; static PyObject * Max_setAdd(Max *self, PyObject *arg) { SET_ADD }; static PyObject * Max_setSub(Max *self, PyObject *arg) { SET_SUB }; static PyObject * Max_setDiv(Max *self, PyObject *arg) { SET_DIV }; static PyObject * Max_play(Max *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Max_out(Max *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Max_stop(Max *self) { STOP }; static PyObject * Max_multiply(Max *self, PyObject *arg) { MULTIPLY }; static PyObject * Max_inplace_multiply(Max *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Max_add(Max *self, PyObject *arg) { ADD }; static PyObject * Max_inplace_add(Max *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Max_sub(Max *self, PyObject *arg) { SUB }; static PyObject * Max_inplace_sub(Max *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Max_div(Max *self, PyObject *arg) { DIV }; static PyObject * Max_inplace_div(Max *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Max_setComp(Max *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->comp); if (isNumber == 1) { self->comp = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->comp = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->comp, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->comp_stream); self->comp_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Max_members[] = { {"server", T_OBJECT_EX, offsetof(Max, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Max, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Max, input), 0, "Input sound object."}, {"comp", T_OBJECT_EX, offsetof(Max, comp), 0, "Comparator."}, {"mul", T_OBJECT_EX, offsetof(Max, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Max, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Max_methods[] = { {"getServer", (PyCFunction)Max_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Max_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Max_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Max_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Max_stop, METH_NOARGS, "Stops computing."}, {"setComp", (PyCFunction)Max_setComp, METH_O, "Sets comparator."}, {"setMul", (PyCFunction)Max_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Max_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Max_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Max_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Max_as_number = { (binaryfunc)Max_add, /*nb_add*/ (binaryfunc)Max_sub, /*nb_subtract*/ (binaryfunc)Max_multiply, /*nb_multiply*/ (binaryfunc)Max_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Max_inplace_add, /*inplace_add*/ (binaryfunc)Max_inplace_sub, /*inplace_subtract*/ (binaryfunc)Max_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Max_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject MaxType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Max_base", /*tp_name*/ sizeof(Max), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Max_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Max_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Max objects. Outputs the Maximum of two values.", /* tp_doc */ (traverseproc)Max_traverse, /* tp_traverse */ (inquiry)Max_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Max_methods, /* tp_methods */ Max_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Max_new, /* tp_new */ };pyo/src/objects/filtremodule.c0000644000175000017500000150040312652732202015740 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" static MYFLT HALF_COS_ARRAY[513] = {1.0, 0.99998110153278696, 0.99992440684545181, 0.99982991808087995, 0.99969763881045715, 0.99952757403393411, 0.99931973017923825, 0.99907411510222999, 0.99879073808640628, 0.99846960984254973, 0.99811074250832332, 0.99771414964781235, 0.99727984625101107, 0.99680784873325645, 0.99629817493460782, 0.99575084411917214, 0.99516587697437664, 0.99454329561018584, 0.99388312355826691, 0.9931853857710996, 0.99245010862103322, 0.99167731989928998, 0.99086704881491472, 0.99001932599367026, 0.98913418347688054, 0.98821165472021921, 0.9872517745924454, 0.98625457937408512, 0.98522010675606064, 0.98414839583826585, 0.98303948712808786, 0.98189342253887657, 0.98071024538836005, 0.97949000039700762, 0.97823273368633901, 0.9769384927771817, 0.97560732658787452, 0.97423928543241856, 0.97283442101857576, 0.97139278644591409, 0.96991443620380113, 0.96839942616934394, 0.96684781360527761, 0.96525965715780015, 0.96363501685435693, 0.96197395410137099, 0.96027653168192206, 0.95854281375337425, 0.95677286584495025, 0.95496675485525528, 0.95312454904974775, 0.95124631805815985, 0.94933213287186513, 0.94738206584119555, 0.94539619067270686, 0.9433745824263926, 0.94131731751284708, 0.9392244736903772, 0.93709613006206383, 0.9349323670727715, 0.93273326650610799, 0.93049891148133324, 0.92822938645021758, 0.92592477719384991, 0.92358517081939495, 0.92121065575680161, 0.91880132175545981, 0.91635725988080907, 0.91387856251089561, 0.91136532333288145, 0.90881763733950294, 0.9062356008254806, 0.90361931138387919, 0.90096886790241915, 0.89828437055973898, 0.89556592082160869, 0.89281362143709486, 0.89002757643467667, 0.88720789111831455, 0.8843546720634694, 0.88146802711307481, 0.87854806537346075, 0.87559489721022943, 0.8726086342440843, 0.86958938934661101, 0.86653727663601088, 0.86345241147278784, 0.86033491045538835, 0.85718489141579368, 0.85400247341506719, 0.8507877767388532, 0.84754092289283123, 0.8442620345981231, 0.84095123578665476, 0.8376086515964718, 0.83423440836700968, 0.83082863363431847, 0.82739145612624232, 0.82392300575755428, 0.82042341362504534, 0.81689281200256991, 0.81333133433604599, 0.80973911523841147, 0.80611629048453592, 0.80246299700608914, 0.79877937288636502, 0.7950655573550629, 0.79132169078302494, 0.78754791467693042, 0.78374437167394739, 0.77991120553634141, 0.77604856114604148, 0.77215658449916424, 0.76823542270049605, 0.76428522395793219, 0.7603061375768756, 0.75629831395459302, 0.75226190457453135, 0.74819706200059122, 0.7441039398713607, 0.73998269289430851, 0.73583347683993672, 0.73165644853589207, 0.72745176586103977, 0.72321958773949491, 0.71896007413461649, 0.71467338604296105, 0.71035968548819706, 0.70601913551498185, 0.70165190018279788, 0.69725814455975277, 0.69283803471633953, 0.68839173771916018, 0.68391942162461061, 0.6794212554725293, 0.67489740927980701, 0.67034805403396192, 0.66577336168667567, 0.66117350514729512, 0.65654865827629605, 0.65189899587871258, 0.64722469369752944, 0.6425259284070397, 0.63780287760616672, 0.63305571981175202, 0.62828463445180749, 0.62348980185873359, 0.61867140326250347, 0.61382962078381298, 0.60896463742719675, 0.60407663707411186, 0.59916580447598711, 0.59423232524724023, 0.58927638585826192, 0.58429817362836856, 0.57929787671872113, 0.57427568412521424, 0.56923178567133192, 0.56416637200097319, 0.55907963457124654, 0.55397176564523298, 0.5488429582847193, 0.5436934063429012, 0.53852330445705543, 0.53333284804118442, 0.52812223327862839, 0.52289165711465235, 0.51764131724900009, 0.51237141212842374, 0.50708214093918114, 0.50177370359950879, 0.49644630075206486, 0.49110013375634509, 0.48573540468107329, 0.48035231629656205, 0.47495107206705045, 0.46953187614301212, 0.46409493335344021, 0.45864044919810504, 0.45316862983978612, 0.44767968209648135, 0.44217381343358825, 0.43665123195606403, 0.43111214640055828, 0.42555676612752463, 0.41998530111330729, 0.41439796194220363, 0.40879495979850627, 0.40317650645851943, 0.39754281428255606, 0.3918940962069094, 0.38623056573580644, 0.38055243693333718, 0.3748599244153632, 0.36915324334140731, 0.36343260940651945, 0.35769823883312568, 0.35195034836285416, 0.34618915524834432, 0.34041487724503472, 0.33462773260293199, 0.32882794005836308, 0.32301571882570607, 0.31719128858910622, 0.31135486949417079, 0.30550668213964982, 0.29964694756909749, 0.29377588726251663, 0.28789372312798917, 0.28200067749328667, 0.27609697309746906, 0.27018283308246382, 0.26425848098463345, 0.25832414072632598, 0.25238003660741054, 0.24642639329680122, 0.24046343582396335, 0.23449138957040974, 0.22851048026118126, 0.22252093395631445, 0.21652297704229864, 0.21051683622351761, 0.20450273851368242, 0.19848091122724945, 0.19245158197082995, 0.18641497863458675, 0.1803713293836198, 0.17432086264934399, 0.16826380712085329, 0.16220039173627876, 0.15613084567413366, 0.1500553983446527, 0.14397427938112045, 0.13788771863119115, 0.13179594614820278, 0.12569919218247999, 0.11959768717263308, 0.11349166173684638, 0.10738134666416307, 0.10126697290576155, 0.095148771566225324, 0.089026973894809708, 0.082901811276699419, 0.076773515224264705, 0.070642317368309157, 0.064508449449316344, 0.058372143308689985, 0.052233630879990445, 0.046093144180169916, 0.039950915300801082, 0.033807176399306589, 0.027662159690182372, 0.021516097436222258, 0.01536922193973846, 0.0092217655337806046, 0.0030739605733557966, -0.0030739605733554522, -0.0092217655337804832, -0.015369221939738116, -0.021516097436222133, -0.027662159690182025, -0.033807176399306464, -0.039950915300800735, -0.046093144180169791, -0.052233630879990098, -0.05837214330868986, -0.064508449449316232, -0.07064231736830906, -0.076773515224264371, -0.082901811276699308, -0.089026973894809375, -0.095148771566225213, -0.10126697290576121, -0.10738134666416296, -0.11349166173684605, -0.11959768717263299, -0.12569919218247966, -0.13179594614820267, -0.13788771863119104, -0.14397427938112034, -0.15005539834465259, -0.15613084567413354, -0.16220039173627843, -0.16826380712085318, -0.17432086264934366, -0.18037132938361969, -0.18641497863458642, -0.19245158197082984, -0.19848091122724912, -0.20450273851368231, -0.21051683622351727, -0.21652297704229853, -0.22252093395631434, -0.22851048026118118, -0.23449138957040966, -0.24046343582396323, -0.24642639329680088, -0.25238003660741043, -0.25832414072632565, -0.26425848098463334, -0.27018283308246349, -0.27609697309746895, -0.28200067749328633, -0.28789372312798905, -0.2937758872625163, -0.29964694756909738, -0.30550668213964971, -0.31135486949417068, -0.31719128858910589, -0.32301571882570601, -0.32882794005836274, -0.33462773260293188, -0.34041487724503444, -0.3461891552483442, -0.35195034836285388, -0.35769823883312557, -0.36343260940651911, -0.3691532433414072, -0.37485992441536287, -0.38055243693333707, -0.38623056573580633, -0.39189409620690935, -0.39754281428255578, -0.40317650645851938, -0.408794959798506, -0.41439796194220352, -0.41998530111330723, -0.42555676612752458, -0.43111214640055795, -0.43665123195606392, -0.44217381343358819, -0.44767968209648107, -0.45316862983978584, -0.45864044919810493, -0.46409493335344015, -0.46953187614301223, -0.47495107206704995, -0.48035231629656183, -0.4857354046810729, -0.49110013375634509, -0.4964463007520647, -0.50177370359950857, -0.5070821409391808, -0.51237141212842352, -0.51764131724899998, -0.52289165711465191, -0.52812223327862795, -0.53333284804118419, -0.53852330445705532, -0.5436934063429012, -0.54884295828471885, -0.55397176564523276, -0.55907963457124621, -0.56416637200097308, -0.5692317856713317, -0.57427568412521401, -0.57929787671872079, -0.58429817362836844, -0.5892763858582617, -0.5942323252472399, -0.59916580447598666, -0.60407663707411174, -0.60896463742719653, -0.61382962078381298, -0.61867140326250303, -0.62348980185873337, -0.62828463445180716, -0.6330557198117519, -0.6378028776061665, -0.64252592840703937, -0.64722469369752911, -0.65189899587871247, -0.65654865827629583, -0.66117350514729478, -0.66577336168667522, -0.67034805403396169, -0.67489740927980679, -0.6794212554725293, -0.68391942162461028, -0.68839173771915996, -0.6928380347163392, -0.69725814455975266, -0.70165190018279777, -0.70601913551498163, -0.71035968548819683, -0.71467338604296105, -0.71896007413461638, -0.72321958773949468, -0.72745176586103955, -0.73165644853589207, -0.73583347683993661, -0.73998269289430874, -0.74410393987136036, -0.74819706200059111, -0.75226190457453113, -0.75629831395459302, -0.76030613757687548, -0.76428522395793208, -0.76823542270049594, -0.77215658449916424, -0.77604856114604126, -0.77991120553634119, -0.78374437167394717, -0.78754791467693031, -0.79132169078302472, -0.7950655573550629, -0.79877937288636469, -0.80246299700608903, -0.80611629048453581, -0.80973911523841147, -0.81333133433604599, -0.8168928120025698, -0.82042341362504512, -0.82392300575755417, -0.82739145612624221, -0.83082863363431825, -0.83423440836700946, -0.8376086515964718, -0.84095123578665465, -0.8442620345981231, -0.84754092289283089, -0.85078777673885309, -0.85400247341506696, -0.85718489141579368, -0.86033491045538824, -0.86345241147278773, -0.86653727663601066, -0.86958938934661101, -0.87260863424408419, -0.87559489721022921, -0.87854806537346053, -0.88146802711307481, -0.88435467206346929, -0.88720789111831455, -0.89002757643467667, -0.89281362143709475, -0.89556592082160857, -0.89828437055973898, -0.90096886790241903, -0.90361931138387908, -0.90623560082548038, -0.90881763733950294, -0.91136532333288134, -0.9138785625108955, -0.91635725988080885, -0.91880132175545981, -0.92121065575680139, -0.92358517081939495, -0.9259247771938498, -0.92822938645021758, -0.93049891148133312, -0.93273326650610799, -0.9349323670727715, -0.93709613006206383, -0.93922447369037709, -0.94131731751284708, -0.9433745824263926, -0.94539619067270697, -0.94738206584119544, -0.94933213287186502, -0.95124631805815973, -0.95312454904974775, -0.95496675485525517, -0.95677286584495025, -0.95854281375337413, -0.96027653168192206, -0.96197395410137099, -0.96363501685435693, -0.96525965715780004, -0.9668478136052775, -0.96839942616934394, -0.96991443620380113, -0.97139278644591398, -0.97283442101857565, -0.97423928543241844, -0.97560732658787452, -0.9769384927771817, -0.9782327336863389, -0.97949000039700751, -0.98071024538836005, -0.98189342253887657, -0.98303948712808775, -0.98414839583826574, -0.98522010675606064, -0.98625457937408501, -0.9872517745924454, -0.98821165472021921, -0.98913418347688054, -0.99001932599367015, -0.99086704881491472, -0.99167731989928998, -0.99245010862103311, -0.99318538577109949, -0.99388312355826691, -0.99454329561018584, -0.99516587697437653, -0.99575084411917214, -0.99629817493460782, -0.99680784873325645, -0.99727984625101107, -0.99771414964781235, -0.99811074250832332, -0.99846960984254973, -0.99879073808640628, -0.99907411510222999, -0.99931973017923825, -0.99952757403393411, -0.99969763881045715, -0.99982991808087995, -0.99992440684545181, -0.99998110153278685, -1.0, -1.0}; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *q; Stream *q_stream; void (*coeffs_func_ptr)(); int init; int modebuffer[4]; // need at least 2 slots for mul & add int filtertype; MYFLT nyquist; // sample memories MYFLT x1; MYFLT x2; MYFLT y1; MYFLT y2; // variables MYFLT c; MYFLT w0; MYFLT alpha; // coefficients MYFLT b0; MYFLT b1; MYFLT b2; MYFLT a0; MYFLT a1; MYFLT a2; } Biquad; static void Biquad_compute_coeffs_lp(Biquad *self) { self->b0 = self->b2 = (1 - self->c) / 2; self->b1 = 1 - self->c; self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } static void Biquad_compute_coeffs_hp(Biquad *self) { self->b0 = (1 + self->c) / 2; self->b1 = -(1 + self->c); self->b2 = self->b0; self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } static void Biquad_compute_coeffs_bp(Biquad *self) { self->b0 = self->alpha; self->b1 = 0; self->b2 = -self->alpha; self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } static void Biquad_compute_coeffs_bs(Biquad *self) { self->b0 = 1; self->b1 = self->a1 = -2 * self->c; self->b2 = 1; self->a0 = 1 + self->alpha; self->a2 = 1 - self->alpha; } static void Biquad_compute_coeffs_ap(Biquad *self) { self->b0 = self->a2 = 1 - self->alpha; self->b1 = self->a1 = -2 * self->c; self->b2 = self->a0 = 1 + self->alpha; } static void Biquad_compute_variables(Biquad *self, MYFLT freq, MYFLT q) { if (freq <= 1) freq = 1; else if (freq >= self->nyquist) freq = self->nyquist; if (q < 0.1) q = 0.1; self->w0 = TWOPI * freq / self->sr; self->c = MYCOS(self->w0); self->alpha = MYSIN(self->w0) / (2 * q); (*self->coeffs_func_ptr)(self); } static void Biquad_filters_ii(Biquad *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->x1 = self->x2 = self->y1 = self->y2 = in[0]; self->init = 0; } for (i=0; ibufsize; i++) { val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; self->data[i] = val; } } static void Biquad_filters_ai(Biquad *self) { MYFLT val, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->x1 = self->x2 = self->y1 = self->y2 = in[0]; self->init = 0; } MYFLT *fr = Stream_getData((Stream *)self->freq_stream); q = PyFloat_AS_DOUBLE(self->q); for (i=0; ibufsize; i++) { Biquad_compute_variables(self, fr[i], q); val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; self->data[i] = val; } } static void Biquad_filters_ia(Biquad *self) { MYFLT val, fr; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->x1 = self->x2 = self->y1 = self->y2 = in[0]; self->init = 0; } fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *q = Stream_getData((Stream *)self->q_stream); for (i=0; ibufsize; i++) { Biquad_compute_variables(self, fr, q[i]); val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; self->data[i] = val; } } static void Biquad_filters_aa(Biquad *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->x1 = self->x2 = self->y1 = self->y2 = in[0]; self->init = 0; } MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *q = Stream_getData((Stream *)self->q_stream); for (i=0; ibufsize; i++) { Biquad_compute_variables(self, fr[i], q[i]); val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; self->data[i] = val; } } static void Biquad_postprocessing_ii(Biquad *self) { POST_PROCESSING_II }; static void Biquad_postprocessing_ai(Biquad *self) { POST_PROCESSING_AI }; static void Biquad_postprocessing_ia(Biquad *self) { POST_PROCESSING_IA }; static void Biquad_postprocessing_aa(Biquad *self) { POST_PROCESSING_AA }; static void Biquad_postprocessing_ireva(Biquad *self) { POST_PROCESSING_IREVA }; static void Biquad_postprocessing_areva(Biquad *self) { POST_PROCESSING_AREVA }; static void Biquad_postprocessing_revai(Biquad *self) { POST_PROCESSING_REVAI }; static void Biquad_postprocessing_revaa(Biquad *self) { POST_PROCESSING_REVAA }; static void Biquad_postprocessing_revareva(Biquad *self) { POST_PROCESSING_REVAREVA }; static void Biquad_setProcMode(Biquad *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (self->filtertype) { case 0: self->coeffs_func_ptr = Biquad_compute_coeffs_lp; break; case 1: self->coeffs_func_ptr = Biquad_compute_coeffs_hp; break; case 2: self->coeffs_func_ptr = Biquad_compute_coeffs_bp; break; case 3: self->coeffs_func_ptr = Biquad_compute_coeffs_bs; break; case 4: self->coeffs_func_ptr = Biquad_compute_coeffs_ap; break; } switch (procmode) { case 0: Biquad_compute_variables(self, PyFloat_AS_DOUBLE(self->freq), PyFloat_AS_DOUBLE(self->q)); self->proc_func_ptr = Biquad_filters_ii; break; case 1: self->proc_func_ptr = Biquad_filters_ai; break; case 10: self->proc_func_ptr = Biquad_filters_ia; break; case 11: self->proc_func_ptr = Biquad_filters_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Biquad_postprocessing_ii; break; case 1: self->muladd_func_ptr = Biquad_postprocessing_ai; break; case 2: self->muladd_func_ptr = Biquad_postprocessing_revai; break; case 10: self->muladd_func_ptr = Biquad_postprocessing_ia; break; case 11: self->muladd_func_ptr = Biquad_postprocessing_aa; break; case 12: self->muladd_func_ptr = Biquad_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Biquad_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Biquad_postprocessing_areva; break; case 22: self->muladd_func_ptr = Biquad_postprocessing_revareva; break; } } static void Biquad_compute_next_data_frame(Biquad *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Biquad_traverse(Biquad *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->q); Py_VISIT(self->q_stream); return 0; } static int Biquad_clear(Biquad *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->q); Py_CLEAR(self->q_stream); return 0; } static void Biquad_dealloc(Biquad* self) { pyo_DEALLOC Biquad_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Biquad_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *multmp=NULL, *addtmp=NULL; Biquad *self; self = (Biquad *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->q = PyFloat_FromDouble(1); self->filtertype = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->init = 1; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.49; Stream_setFunctionPtr(self->stream, Biquad_compute_next_data_frame); self->mode_func_ptr = Biquad_setProcMode; static char *kwlist[] = {"input", "freq", "q", "type", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOiOO", kwlist, &inputtmp, &freqtmp, &qtmp, &self->filtertype, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (qtmp) { PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Biquad_getServer(Biquad* self) { GET_SERVER }; static PyObject * Biquad_getStream(Biquad* self) { GET_STREAM }; static PyObject * Biquad_setMul(Biquad *self, PyObject *arg) { SET_MUL }; static PyObject * Biquad_setAdd(Biquad *self, PyObject *arg) { SET_ADD }; static PyObject * Biquad_setSub(Biquad *self, PyObject *arg) { SET_SUB }; static PyObject * Biquad_setDiv(Biquad *self, PyObject *arg) { SET_DIV }; static PyObject * Biquad_play(Biquad *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Biquad_out(Biquad *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Biquad_stop(Biquad *self) { STOP }; static PyObject * Biquad_multiply(Biquad *self, PyObject *arg) { MULTIPLY }; static PyObject * Biquad_inplace_multiply(Biquad *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Biquad_add(Biquad *self, PyObject *arg) { ADD }; static PyObject * Biquad_inplace_add(Biquad *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Biquad_sub(Biquad *self, PyObject *arg) { SUB }; static PyObject * Biquad_inplace_sub(Biquad *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Biquad_div(Biquad *self, PyObject *arg) { DIV }; static PyObject * Biquad_inplace_div(Biquad *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Biquad_setFreq(Biquad *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Biquad_setQ(Biquad *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->q); if (isNumber == 1) { self->q = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->q = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->q, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->q_stream); self->q_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Biquad_setType(Biquad *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { self->filtertype = PyInt_AsLong(arg); } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Biquad_members[] = { {"server", T_OBJECT_EX, offsetof(Biquad, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Biquad, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Biquad, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(Biquad, freq), 0, "Cutoff frequency in cycle per second."}, {"q", T_OBJECT_EX, offsetof(Biquad, q), 0, "Q factor."}, {"mul", T_OBJECT_EX, offsetof(Biquad, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Biquad, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Biquad_methods[] = { {"getServer", (PyCFunction)Biquad_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Biquad_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Biquad_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Biquad_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Biquad_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Biquad_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setQ", (PyCFunction)Biquad_setQ, METH_O, "Sets filter Q factor."}, {"setType", (PyCFunction)Biquad_setType, METH_O, "Sets filter type factor."}, {"setMul", (PyCFunction)Biquad_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Biquad_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Biquad_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Biquad_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Biquad_as_number = { (binaryfunc)Biquad_add, /*nb_add*/ (binaryfunc)Biquad_sub, /*nb_subtract*/ (binaryfunc)Biquad_multiply, /*nb_multiply*/ (binaryfunc)Biquad_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Biquad_inplace_add, /*inplace_add*/ (binaryfunc)Biquad_inplace_sub, /*inplace_subtract*/ (binaryfunc)Biquad_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Biquad_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject BiquadType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Biquad_base", /*tp_name*/ sizeof(Biquad), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Biquad_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Biquad_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Biquad objects. Generates a biquadratic filter.", /* tp_doc */ (traverseproc)Biquad_traverse, /* tp_traverse */ (inquiry)Biquad_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Biquad_methods, /* tp_methods */ Biquad_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Biquad_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *q; Stream *q_stream; void (*coeffs_func_ptr)(); int init; int modebuffer[4]; // need at least 2 slots for mul & add int filtertype; int stages; MYFLT nyquist; // sample memories MYFLT *x1; MYFLT *x2; MYFLT *y1; MYFLT *y2; // variables MYFLT c; MYFLT w0; MYFLT alpha; // coefficients MYFLT b0; MYFLT b1; MYFLT b2; MYFLT a0; MYFLT a1; MYFLT a2; } Biquadx; static void Biquadx_allocate_memories(Biquadx *self) { self->x1 = (MYFLT *)realloc(self->x1, self->stages * sizeof(MYFLT)); self->x2 = (MYFLT *)realloc(self->x2, self->stages * sizeof(MYFLT)); self->y1 = (MYFLT *)realloc(self->y1, self->stages * sizeof(MYFLT)); self->y2 = (MYFLT *)realloc(self->y2, self->stages * sizeof(MYFLT)); self->init = 1; } static void Biquadx_compute_coeffs_lp(Biquadx *self) { self->b0 = self->b2 = (1 - self->c) / 2; self->b1 = 1 - self->c; self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } static void Biquadx_compute_coeffs_hp(Biquadx *self) { self->b0 = (1 + self->c) / 2; self->b1 = -(1 + self->c); self->b2 = self->b0; self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } static void Biquadx_compute_coeffs_bp(Biquadx *self) { self->b0 = self->alpha; self->b1 = 0; self->b2 = -self->alpha; self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } static void Biquadx_compute_coeffs_bs(Biquadx *self) { self->b0 = 1; self->b1 = self->a1 = -2 * self->c; self->b2 = 1; self->a0 = 1 + self->alpha; self->a2 = 1 - self->alpha; } static void Biquadx_compute_coeffs_ap(Biquadx *self) { self->b0 = self->a2 = 1 - self->alpha; self->b1 = self->a1 = -2 * self->c; self->b2 = self->a0 = 1 + self->alpha; } static void Biquadx_compute_variables(Biquadx *self, MYFLT freq, MYFLT q) { if (freq <= 1) freq = 1; else if (freq >= self->nyquist) freq = self->nyquist; if (q < 0.1) q = 0.1; self->w0 = TWOPI * freq / self->sr; self->c = MYCOS(self->w0); self->alpha = MYSIN(self->w0) / (2 * q); (*self->coeffs_func_ptr)(self); } static void Biquadx_filters_ii(Biquadx *self) { MYFLT vin, vout; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { for (i=0; istages; i++) { self->x1[i] = self->x2[i] = self->y1[i] = self->y2[i] = in[0]; } self->init = 0; } vout = 0.0; for (i=0; ibufsize; i++) { vin = in[i]; for (j=0; jstages; j++) { vout = ( (self->b0 * vin) + (self->b1 * self->x1[j]) + (self->b2 * self->x2[j]) - (self->a1 * self->y1[j]) - (self->a2 * self->y2[j]) ) / self->a0; self->x2[j] = self->x1[j]; self->x1[j] = vin; self->y2[j] = self->y1[j]; self->y1[j] = vin = vout; } self->data[i] = vout; } } static void Biquadx_filters_ai(Biquadx *self) { MYFLT vin, vout, q; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { for (i=0; istages; i++) { self->x1[i] = self->x2[i] = self->y1[i] = self->y2[i] = in[0]; } self->init = 0; } MYFLT *fr = Stream_getData((Stream *)self->freq_stream); q = PyFloat_AS_DOUBLE(self->q); vout = 0.0; for (i=0; ibufsize; i++) { Biquadx_compute_variables(self, fr[i], q); vin = in[i]; for (j=0; jstages; j++) { vout = ( (self->b0 * vin) + (self->b1 * self->x1[j]) + (self->b2 * self->x2[j]) - (self->a1 * self->y1[j]) - (self->a2 * self->y2[j]) ) / self->a0; self->x2[j] = self->x1[j]; self->x1[j] = vin; self->y2[j] = self->y1[j]; self->y1[j] = vin = vout; } self->data[i] = vout; } } static void Biquadx_filters_ia(Biquadx *self) { MYFLT vin, vout, fr; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { for (i=0; istages; i++) { self->x1[i] = self->x2[i] = self->y1[i] = self->y2[i] = in[0]; } self->init = 0; } fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *q = Stream_getData((Stream *)self->q_stream); vout = 0.0; for (i=0; ibufsize; i++) { Biquadx_compute_variables(self, fr, q[i]); vin = in[i]; for (j=0; jstages; j++) { vout = ( (self->b0 * vin) + (self->b1 * self->x1[j]) + (self->b2 * self->x2[j]) - (self->a1 * self->y1[j]) - (self->a2 * self->y2[j]) ) / self->a0; self->x2[j] = self->x1[j]; self->x1[j] = vin; self->y2[j] = self->y1[j]; self->y1[j] = vin = vout; } self->data[i] = vout; } } static void Biquadx_filters_aa(Biquadx *self) { MYFLT vin, vout; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { for (i=0; istages; i++) { self->x1[i] = self->x2[i] = self->y1[i] = self->y2[i] = in[0]; } self->init = 0; } MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *q = Stream_getData((Stream *)self->q_stream); vout = 0.0; for (i=0; ibufsize; i++) { Biquadx_compute_variables(self, fr[i], q[i]); vin = in[i]; for (j=0; jstages; j++) { vout = ( (self->b0 * vin) + (self->b1 * self->x1[j]) + (self->b2 * self->x2[j]) - (self->a1 * self->y1[j]) - (self->a2 * self->y2[j]) ) / self->a0; self->x2[j] = self->x1[j]; self->x1[j] = vin; self->y2[j] = self->y1[j]; self->y1[j] = vin = vout; } self->data[i] = vout; } } static void Biquadx_postprocessing_ii(Biquadx *self) { POST_PROCESSING_II }; static void Biquadx_postprocessing_ai(Biquadx *self) { POST_PROCESSING_AI }; static void Biquadx_postprocessing_ia(Biquadx *self) { POST_PROCESSING_IA }; static void Biquadx_postprocessing_aa(Biquadx *self) { POST_PROCESSING_AA }; static void Biquadx_postprocessing_ireva(Biquadx *self) { POST_PROCESSING_IREVA }; static void Biquadx_postprocessing_areva(Biquadx *self) { POST_PROCESSING_AREVA }; static void Biquadx_postprocessing_revai(Biquadx *self) { POST_PROCESSING_REVAI }; static void Biquadx_postprocessing_revaa(Biquadx *self) { POST_PROCESSING_REVAA }; static void Biquadx_postprocessing_revareva(Biquadx *self) { POST_PROCESSING_REVAREVA }; static void Biquadx_setProcMode(Biquadx *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (self->filtertype) { case 0: self->coeffs_func_ptr = Biquadx_compute_coeffs_lp; break; case 1: self->coeffs_func_ptr = Biquadx_compute_coeffs_hp; break; case 2: self->coeffs_func_ptr = Biquadx_compute_coeffs_bp; break; case 3: self->coeffs_func_ptr = Biquadx_compute_coeffs_bs; break; case 4: self->coeffs_func_ptr = Biquadx_compute_coeffs_ap; break; } switch (procmode) { case 0: Biquadx_compute_variables(self, PyFloat_AS_DOUBLE(self->freq), PyFloat_AS_DOUBLE(self->q)); self->proc_func_ptr = Biquadx_filters_ii; break; case 1: self->proc_func_ptr = Biquadx_filters_ai; break; case 10: self->proc_func_ptr = Biquadx_filters_ia; break; case 11: self->proc_func_ptr = Biquadx_filters_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Biquadx_postprocessing_ii; break; case 1: self->muladd_func_ptr = Biquadx_postprocessing_ai; break; case 2: self->muladd_func_ptr = Biquadx_postprocessing_revai; break; case 10: self->muladd_func_ptr = Biquadx_postprocessing_ia; break; case 11: self->muladd_func_ptr = Biquadx_postprocessing_aa; break; case 12: self->muladd_func_ptr = Biquadx_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Biquadx_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Biquadx_postprocessing_areva; break; case 22: self->muladd_func_ptr = Biquadx_postprocessing_revareva; break; } } static void Biquadx_compute_next_data_frame(Biquadx *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Biquadx_traverse(Biquadx *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->q); Py_VISIT(self->q_stream); return 0; } static int Biquadx_clear(Biquadx *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->q); Py_CLEAR(self->q_stream); return 0; } static void Biquadx_dealloc(Biquadx* self) { pyo_DEALLOC free(self->x1); free(self->x2); free(self->y1); free(self->y2); Biquadx_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Biquadx_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *multmp=NULL, *addtmp=NULL; Biquadx *self; self = (Biquadx *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->q = PyFloat_FromDouble(1); self->filtertype = 0; self->stages = 4; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->init = 1; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.49; Stream_setFunctionPtr(self->stream, Biquadx_compute_next_data_frame); self->mode_func_ptr = Biquadx_setProcMode; static char *kwlist[] = {"input", "freq", "q", "type", "stages", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOiiOO", kwlist, &inputtmp, &freqtmp, &qtmp, &self->filtertype, &self->stages, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (qtmp) { PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Biquadx_allocate_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Biquadx_getServer(Biquadx* self) { GET_SERVER }; static PyObject * Biquadx_getStream(Biquadx* self) { GET_STREAM }; static PyObject * Biquadx_setMul(Biquadx *self, PyObject *arg) { SET_MUL }; static PyObject * Biquadx_setAdd(Biquadx *self, PyObject *arg) { SET_ADD }; static PyObject * Biquadx_setSub(Biquadx *self, PyObject *arg) { SET_SUB }; static PyObject * Biquadx_setDiv(Biquadx *self, PyObject *arg) { SET_DIV }; static PyObject * Biquadx_play(Biquadx *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Biquadx_out(Biquadx *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Biquadx_stop(Biquadx *self) { STOP }; static PyObject * Biquadx_multiply(Biquadx *self, PyObject *arg) { MULTIPLY }; static PyObject * Biquadx_inplace_multiply(Biquadx *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Biquadx_add(Biquadx *self, PyObject *arg) { ADD }; static PyObject * Biquadx_inplace_add(Biquadx *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Biquadx_sub(Biquadx *self, PyObject *arg) { SUB }; static PyObject * Biquadx_inplace_sub(Biquadx *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Biquadx_div(Biquadx *self, PyObject *arg) { DIV }; static PyObject * Biquadx_inplace_div(Biquadx *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Biquadx_setFreq(Biquadx *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Biquadx_setQ(Biquadx *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->q); if (isNumber == 1) { self->q = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->q = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->q, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->q_stream); self->q_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Biquadx_setType(Biquadx *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { self->filtertype = PyInt_AsLong(arg); } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Biquadx_setStages(Biquadx *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { self->stages = PyInt_AsLong(arg); Biquadx_allocate_memories(self); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Biquadx_members[] = { {"server", T_OBJECT_EX, offsetof(Biquadx, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Biquadx, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Biquadx, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(Biquadx, freq), 0, "Cutoff frequency in cycle per second."}, {"q", T_OBJECT_EX, offsetof(Biquadx, q), 0, "Q factor."}, {"mul", T_OBJECT_EX, offsetof(Biquadx, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Biquadx, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Biquadx_methods[] = { {"getServer", (PyCFunction)Biquadx_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Biquadx_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Biquadx_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Biquadx_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Biquadx_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Biquadx_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setQ", (PyCFunction)Biquadx_setQ, METH_O, "Sets filter Q factor."}, {"setType", (PyCFunction)Biquadx_setType, METH_O, "Sets filter type factor."}, {"setStages", (PyCFunction)Biquadx_setStages, METH_O, "Sets the number of filtering stages."}, {"setMul", (PyCFunction)Biquadx_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Biquadx_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Biquadx_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Biquadx_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Biquadx_as_number = { (binaryfunc)Biquadx_add, /*nb_add*/ (binaryfunc)Biquadx_sub, /*nb_subtract*/ (binaryfunc)Biquadx_multiply, /*nb_multiply*/ (binaryfunc)Biquadx_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Biquadx_inplace_add, /*inplace_add*/ (binaryfunc)Biquadx_inplace_sub, /*inplace_subtract*/ (binaryfunc)Biquadx_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Biquadx_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject BiquadxType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Biquadx_base", /*tp_name*/ sizeof(Biquadx), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Biquadx_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Biquadx_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Biquadx objects. Generates a biquadratic filter.", /* tp_doc */ (traverseproc)Biquadx_traverse, /* tp_traverse */ (inquiry)Biquadx_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Biquadx_methods, /* tp_methods */ Biquadx_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Biquadx_new, /* tp_new */ }; /*** Biquad filter with direct coefficient control ***/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; // coefficients Stream *b0_stream; Stream *b1_stream; Stream *b2_stream; Stream *a0_stream; Stream *a1_stream; Stream *a2_stream; int init; int modebuffer[2]; // need at least 2 slots for mul & add // sample memories MYFLT x1; MYFLT x2; MYFLT y1; MYFLT y2; } Biquada; static void Biquada_filters(Biquada *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *b0 = Stream_getData((Stream *)self->b0_stream); MYFLT *b1 = Stream_getData((Stream *)self->b1_stream); MYFLT *b2 = Stream_getData((Stream *)self->b2_stream); MYFLT *a0 = Stream_getData((Stream *)self->a0_stream); MYFLT *a1 = Stream_getData((Stream *)self->a1_stream); MYFLT *a2 = Stream_getData((Stream *)self->a2_stream); if (self->init == 1) { self->x1 = self->x2 = self->y1 = self->y2 = in[0]; self->init = 0; } for (i=0; ibufsize; i++) { val = ( (b0[i] * in[i]) + (b1[i] * self->x1) + (b2[i] * self->x2) - (a1[i] * self->y1) - (a2[i] * self->y2) ) / a0[i]; self->y2 = self->y1; self->data[i] = self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; } } static void Biquada_postprocessing_ii(Biquada *self) { POST_PROCESSING_II }; static void Biquada_postprocessing_ai(Biquada *self) { POST_PROCESSING_AI }; static void Biquada_postprocessing_ia(Biquada *self) { POST_PROCESSING_IA }; static void Biquada_postprocessing_aa(Biquada *self) { POST_PROCESSING_AA }; static void Biquada_postprocessing_ireva(Biquada *self) { POST_PROCESSING_IREVA }; static void Biquada_postprocessing_areva(Biquada *self) { POST_PROCESSING_AREVA }; static void Biquada_postprocessing_revai(Biquada *self) { POST_PROCESSING_REVAI }; static void Biquada_postprocessing_revaa(Biquada *self) { POST_PROCESSING_REVAA }; static void Biquada_postprocessing_revareva(Biquada *self) { POST_PROCESSING_REVAREVA }; static void Biquada_setProcMode(Biquada *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Biquada_filters; switch (muladdmode) { case 0: self->muladd_func_ptr = Biquada_postprocessing_ii; break; case 1: self->muladd_func_ptr = Biquada_postprocessing_ai; break; case 2: self->muladd_func_ptr = Biquada_postprocessing_revai; break; case 10: self->muladd_func_ptr = Biquada_postprocessing_ia; break; case 11: self->muladd_func_ptr = Biquada_postprocessing_aa; break; case 12: self->muladd_func_ptr = Biquada_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Biquada_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Biquada_postprocessing_areva; break; case 22: self->muladd_func_ptr = Biquada_postprocessing_revareva; break; } } static void Biquada_compute_next_data_frame(Biquada *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Biquada_traverse(Biquada *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->b0_stream); Py_VISIT(self->b1_stream); Py_VISIT(self->b2_stream); Py_VISIT(self->a0_stream); Py_VISIT(self->a1_stream); Py_VISIT(self->a2_stream); return 0; } static int Biquada_clear(Biquada *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->b0_stream); Py_CLEAR(self->b1_stream); Py_CLEAR(self->b2_stream); Py_CLEAR(self->a0_stream); Py_CLEAR(self->a1_stream); Py_CLEAR(self->a2_stream); return 0; } static void Biquada_dealloc(Biquada* self) { pyo_DEALLOC Biquada_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Biquada_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *b0tmp, *b1tmp, *b2tmp, *a0tmp, *a1tmp, *a2tmp, *multmp=NULL, *addtmp=NULL; Biquada *self; self = (Biquada *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->init = 1; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Biquada_compute_next_data_frame); self->mode_func_ptr = Biquada_setProcMode; static char *kwlist[] = {"input", "b0", "b1", "b2", "a0", "a1", "a2", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOO", kwlist, &inputtmp, &b0tmp, &b1tmp, &b2tmp, &a0tmp, &a1tmp, &a2tmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (b0tmp) PyObject_CallMethod((PyObject *)self, "setB0", "O", b0tmp); if (b1tmp) PyObject_CallMethod((PyObject *)self, "setB1", "O", b1tmp); if (b2tmp) PyObject_CallMethod((PyObject *)self, "setB2", "O", b2tmp); if (a0tmp) PyObject_CallMethod((PyObject *)self, "setA0", "O", a0tmp); if (a1tmp) PyObject_CallMethod((PyObject *)self, "setA1", "O", a1tmp); if (a2tmp) PyObject_CallMethod((PyObject *)self, "setA2", "O", a2tmp); if (multmp) PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); if (addtmp) PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Biquada_getServer(Biquada* self) { GET_SERVER }; static PyObject * Biquada_getStream(Biquada* self) { GET_STREAM }; static PyObject * Biquada_setMul(Biquada *self, PyObject *arg) { SET_MUL }; static PyObject * Biquada_setAdd(Biquada *self, PyObject *arg) { SET_ADD }; static PyObject * Biquada_setSub(Biquada *self, PyObject *arg) { SET_SUB }; static PyObject * Biquada_setDiv(Biquada *self, PyObject *arg) { SET_DIV }; static PyObject * Biquada_play(Biquada *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Biquada_out(Biquada *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Biquada_stop(Biquada *self) { STOP }; static PyObject * Biquada_multiply(Biquada *self, PyObject *arg) { MULTIPLY }; static PyObject * Biquada_inplace_multiply(Biquada *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Biquada_add(Biquada *self, PyObject *arg) { ADD }; static PyObject * Biquada_inplace_add(Biquada *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Biquada_sub(Biquada *self, PyObject *arg) { SUB }; static PyObject * Biquada_inplace_sub(Biquada *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Biquada_div(Biquada *self, PyObject *arg) { DIV }; static PyObject * Biquada_inplace_div(Biquada *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Biquada_setB0(Biquada *self, PyObject *arg) { PyObject *streamtmp; ASSERT_ARG_NOT_NULL streamtmp = PyObject_CallMethod((PyObject *)arg, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->b0_stream); self->b0_stream = (Stream *)streamtmp; Py_RETURN_NONE; } static PyObject * Biquada_setB1(Biquada *self, PyObject *arg) { PyObject *streamtmp; ASSERT_ARG_NOT_NULL streamtmp = PyObject_CallMethod((PyObject *)arg, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->b1_stream); self->b1_stream = (Stream *)streamtmp; Py_RETURN_NONE; } static PyObject * Biquada_setB2(Biquada *self, PyObject *arg) { PyObject *streamtmp; ASSERT_ARG_NOT_NULL streamtmp = PyObject_CallMethod((PyObject *)arg, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->b2_stream); self->b2_stream = (Stream *)streamtmp; Py_RETURN_NONE; } static PyObject * Biquada_setA0(Biquada *self, PyObject *arg) { PyObject *streamtmp; ASSERT_ARG_NOT_NULL streamtmp = PyObject_CallMethod((PyObject *)arg, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->a0_stream); self->a0_stream = (Stream *)streamtmp; Py_RETURN_NONE; } static PyObject * Biquada_setA1(Biquada *self, PyObject *arg) { PyObject *streamtmp; ASSERT_ARG_NOT_NULL streamtmp = PyObject_CallMethod((PyObject *)arg, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->a1_stream); self->a1_stream = (Stream *)streamtmp; Py_RETURN_NONE; } static PyObject * Biquada_setA2(Biquada *self, PyObject *arg) { PyObject *streamtmp; ASSERT_ARG_NOT_NULL streamtmp = PyObject_CallMethod((PyObject *)arg, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->a2_stream); self->a2_stream = (Stream *)streamtmp; Py_RETURN_NONE; } static PyMemberDef Biquada_members[] = { {"server", T_OBJECT_EX, offsetof(Biquada, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Biquada, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Biquada, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(Biquada, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Biquada, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Biquada_methods[] = { {"getServer", (PyCFunction)Biquada_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Biquada_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Biquada_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Biquada_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Biquada_stop, METH_NOARGS, "Stops computing."}, {"setB0", (PyCFunction)Biquada_setB0, METH_O, "Sets b0 coefficient."}, {"setB1", (PyCFunction)Biquada_setB1, METH_O, "Sets b1 coefficient."}, {"setB2", (PyCFunction)Biquada_setB2, METH_O, "Sets b2 coefficient."}, {"setA0", (PyCFunction)Biquada_setA0, METH_O, "Sets a0 coefficient."}, {"setA1", (PyCFunction)Biquada_setA1, METH_O, "Sets a1 coefficient."}, {"setA2", (PyCFunction)Biquada_setA2, METH_O, "Sets a2 coefficient."}, {"setMul", (PyCFunction)Biquada_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Biquada_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Biquada_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Biquada_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Biquada_as_number = { (binaryfunc)Biquada_add, /*nb_add*/ (binaryfunc)Biquada_sub, /*nb_subtract*/ (binaryfunc)Biquada_multiply, /*nb_multiply*/ (binaryfunc)Biquada_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Biquada_inplace_add, /*inplace_add*/ (binaryfunc)Biquada_inplace_sub, /*inplace_subtract*/ (binaryfunc)Biquada_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Biquada_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject BiquadaType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Biquada_base", /*tp_name*/ sizeof(Biquada), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Biquada_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Biquada_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Biquada objects. Generates a biquadratic filter with direct coefficient control.", /* tp_doc */ (traverseproc)Biquada_traverse, /* tp_traverse */ (inquiry)Biquada_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Biquada_methods, /* tp_methods */ Biquada_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Biquada_new, /* tp_new */ }; /*** Typical EQ filter ***/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *q; Stream *q_stream; PyObject *boost; Stream *boost_stream; void (*coeffs_func_ptr)(); int init; int modebuffer[5]; // need at least 2 slots for mul & add int filtertype; MYFLT nyquist; // sample memories MYFLT x1; MYFLT x2; MYFLT y1; MYFLT y2; // variables MYFLT A; MYFLT c; MYFLT w0; MYFLT alpha; // coefficients MYFLT b0; MYFLT b1; MYFLT b2; MYFLT a0; MYFLT a1; MYFLT a2; } EQ; static void EQ_compute_coeffs_peak(EQ *self) { MYFLT alphaMul = self->alpha * self->A; MYFLT alphaDiv = self->alpha / self->A; self->b0 = 1.0 + alphaMul; self->b1 = self->a1 = -2.0 * self->c; self->b2 = 1.0 - alphaMul; self->a0 = 1.0 + alphaDiv; self->a2 = 1.0 - alphaDiv; } static void EQ_compute_coeffs_lowshelf(EQ *self) { MYFLT twoSqrtAAlpha = MYSQRT(self->A * 2.0)*self->alpha; MYFLT AminOneC = (self->A - 1.0) * self->c; MYFLT AAddOneC = (self->A + 1.0) * self->c; self->b0 = self->A * ((self->A + 1.0) - AminOneC + twoSqrtAAlpha); self->b1 = 2.0 * self->A * ((self->A - 1.0) - AAddOneC); self->b2 = self->A * ((self->A + 1.0) - AminOneC - twoSqrtAAlpha); self->a0 = (self->A + 1.0) + AminOneC + twoSqrtAAlpha; self->a1 = -2.0 * ((self->A - 1.0) + AAddOneC); self->a2 = (self->A + 1.0) + AminOneC - twoSqrtAAlpha; } static void EQ_compute_coeffs_highshelf(EQ *self) { MYFLT twoSqrtAAlpha = MYSQRT(self->A * 2.0)*self->alpha; MYFLT AminOneC = (self->A - 1.0) * self->c; MYFLT AAddOneC = (self->A + 1.0) * self->c; self->b0 = self->A * ((self->A + 1.0) + AminOneC + twoSqrtAAlpha); self->b1 = -2.0 * self->A * ((self->A - 1.0) + AAddOneC); self->b2 = self->A * ((self->A + 1.0) + AminOneC - twoSqrtAAlpha); self->a0 = (self->A + 1.0) - AminOneC + twoSqrtAAlpha; self->a1 = 2.0 * ((self->A - 1.0) - AAddOneC); self->a2 = (self->A + 1.0) - AminOneC - twoSqrtAAlpha; } static void EQ_compute_variables(EQ *self, MYFLT freq, MYFLT q, MYFLT boost) { if (freq <= 1) freq = 1; else if (freq >= self->nyquist) freq = self->nyquist; self->A = MYPOW(10.0, boost/40.0); self->w0 = TWOPI * freq / self->sr; self->c = MYCOS(self->w0); self->alpha = MYSIN(self->w0) / (2 * q); (*self->coeffs_func_ptr)(self); } static void EQ_filters_iii(EQ *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->x1 = self->x2 = self->y1 = self->y2 = in[0]; self->init = 0; } for (i=0; ibufsize; i++) { val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; self->data[i] = val; } } static void EQ_filters_aii(EQ *self) { MYFLT val, q, boost; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->x1 = self->x2 = self->y1 = self->y2 = in[0]; self->init = 0; } MYFLT *fr = Stream_getData((Stream *)self->freq_stream); q = PyFloat_AS_DOUBLE(self->q); boost = PyFloat_AS_DOUBLE(self->boost); for (i=0; ibufsize; i++) { EQ_compute_variables(self, fr[i], q, boost); val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; self->data[i] = val; } } static void EQ_filters_iai(EQ *self) { MYFLT val, fr, boost; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->x1 = self->x2 = self->y1 = self->y2 = in[0]; self->init = 0; } fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *q = Stream_getData((Stream *)self->q_stream); boost = PyFloat_AS_DOUBLE(self->boost); for (i=0; ibufsize; i++) { EQ_compute_variables(self, fr, q[i], boost); val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; self->data[i] = val; } } static void EQ_filters_aai(EQ *self) { MYFLT val, boost; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->x1 = self->x2 = self->y1 = self->y2 = in[0]; self->init = 0; } MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *q = Stream_getData((Stream *)self->q_stream); boost = PyFloat_AS_DOUBLE(self->boost); for (i=0; ibufsize; i++) { EQ_compute_variables(self, fr[i], q[i], boost); val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; self->data[i] = val; } } static void EQ_filters_iia(EQ *self) { MYFLT val, fr, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->x1 = self->x2 = self->y1 = self->y2 = in[0]; self->init = 0; } fr = PyFloat_AS_DOUBLE(self->freq); q = PyFloat_AS_DOUBLE(self->q); MYFLT *boost = Stream_getData((Stream *)self->boost_stream); for (i=0; ibufsize; i++) { EQ_compute_variables(self, fr, q, boost[i]); val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; self->data[i] = val; } } static void EQ_filters_aia(EQ *self) { MYFLT val, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->x1 = self->x2 = self->y1 = self->y2 = in[0]; self->init = 0; } MYFLT *fr = Stream_getData((Stream *)self->freq_stream); q = PyFloat_AS_DOUBLE(self->q); MYFLT *boost = Stream_getData((Stream *)self->boost_stream); for (i=0; ibufsize; i++) { EQ_compute_variables(self, fr[i], q, boost[i]); val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; self->data[i] = val; } } static void EQ_filters_iaa(EQ *self) { MYFLT val, fr; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->x1 = self->x2 = self->y1 = self->y2 = in[0]; self->init = 0; } fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *q = Stream_getData((Stream *)self->q_stream); MYFLT *boost = Stream_getData((Stream *)self->boost_stream); for (i=0; ibufsize; i++) { EQ_compute_variables(self, fr, q[i], boost[i]); val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; self->data[i] = val; } } static void EQ_filters_aaa(EQ *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->x1 = self->x2 = self->y1 = self->y2 = in[0]; self->init = 0; } MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *q = Stream_getData((Stream *)self->q_stream); MYFLT *boost = Stream_getData((Stream *)self->boost_stream); for (i=0; ibufsize; i++) { EQ_compute_variables(self, fr[i], q[i], boost[i]); val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; self->data[i] = val; } } static void EQ_postprocessing_ii(EQ *self) { POST_PROCESSING_II }; static void EQ_postprocessing_ai(EQ *self) { POST_PROCESSING_AI }; static void EQ_postprocessing_ia(EQ *self) { POST_PROCESSING_IA }; static void EQ_postprocessing_aa(EQ *self) { POST_PROCESSING_AA }; static void EQ_postprocessing_ireva(EQ *self) { POST_PROCESSING_IREVA }; static void EQ_postprocessing_areva(EQ *self) { POST_PROCESSING_AREVA }; static void EQ_postprocessing_revai(EQ *self) { POST_PROCESSING_REVAI }; static void EQ_postprocessing_revaa(EQ *self) { POST_PROCESSING_REVAA }; static void EQ_postprocessing_revareva(EQ *self) { POST_PROCESSING_REVAREVA }; static void EQ_setProcMode(EQ *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (self->filtertype) { case 0: self->coeffs_func_ptr = EQ_compute_coeffs_peak; break; case 1: self->coeffs_func_ptr = EQ_compute_coeffs_lowshelf; break; case 2: self->coeffs_func_ptr = EQ_compute_coeffs_highshelf; break; } switch (procmode) { case 0: EQ_compute_variables(self, PyFloat_AS_DOUBLE(self->freq), PyFloat_AS_DOUBLE(self->q), PyFloat_AS_DOUBLE(self->boost)); self->proc_func_ptr = EQ_filters_iii; break; case 1: self->proc_func_ptr = EQ_filters_aii; break; case 10: self->proc_func_ptr = EQ_filters_iai; break; case 11: self->proc_func_ptr = EQ_filters_aai; break; case 100: self->proc_func_ptr = EQ_filters_iia; break; case 101: self->proc_func_ptr = EQ_filters_aia; break; case 110: self->proc_func_ptr = EQ_filters_iaa; break; case 111: self->proc_func_ptr = EQ_filters_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = EQ_postprocessing_ii; break; case 1: self->muladd_func_ptr = EQ_postprocessing_ai; break; case 2: self->muladd_func_ptr = EQ_postprocessing_revai; break; case 10: self->muladd_func_ptr = EQ_postprocessing_ia; break; case 11: self->muladd_func_ptr = EQ_postprocessing_aa; break; case 12: self->muladd_func_ptr = EQ_postprocessing_revaa; break; case 20: self->muladd_func_ptr = EQ_postprocessing_ireva; break; case 21: self->muladd_func_ptr = EQ_postprocessing_areva; break; case 22: self->muladd_func_ptr = EQ_postprocessing_revareva; break; } } static void EQ_compute_next_data_frame(EQ *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int EQ_traverse(EQ *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->q); Py_VISIT(self->q_stream); Py_VISIT(self->boost); Py_VISIT(self->boost_stream); return 0; } static int EQ_clear(EQ *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->q); Py_CLEAR(self->q_stream); Py_CLEAR(self->boost); Py_CLEAR(self->boost_stream); return 0; } static void EQ_dealloc(EQ* self) { pyo_DEALLOC EQ_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * EQ_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *boosttmp=NULL, *multmp=NULL, *addtmp=NULL; EQ *self; self = (EQ *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->q = PyFloat_FromDouble(1); self->boost = PyFloat_FromDouble(-3.0); self->filtertype = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->init = 1; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.49; Stream_setFunctionPtr(self->stream, EQ_compute_next_data_frame); self->mode_func_ptr = EQ_setProcMode; static char *kwlist[] = {"input", "freq", "q", "boost", "type", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOiOO", kwlist, &inputtmp, &freqtmp, &qtmp, &boosttmp, &self->filtertype, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (qtmp) { PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp); } if (boosttmp) { PyObject_CallMethod((PyObject *)self, "setBoost", "O", boosttmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * EQ_getServer(EQ* self) { GET_SERVER }; static PyObject * EQ_getStream(EQ* self) { GET_STREAM }; static PyObject * EQ_setMul(EQ *self, PyObject *arg) { SET_MUL }; static PyObject * EQ_setAdd(EQ *self, PyObject *arg) { SET_ADD }; static PyObject * EQ_setSub(EQ *self, PyObject *arg) { SET_SUB }; static PyObject * EQ_setDiv(EQ *self, PyObject *arg) { SET_DIV }; static PyObject * EQ_play(EQ *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * EQ_out(EQ *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * EQ_stop(EQ *self) { STOP }; static PyObject * EQ_multiply(EQ *self, PyObject *arg) { MULTIPLY }; static PyObject * EQ_inplace_multiply(EQ *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * EQ_add(EQ *self, PyObject *arg) { ADD }; static PyObject * EQ_inplace_add(EQ *self, PyObject *arg) { INPLACE_ADD }; static PyObject * EQ_sub(EQ *self, PyObject *arg) { SUB }; static PyObject * EQ_inplace_sub(EQ *self, PyObject *arg) { INPLACE_SUB }; static PyObject * EQ_div(EQ *self, PyObject *arg) { DIV }; static PyObject * EQ_inplace_div(EQ *self, PyObject *arg) { INPLACE_DIV }; static PyObject * EQ_setFreq(EQ *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * EQ_setQ(EQ *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->q); if (isNumber == 1) { self->q = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->q = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->q, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->q_stream); self->q_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * EQ_setBoost(EQ *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->boost); if (isNumber == 1) { self->boost = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->boost = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->boost, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->boost_stream); self->boost_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * EQ_setType(EQ *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { self->filtertype = PyInt_AsLong(arg); } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef EQ_members[] = { {"server", T_OBJECT_EX, offsetof(EQ, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(EQ, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(EQ, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(EQ, freq), 0, "Cutoff frequency in cycle per second."}, {"q", T_OBJECT_EX, offsetof(EQ, q), 0, "Q factor."}, {"boost", T_OBJECT_EX, offsetof(EQ, boost), 0, "Boost factor."}, {"mul", T_OBJECT_EX, offsetof(EQ, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(EQ, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef EQ_methods[] = { {"getServer", (PyCFunction)EQ_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)EQ_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)EQ_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)EQ_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)EQ_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)EQ_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setQ", (PyCFunction)EQ_setQ, METH_O, "Sets filter Q factor."}, {"setBoost", (PyCFunction)EQ_setBoost, METH_O, "Sets filter boost factor."}, {"setType", (PyCFunction)EQ_setType, METH_O, "Sets filter type factor."}, {"setMul", (PyCFunction)EQ_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)EQ_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)EQ_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)EQ_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods EQ_as_number = { (binaryfunc)EQ_add, /*nb_add*/ (binaryfunc)EQ_sub, /*nb_subtract*/ (binaryfunc)EQ_multiply, /*nb_multiply*/ (binaryfunc)EQ_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)EQ_inplace_add, /*inplace_add*/ (binaryfunc)EQ_inplace_sub, /*inplace_subtract*/ (binaryfunc)EQ_inplace_multiply, /*inplace_multiply*/ (binaryfunc)EQ_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject EQType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.EQ_base", /*tp_name*/ sizeof(EQ), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)EQ_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &EQ_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "EQ objects. Generates a biquadratic filter.", /* tp_doc */ (traverseproc)EQ_traverse, /* tp_traverse */ (inquiry)EQ_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ EQ_methods, /* tp_methods */ EQ_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ EQ_new, /* tp_new */ }; /* Performs portamento on audio signal */ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *risetime; PyObject *falltime; Stream *risetime_stream; Stream *falltime_stream; int modebuffer[4]; // need at least 2 slots for mul & add MYFLT y1; // sample memory MYFLT x1; int dir; } Port; static void direction(Port *self, MYFLT val) { if (val == self->x1) return; else if (val > self->x1) self->dir = 1; else self->dir = 0; self->x1 = val; } static void Port_filters_ii(Port *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT risetime = PyFloat_AS_DOUBLE(self->risetime); MYFLT falltime = PyFloat_AS_DOUBLE(self->falltime); MYFLT risefactor = 1. / ((risetime + 0.001) * self->sr); MYFLT fallfactor = 1. / ((falltime + 0.001) * self->sr); MYFLT factors[2] = {fallfactor, risefactor}; for (i=0; ibufsize; i++) { direction(self, in[i]); val = self->y1 + (in[i] - self->y1) * factors[self->dir]; self->y1 = val; self->data[i] = val; } } static void Port_filters_ai(Port *self) { MYFLT val, risefactor; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *risetime = Stream_getData((Stream *)self->risetime_stream); MYFLT falltime = PyFloat_AS_DOUBLE(self->falltime); MYFLT fallfactor = 1. / ((falltime + 0.001) * self->sr); for (i=0; ibufsize; i++) { direction(self, in[i]); risefactor = (*risetime++ + 0.001) * self->sr; if (self->dir == 1) val = self->y1 + (*in++ - self->y1) / risefactor; else val = self->y1 + (*in++ - self->y1) * fallfactor; self->y1 = val; self->data[i] = val; } } static void Port_filters_ia(Port *self) { MYFLT val, fallfactor; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *falltime = Stream_getData((Stream *)self->falltime_stream); MYFLT risetime = PyFloat_AS_DOUBLE(self->risetime); MYFLT risefactor = 1. / ((risetime + 0.001) * self->sr); for (i=0; ibufsize; i++) { direction(self, in[i]); fallfactor = (*falltime++ + 0.001) * self->sr; if (self->dir == 1) val = self->y1 + (*in++ - self->y1) * risefactor; else val = self->y1 + (*in++ - self->y1) / fallfactor; self->y1 = val; self->data[i] = val; } } static void Port_filters_aa(Port *self) { MYFLT val, risefactor, fallfactor; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *risetime = Stream_getData((Stream *)self->risetime_stream); MYFLT *falltime = Stream_getData((Stream *)self->falltime_stream); for (i=0; ibufsize; i++) { direction(self, in[i]); risefactor = (*risetime++ + 0.001) * self->sr; fallfactor = (*falltime++ + 0.001) * self->sr; if (self->dir == 1) val = self->y1 + (*in++ - self->y1) / risefactor; else val = self->y1 + (*in++ - self->y1) / fallfactor; self->y1 = val; self->data[i] = val; } } static void Port_postprocessing_ii(Port *self) { POST_PROCESSING_II }; static void Port_postprocessing_ai(Port *self) { POST_PROCESSING_AI }; static void Port_postprocessing_ia(Port *self) { POST_PROCESSING_IA }; static void Port_postprocessing_aa(Port *self) { POST_PROCESSING_AA }; static void Port_postprocessing_ireva(Port *self) { POST_PROCESSING_IREVA }; static void Port_postprocessing_areva(Port *self) { POST_PROCESSING_AREVA }; static void Port_postprocessing_revai(Port *self) { POST_PROCESSING_REVAI }; static void Port_postprocessing_revaa(Port *self) { POST_PROCESSING_REVAA }; static void Port_postprocessing_revareva(Port *self) { POST_PROCESSING_REVAREVA }; static void Port_setProcMode(Port *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Port_filters_ii; break; case 1: self->proc_func_ptr = Port_filters_ai; break; case 10: self->proc_func_ptr = Port_filters_ia; break; case 11: self->proc_func_ptr = Port_filters_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Port_postprocessing_ii; break; case 1: self->muladd_func_ptr = Port_postprocessing_ai; break; case 2: self->muladd_func_ptr = Port_postprocessing_revai; break; case 10: self->muladd_func_ptr = Port_postprocessing_ia; break; case 11: self->muladd_func_ptr = Port_postprocessing_aa; break; case 12: self->muladd_func_ptr = Port_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Port_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Port_postprocessing_areva; break; case 22: self->muladd_func_ptr = Port_postprocessing_revareva; break; } } static void Port_compute_next_data_frame(Port *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Port_traverse(Port *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->risetime); Py_VISIT(self->risetime_stream); Py_VISIT(self->falltime); Py_VISIT(self->falltime_stream); return 0; } static int Port_clear(Port *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->risetime); Py_CLEAR(self->risetime_stream); Py_CLEAR(self->falltime); Py_CLEAR(self->falltime_stream); return 0; } static void Port_dealloc(Port* self) { pyo_DEALLOC Port_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Port_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT inittmp = 0.0; PyObject *inputtmp, *input_streamtmp, *risetimetmp=NULL, *falltimetmp=NULL, *multmp=NULL, *addtmp=NULL; Port *self; self = (Port *)type->tp_alloc(type, 0); self->risetime = PyFloat_FromDouble(0.05); self->falltime = PyFloat_FromDouble(0.05); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->y1 = 0.0; self->x1 = 0.0; self->dir = 1; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Port_compute_next_data_frame); self->mode_func_ptr = Port_setProcMode; static char *kwlist[] = {"input", "risetime", "falltime", "init", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOFOO, kwlist, &inputtmp, &risetimetmp, &falltimetmp, &inittmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (risetimetmp) { PyObject_CallMethod((PyObject *)self, "setRiseTime", "O", risetimetmp); } if (falltimetmp) { PyObject_CallMethod((PyObject *)self, "setFallTime", "O", falltimetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } if (inittmp != 0.0) self->x1 = self->y1 = inittmp; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Port_getServer(Port* self) { GET_SERVER }; static PyObject * Port_getStream(Port* self) { GET_STREAM }; static PyObject * Port_setMul(Port *self, PyObject *arg) { SET_MUL }; static PyObject * Port_setAdd(Port *self, PyObject *arg) { SET_ADD }; static PyObject * Port_setSub(Port *self, PyObject *arg) { SET_SUB }; static PyObject * Port_setDiv(Port *self, PyObject *arg) { SET_DIV }; static PyObject * Port_play(Port *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Port_out(Port *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Port_stop(Port *self) { STOP }; static PyObject * Port_multiply(Port *self, PyObject *arg) { MULTIPLY }; static PyObject * Port_inplace_multiply(Port *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Port_add(Port *self, PyObject *arg) { ADD }; static PyObject * Port_inplace_add(Port *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Port_sub(Port *self, PyObject *arg) { SUB }; static PyObject * Port_inplace_sub(Port *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Port_div(Port *self, PyObject *arg) { DIV }; static PyObject * Port_inplace_div(Port *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Port_setRiseTime(Port *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->risetime); if (isNumber == 1) { self->risetime = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->risetime = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->risetime, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->risetime_stream); self->risetime_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Port_setFallTime(Port *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->falltime); if (isNumber == 1) { self->falltime = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->falltime = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->falltime, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->falltime_stream); self->falltime_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Port_members[] = { {"server", T_OBJECT_EX, offsetof(Port, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Port, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Port, input), 0, "Input sound object."}, {"risetime", T_OBJECT_EX, offsetof(Port, risetime), 0, "Rising portamento time in seconds."}, {"falltime", T_OBJECT_EX, offsetof(Port, falltime), 0, "Falling portamento time in seconds."}, {"mul", T_OBJECT_EX, offsetof(Port, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Port, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Port_methods[] = { {"getServer", (PyCFunction)Port_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Port_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Port_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Port_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Port_stop, METH_NOARGS, "Stops computing."}, {"setRiseTime", (PyCFunction)Port_setRiseTime, METH_O, "Sets rising portamento time in seconds."}, {"setFallTime", (PyCFunction)Port_setFallTime, METH_O, "Sets falling portamento time in seconds."}, {"setMul", (PyCFunction)Port_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Port_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Port_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Port_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Port_as_number = { (binaryfunc)Port_add, /*nb_add*/ (binaryfunc)Port_sub, /*nb_subtract*/ (binaryfunc)Port_multiply, /*nb_multiply*/ (binaryfunc)Port_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Port_inplace_add, /*inplace_add*/ (binaryfunc)Port_inplace_sub, /*inplace_subtract*/ (binaryfunc)Port_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Port_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject PortType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Port_base", /*tp_name*/ sizeof(Port), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Port_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Port_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Port objects. Generates a portamento filter.", /* tp_doc */ (traverseproc)Port_traverse, /* tp_traverse */ (inquiry)Port_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Port_methods, /* tp_methods */ Port_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Port_new, /* tp_new */ }; /************/ /* Tone */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; int modebuffer[3]; // need at least 2 slots for mul & add MYFLT lastFreq; MYFLT nyquist; // sample memories MYFLT y1; // variables MYFLT c1; MYFLT c2; } Tone; static void Tone_filters_i(Tone *self) { MYFLT val, b; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); if (fr != self->lastFreq) { if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; self->lastFreq = fr; b = 2.0 - MYCOS(TWOPI * fr / self->sr); self->c2 = (b - MYSQRT(b * b - 1.0)); self->c1 = 1.0 - self->c2; } for (i=0; ibufsize; i++) { val = self->c1 * in[i] + self->c2 * self->y1; self->data[i] = val; self->y1 = val; } } static void Tone_filters_a(Tone *self) { MYFLT val, freq, b; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { freq = fr[i]; if (freq != self->lastFreq) { if (freq <= 1.0) freq = 1.0; else if (freq >= self->nyquist) freq = self->nyquist; self->lastFreq = freq; b = 2.0 - MYCOS(TWOPI * freq / self->sr); self->c2 = (b - MYSQRT(b * b - 1.0)); self->c1 = 1.0 - self->c2; } val = self->c1 * in[i] + self->c2 * self->y1; self->data[i] = val; self->y1 = val; } } static void Tone_postprocessing_ii(Tone *self) { POST_PROCESSING_II }; static void Tone_postprocessing_ai(Tone *self) { POST_PROCESSING_AI }; static void Tone_postprocessing_ia(Tone *self) { POST_PROCESSING_IA }; static void Tone_postprocessing_aa(Tone *self) { POST_PROCESSING_AA }; static void Tone_postprocessing_ireva(Tone *self) { POST_PROCESSING_IREVA }; static void Tone_postprocessing_areva(Tone *self) { POST_PROCESSING_AREVA }; static void Tone_postprocessing_revai(Tone *self) { POST_PROCESSING_REVAI }; static void Tone_postprocessing_revaa(Tone *self) { POST_PROCESSING_REVAA }; static void Tone_postprocessing_revareva(Tone *self) { POST_PROCESSING_REVAREVA }; static void Tone_setProcMode(Tone *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Tone_filters_i; break; case 1: self->proc_func_ptr = Tone_filters_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Tone_postprocessing_ii; break; case 1: self->muladd_func_ptr = Tone_postprocessing_ai; break; case 2: self->muladd_func_ptr = Tone_postprocessing_revai; break; case 10: self->muladd_func_ptr = Tone_postprocessing_ia; break; case 11: self->muladd_func_ptr = Tone_postprocessing_aa; break; case 12: self->muladd_func_ptr = Tone_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Tone_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Tone_postprocessing_areva; break; case 22: self->muladd_func_ptr = Tone_postprocessing_revareva; break; } } static void Tone_compute_next_data_frame(Tone *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Tone_traverse(Tone *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); return 0; } static int Tone_clear(Tone *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); return 0; } static void Tone_dealloc(Tone* self) { pyo_DEALLOC Tone_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Tone_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL; Tone *self; self = (Tone *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->lastFreq = -1.0; self->y1 = self->c1 = self->c2 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.49; Stream_setFunctionPtr(self->stream, Tone_compute_next_data_frame); self->mode_func_ptr = Tone_setProcMode; static char *kwlist[] = {"input", "freq", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &freqtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Tone_getServer(Tone* self) { GET_SERVER }; static PyObject * Tone_getStream(Tone* self) { GET_STREAM }; static PyObject * Tone_setMul(Tone *self, PyObject *arg) { SET_MUL }; static PyObject * Tone_setAdd(Tone *self, PyObject *arg) { SET_ADD }; static PyObject * Tone_setSub(Tone *self, PyObject *arg) { SET_SUB }; static PyObject * Tone_setDiv(Tone *self, PyObject *arg) { SET_DIV }; static PyObject * Tone_play(Tone *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Tone_out(Tone *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Tone_stop(Tone *self) { STOP }; static PyObject * Tone_multiply(Tone *self, PyObject *arg) { MULTIPLY }; static PyObject * Tone_inplace_multiply(Tone *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Tone_add(Tone *self, PyObject *arg) { ADD }; static PyObject * Tone_inplace_add(Tone *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Tone_sub(Tone *self, PyObject *arg) { SUB }; static PyObject * Tone_inplace_sub(Tone *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Tone_div(Tone *self, PyObject *arg) { DIV }; static PyObject * Tone_inplace_div(Tone *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Tone_setFreq(Tone *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Tone_members[] = { {"server", T_OBJECT_EX, offsetof(Tone, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Tone, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Tone, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(Tone, freq), 0, "Cutoff frequency in cycle per second."}, {"mul", T_OBJECT_EX, offsetof(Tone, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Tone, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Tone_methods[] = { {"getServer", (PyCFunction)Tone_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Tone_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Tone_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Tone_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Tone_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Tone_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setMul", (PyCFunction)Tone_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Tone_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Tone_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Tone_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Tone_as_number = { (binaryfunc)Tone_add, /*nb_add*/ (binaryfunc)Tone_sub, /*nb_subtract*/ (binaryfunc)Tone_multiply, /*nb_multiply*/ (binaryfunc)Tone_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Tone_inplace_add, /*inplace_add*/ (binaryfunc)Tone_inplace_sub, /*inplace_subtract*/ (binaryfunc)Tone_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Tone_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ToneType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Tone_base", /*tp_name*/ sizeof(Tone), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Tone_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Tone_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Tone objects. One-pole recursive lowpass filter.", /* tp_doc */ (traverseproc)Tone_traverse, /* tp_traverse */ (inquiry)Tone_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Tone_methods, /* tp_methods */ Tone_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Tone_new, /* tp_new */ }; /************/ /* Atone */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; int modebuffer[3]; // need at least 2 slots for mul & add MYFLT lastFreq; MYFLT nyquist; // sample memories MYFLT y1; // variables MYFLT c1; MYFLT c2; } Atone; static void Atone_filters_i(Atone *self) { MYFLT val, b; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); if (fr != self->lastFreq) { if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; self->lastFreq = fr; b = 2.0 - MYCOS(TWOPI * fr / self->sr); self->c2 = (b - MYSQRT(b * b - 1.0)); self->c1 = 1.0 - self->c2; } for (i=0; ibufsize; i++) { self->y1 = val = self->c1 * in[i] + self->c2 * self->y1; self->data[i] = in[i] - val; } } static void Atone_filters_a(Atone *self) { MYFLT val, freq, b; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { freq = fr[i]; if (freq != self->lastFreq) { if (freq <= 1.0) freq = 1.0; else if (freq >= self->nyquist) freq = self->nyquist; self->lastFreq = freq; b = 2.0 - MYCOS(TWOPI * freq / self->sr); self->c2 = (b - MYSQRT(b * b - 1.0)); self->c1 = 1.0 - self->c2; } self->y1 = val = self->c1 * in[i] + self->c2 * self->y1; self->data[i] = in[i] - val; } } static void Atone_postprocessing_ii(Atone *self) { POST_PROCESSING_II }; static void Atone_postprocessing_ai(Atone *self) { POST_PROCESSING_AI }; static void Atone_postprocessing_ia(Atone *self) { POST_PROCESSING_IA }; static void Atone_postprocessing_aa(Atone *self) { POST_PROCESSING_AA }; static void Atone_postprocessing_ireva(Atone *self) { POST_PROCESSING_IREVA }; static void Atone_postprocessing_areva(Atone *self) { POST_PROCESSING_AREVA }; static void Atone_postprocessing_revai(Atone *self) { POST_PROCESSING_REVAI }; static void Atone_postprocessing_revaa(Atone *self) { POST_PROCESSING_REVAA }; static void Atone_postprocessing_revareva(Atone *self) { POST_PROCESSING_REVAREVA }; static void Atone_setProcMode(Atone *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Atone_filters_i; break; case 1: self->proc_func_ptr = Atone_filters_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Atone_postprocessing_ii; break; case 1: self->muladd_func_ptr = Atone_postprocessing_ai; break; case 2: self->muladd_func_ptr = Atone_postprocessing_revai; break; case 10: self->muladd_func_ptr = Atone_postprocessing_ia; break; case 11: self->muladd_func_ptr = Atone_postprocessing_aa; break; case 12: self->muladd_func_ptr = Atone_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Atone_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Atone_postprocessing_areva; break; case 22: self->muladd_func_ptr = Atone_postprocessing_revareva; break; } } static void Atone_compute_next_data_frame(Atone *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Atone_traverse(Atone *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); return 0; } static int Atone_clear(Atone *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); return 0; } static void Atone_dealloc(Atone* self) { pyo_DEALLOC Atone_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Atone_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL; Atone *self; self = (Atone *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->lastFreq = -1.0; self->y1 = self->c1 = self->c2 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.49; Stream_setFunctionPtr(self->stream, Atone_compute_next_data_frame); self->mode_func_ptr = Atone_setProcMode; static char *kwlist[] = {"input", "freq", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &freqtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Atone_getServer(Atone* self) { GET_SERVER }; static PyObject * Atone_getStream(Atone* self) { GET_STREAM }; static PyObject * Atone_setMul(Atone *self, PyObject *arg) { SET_MUL }; static PyObject * Atone_setAdd(Atone *self, PyObject *arg) { SET_ADD }; static PyObject * Atone_setSub(Atone *self, PyObject *arg) { SET_SUB }; static PyObject * Atone_setDiv(Atone *self, PyObject *arg) { SET_DIV }; static PyObject * Atone_play(Atone *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Atone_out(Atone *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Atone_stop(Atone *self) { STOP }; static PyObject * Atone_multiply(Atone *self, PyObject *arg) { MULTIPLY }; static PyObject * Atone_inplace_multiply(Atone *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Atone_add(Atone *self, PyObject *arg) { ADD }; static PyObject * Atone_inplace_add(Atone *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Atone_sub(Atone *self, PyObject *arg) { SUB }; static PyObject * Atone_inplace_sub(Atone *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Atone_div(Atone *self, PyObject *arg) { DIV }; static PyObject * Atone_inplace_div(Atone *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Atone_setFreq(Atone *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Atone_members[] = { {"server", T_OBJECT_EX, offsetof(Atone, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Atone, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Atone, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(Atone, freq), 0, "Cutoff frequency in cycle per second."}, {"mul", T_OBJECT_EX, offsetof(Atone, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Atone, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Atone_methods[] = { {"getServer", (PyCFunction)Atone_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Atone_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Atone_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Atone_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Atone_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Atone_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setMul", (PyCFunction)Atone_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Atone_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Atone_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Atone_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Atone_as_number = { (binaryfunc)Atone_add, /*nb_add*/ (binaryfunc)Atone_sub, /*nb_subtract*/ (binaryfunc)Atone_multiply, /*nb_multiply*/ (binaryfunc)Atone_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Atone_inplace_add, /*inplace_add*/ (binaryfunc)Atone_inplace_sub, /*inplace_subtract*/ (binaryfunc)Atone_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Atone_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject AtoneType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Atone_base", /*tp_name*/ sizeof(Atone), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Atone_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Atone_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Atone objects. One-pole recursive lowpass filter.", /* tp_doc */ (traverseproc)Atone_traverse, /* tp_traverse */ (inquiry)Atone_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Atone_methods, /* tp_methods */ Atone_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Atone_new, /* tp_new */ }; /************/ /* DCBlock */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add // sample memories MYFLT x1; MYFLT y1; } DCBlock; static void DCBlock_filters(DCBlock *self) { MYFLT x, y; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { x = in[i]; y = x - self->x1 + 0.995 * self->y1; self->x1 = x; self->data[i] = self->y1 = y; } } static void DCBlock_postprocessing_ii(DCBlock *self) { POST_PROCESSING_II }; static void DCBlock_postprocessing_ai(DCBlock *self) { POST_PROCESSING_AI }; static void DCBlock_postprocessing_ia(DCBlock *self) { POST_PROCESSING_IA }; static void DCBlock_postprocessing_aa(DCBlock *self) { POST_PROCESSING_AA }; static void DCBlock_postprocessing_ireva(DCBlock *self) { POST_PROCESSING_IREVA }; static void DCBlock_postprocessing_areva(DCBlock *self) { POST_PROCESSING_AREVA }; static void DCBlock_postprocessing_revai(DCBlock *self) { POST_PROCESSING_REVAI }; static void DCBlock_postprocessing_revaa(DCBlock *self) { POST_PROCESSING_REVAA }; static void DCBlock_postprocessing_revareva(DCBlock *self) { POST_PROCESSING_REVAREVA }; static void DCBlock_setProcMode(DCBlock *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = DCBlock_filters; switch (muladdmode) { case 0: self->muladd_func_ptr = DCBlock_postprocessing_ii; break; case 1: self->muladd_func_ptr = DCBlock_postprocessing_ai; break; case 2: self->muladd_func_ptr = DCBlock_postprocessing_revai; break; case 10: self->muladd_func_ptr = DCBlock_postprocessing_ia; break; case 11: self->muladd_func_ptr = DCBlock_postprocessing_aa; break; case 12: self->muladd_func_ptr = DCBlock_postprocessing_revaa; break; case 20: self->muladd_func_ptr = DCBlock_postprocessing_ireva; break; case 21: self->muladd_func_ptr = DCBlock_postprocessing_areva; break; case 22: self->muladd_func_ptr = DCBlock_postprocessing_revareva; break; } } static void DCBlock_compute_next_data_frame(DCBlock *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int DCBlock_traverse(DCBlock *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int DCBlock_clear(DCBlock *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void DCBlock_dealloc(DCBlock* self) { pyo_DEALLOC DCBlock_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * DCBlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; DCBlock *self; self = (DCBlock *)type->tp_alloc(type, 0); self->x1 = self->y1 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, DCBlock_compute_next_data_frame); self->mode_func_ptr = DCBlock_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * DCBlock_getServer(DCBlock* self) { GET_SERVER }; static PyObject * DCBlock_getStream(DCBlock* self) { GET_STREAM }; static PyObject * DCBlock_setMul(DCBlock *self, PyObject *arg) { SET_MUL }; static PyObject * DCBlock_setAdd(DCBlock *self, PyObject *arg) { SET_ADD }; static PyObject * DCBlock_setSub(DCBlock *self, PyObject *arg) { SET_SUB }; static PyObject * DCBlock_setDiv(DCBlock *self, PyObject *arg) { SET_DIV }; static PyObject * DCBlock_play(DCBlock *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * DCBlock_out(DCBlock *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * DCBlock_stop(DCBlock *self) { STOP }; static PyObject * DCBlock_multiply(DCBlock *self, PyObject *arg) { MULTIPLY }; static PyObject * DCBlock_inplace_multiply(DCBlock *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * DCBlock_add(DCBlock *self, PyObject *arg) { ADD }; static PyObject * DCBlock_inplace_add(DCBlock *self, PyObject *arg) { INPLACE_ADD }; static PyObject * DCBlock_sub(DCBlock *self, PyObject *arg) { SUB }; static PyObject * DCBlock_inplace_sub(DCBlock *self, PyObject *arg) { INPLACE_SUB }; static PyObject * DCBlock_div(DCBlock *self, PyObject *arg) { DIV }; static PyObject * DCBlock_inplace_div(DCBlock *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef DCBlock_members[] = { {"server", T_OBJECT_EX, offsetof(DCBlock, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(DCBlock, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(DCBlock, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(DCBlock, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(DCBlock, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef DCBlock_methods[] = { {"getServer", (PyCFunction)DCBlock_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)DCBlock_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)DCBlock_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)DCBlock_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)DCBlock_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)DCBlock_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)DCBlock_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)DCBlock_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)DCBlock_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods DCBlock_as_number = { (binaryfunc)DCBlock_add, /*nb_add*/ (binaryfunc)DCBlock_sub, /*nb_subtract*/ (binaryfunc)DCBlock_multiply, /*nb_multiply*/ (binaryfunc)DCBlock_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)DCBlock_inplace_add, /*inplace_add*/ (binaryfunc)DCBlock_inplace_sub, /*inplace_subtract*/ (binaryfunc)DCBlock_inplace_multiply, /*inplace_multiply*/ (binaryfunc)DCBlock_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject DCBlockType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.DCBlock_base", /*tp_name*/ sizeof(DCBlock), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)DCBlock_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &DCBlock_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "DCBlock objects. Implements the DC blocking filter.", /* tp_doc */ (traverseproc)DCBlock_traverse, /* tp_traverse */ (inquiry)DCBlock_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ DCBlock_methods, /* tp_methods */ DCBlock_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ DCBlock_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *delay; Stream *delay_stream; PyObject *feedback; Stream *feedback_stream; MYFLT maxDelay; long size; int in_count; int modebuffer[4]; MYFLT *buffer; // samples memory } Allpass; static void Allpass_process_ii(Allpass *self) { MYFLT val, xind, frac; int i, ind; MYFLT del = PyFloat_AS_DOUBLE(self->delay); MYFLT feed = PyFloat_AS_DOUBLE(self->feedback); if (del < 0.) del = 0.; else if (del > self->maxDelay) del = self->maxDelay; MYFLT sampdel = del * self->sr; if (feed < 0) feed = 0; else if (feed > 1) feed = 1; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (int)xind; frac = xind - ind; val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac; self->data[i] = val * (1.0 - (feed * feed)) + in[i] * -feed; self->buffer[self->in_count] = in[i] + (val * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count >= self->size) self->in_count = 0; } } static void Allpass_process_ai(Allpass *self) { MYFLT val, xind, frac, sampdel, del; int i, ind; MYFLT *delobj = Stream_getData((Stream *)self->delay_stream); MYFLT feed = PyFloat_AS_DOUBLE(self->feedback); if (feed < 0) feed = 0; else if (feed > 1) feed = 1; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { del = delobj[i]; if (del < 0.) del = 0.; else if (del > self->maxDelay) del = self->maxDelay; sampdel = del * self->sr; xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (int)xind; frac = xind - ind; val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac; self->data[i] = val * (1.0 - (feed * feed)) + in[i] * -feed; self->buffer[self->in_count] = in[i] + (val * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count >= self->size) self->in_count = 0; } } static void Allpass_process_ia(Allpass *self) { MYFLT val, xind, frac, feed; int i, ind; MYFLT del = PyFloat_AS_DOUBLE(self->delay); MYFLT *fdb = Stream_getData((Stream *)self->feedback_stream); if (del < 0.) del = 0.; else if (del > self->maxDelay) del = self->maxDelay; MYFLT sampdel = del * self->sr; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { feed = fdb[i]; if (feed < 0) feed = 0; else if (feed > 1) feed = 1; xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (int)xind; frac = xind - ind; val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac; self->data[i] = val * (1.0 - (feed * feed)) + in[i] * -feed; self->buffer[self->in_count] = in[i] + (val * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void Allpass_process_aa(Allpass *self) { MYFLT val, xind, frac, sampdel, feed, del; int i, ind; MYFLT *delobj = Stream_getData((Stream *)self->delay_stream); MYFLT *fdb = Stream_getData((Stream *)self->feedback_stream); MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { del = delobj[i]; feed = fdb[i]; if (feed < 0) feed = 0; else if (feed > 1) feed = 1; if (del < 0.) del = 0.; else if (del > self->maxDelay) del = self->maxDelay; sampdel = del * self->sr; xind = self->in_count - sampdel; if (xind < 0) xind += self->size; ind = (int)xind; frac = xind - ind; val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac; self->data[i] = val * (1.0 - (feed * feed)) + in[i] * -feed; self->buffer[self->in_count] = in[i] + (val * feed); if (self->in_count == 0) self->buffer[self->size] = self->buffer[0]; self->in_count++; if (self->in_count == self->size) self->in_count = 0; } } static void Allpass_postprocessing_ii(Allpass *self) { POST_PROCESSING_II }; static void Allpass_postprocessing_ai(Allpass *self) { POST_PROCESSING_AI }; static void Allpass_postprocessing_ia(Allpass *self) { POST_PROCESSING_IA }; static void Allpass_postprocessing_aa(Allpass *self) { POST_PROCESSING_AA }; static void Allpass_postprocessing_ireva(Allpass *self) { POST_PROCESSING_IREVA }; static void Allpass_postprocessing_areva(Allpass *self) { POST_PROCESSING_AREVA }; static void Allpass_postprocessing_revai(Allpass *self) { POST_PROCESSING_REVAI }; static void Allpass_postprocessing_revaa(Allpass *self) { POST_PROCESSING_REVAA }; static void Allpass_postprocessing_revareva(Allpass *self) { POST_PROCESSING_REVAREVA }; static void Allpass_setProcMode(Allpass *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Allpass_process_ii; break; case 1: self->proc_func_ptr = Allpass_process_ai; break; case 10: self->proc_func_ptr = Allpass_process_ia; break; case 11: self->proc_func_ptr = Allpass_process_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Allpass_postprocessing_ii; break; case 1: self->muladd_func_ptr = Allpass_postprocessing_ai; break; case 2: self->muladd_func_ptr = Allpass_postprocessing_revai; break; case 10: self->muladd_func_ptr = Allpass_postprocessing_ia; break; case 11: self->muladd_func_ptr = Allpass_postprocessing_aa; break; case 12: self->muladd_func_ptr = Allpass_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Allpass_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Allpass_postprocessing_areva; break; case 22: self->muladd_func_ptr = Allpass_postprocessing_revareva; break; } } static void Allpass_compute_next_data_frame(Allpass *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Allpass_traverse(Allpass *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->delay); Py_VISIT(self->delay_stream); Py_VISIT(self->feedback); Py_VISIT(self->feedback_stream); return 0; } static int Allpass_clear(Allpass *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->delay); Py_CLEAR(self->delay_stream); Py_CLEAR(self->feedback); Py_CLEAR(self->feedback_stream); return 0; } static void Allpass_dealloc(Allpass* self) { pyo_DEALLOC free(self->buffer); Allpass_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Allpass_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *delaytmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL; Allpass *self; self = (Allpass *)type->tp_alloc(type, 0); self->delay = PyFloat_FromDouble(0); self->feedback = PyFloat_FromDouble(0); self->maxDelay = 1; self->in_count = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Allpass_compute_next_data_frame); self->mode_func_ptr = Allpass_setProcMode; static char *kwlist[] = {"input", "delay", "feedback", "maxDelay", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOFOO, kwlist, &inputtmp, &delaytmp, &feedbacktmp, &self->maxDelay, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (delaytmp) { PyObject_CallMethod((PyObject *)self, "setDelay", "O", delaytmp); } if (feedbacktmp) { PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->size = self->maxDelay * self->sr + 0.5; self->buffer = (MYFLT *)realloc(self->buffer, (self->size+1) * sizeof(MYFLT)); for (i=0; i<(self->size+1); i++) { self->buffer[i] = 0.; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Allpass_getServer(Allpass* self) { GET_SERVER }; static PyObject * Allpass_getStream(Allpass* self) { GET_STREAM }; static PyObject * Allpass_setMul(Allpass *self, PyObject *arg) { SET_MUL }; static PyObject * Allpass_setAdd(Allpass *self, PyObject *arg) { SET_ADD }; static PyObject * Allpass_setSub(Allpass *self, PyObject *arg) { SET_SUB }; static PyObject * Allpass_setDiv(Allpass *self, PyObject *arg) { SET_DIV }; static PyObject * Allpass_play(Allpass *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Allpass_out(Allpass *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Allpass_stop(Allpass *self) { STOP }; static PyObject * Allpass_multiply(Allpass *self, PyObject *arg) { MULTIPLY }; static PyObject * Allpass_inplace_multiply(Allpass *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Allpass_add(Allpass *self, PyObject *arg) { ADD }; static PyObject * Allpass_inplace_add(Allpass *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Allpass_sub(Allpass *self, PyObject *arg) { SUB }; static PyObject * Allpass_inplace_sub(Allpass *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Allpass_div(Allpass *self, PyObject *arg) { DIV }; static PyObject * Allpass_inplace_div(Allpass *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Allpass_setDelay(Allpass *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->delay); if (isNumber == 1) { self->delay = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->delay = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->delay, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->delay_stream); self->delay_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Allpass_setFeedback(Allpass *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->feedback); if (isNumber == 1) { self->feedback = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->feedback = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->feedback_stream); self->feedback_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Allpass_members[] = { {"server", T_OBJECT_EX, offsetof(Allpass, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Allpass, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Allpass, input), 0, "Input sound object."}, {"delay", T_OBJECT_EX, offsetof(Allpass, delay), 0, "delay time in seconds."}, {"feedback", T_OBJECT_EX, offsetof(Allpass, feedback), 0, "Feedback value."}, {"mul", T_OBJECT_EX, offsetof(Allpass, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Allpass, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Allpass_methods[] = { {"getServer", (PyCFunction)Allpass_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Allpass_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Allpass_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Allpass_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Allpass_stop, METH_NOARGS, "Stops computing."}, {"setDelay", (PyCFunction)Allpass_setDelay, METH_O, "Sets delay time in seconds."}, {"setFeedback", (PyCFunction)Allpass_setFeedback, METH_O, "Sets feedback value between 0 -> 1."}, {"setMul", (PyCFunction)Allpass_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Allpass_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Allpass_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Allpass_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Allpass_as_number = { (binaryfunc)Allpass_add, /*nb_add*/ (binaryfunc)Allpass_sub, /*nb_subtract*/ (binaryfunc)Allpass_multiply, /*nb_multiply*/ (binaryfunc)Allpass_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Allpass_inplace_add, /*inplace_add*/ (binaryfunc)Allpass_inplace_sub, /*inplace_subtract*/ (binaryfunc)Allpass_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Allpass_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject AllpassType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Allpass_base", /*tp_name*/ sizeof(Allpass), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Allpass_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Allpass_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Allpass objects. Allpass signal by x samples.", /* tp_doc */ (traverseproc)Allpass_traverse, /* tp_traverse */ (inquiry)Allpass_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Allpass_methods, /* tp_methods */ Allpass_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Allpass_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *bw; Stream *bw_stream; int init; int modebuffer[4]; // need at least 2 slots for mul & add MYFLT oneOnSr; MYFLT nyquist; // sample memories MYFLT y1; MYFLT y2; // coefficients MYFLT alpha; MYFLT beta; } Allpass2; static void Allpass2_compute_variables(Allpass2 *self, MYFLT freq, MYFLT bw) { MYFLT radius, angle; if (freq <= 1) freq = 1; else if (freq >= self->nyquist) freq = self->nyquist; radius = MYPOW(E, -PI * bw * self->oneOnSr); angle = TWOPI * freq * self->oneOnSr; self->alpha = radius * radius; self->beta = -2.0 * radius * MYCOS(angle); } static void Allpass2_filters_ii(Allpass2 *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->y1 = self->y2 = in[0]; self->init = 0; } for (i=0; ibufsize; i++) { val = in[i] + (self->y1 * -self->beta) + (self->y2 * -self->alpha); self->data[i] = (val * self->alpha) + (self->y1 * self->beta) + self->y2; self->y2 = self->y1; self->y1 = val; } } static void Allpass2_filters_ai(Allpass2 *self) { MYFLT val, bw; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->y1 = self->y2 = in[0]; self->init = 0; } MYFLT *fr = Stream_getData((Stream *)self->freq_stream); bw = PyFloat_AS_DOUBLE(self->bw); for (i=0; ibufsize; i++) { Allpass2_compute_variables(self, fr[i], bw); val = in[i] + (self->y1 * -self->beta) + (self->y2 * -self->alpha); self->data[i] = (val * self->alpha) + (self->y1 * self->beta) + self->y2; self->y2 = self->y1; self->y1 = val; } } static void Allpass2_filters_ia(Allpass2 *self) { MYFLT val, fr; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->y1 = self->y2 = in[0]; self->init = 0; } fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *bw = Stream_getData((Stream *)self->bw_stream); for (i=0; ibufsize; i++) { Allpass2_compute_variables(self, fr, bw[i]); val = in[i] + (self->y1 * -self->beta) + (self->y2 * -self->alpha); self->data[i] = (val * self->alpha) + (self->y1 * self->beta) + self->y2; self->y2 = self->y1; self->y1 = val; } } static void Allpass2_filters_aa(Allpass2 *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { self->y1 = self->y2 = in[0]; self->init = 0; } MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *bw = Stream_getData((Stream *)self->bw_stream); for (i=0; ibufsize; i++) { Allpass2_compute_variables(self, fr[i], bw[i]); val = in[i] + (self->y1 * -self->beta) + (self->y2 * -self->alpha); self->data[i] = (val * self->alpha) + (self->y1 * self->beta) + self->y2; self->y2 = self->y1; self->y1 = val; } } static void Allpass2_postprocessing_ii(Allpass2 *self) { POST_PROCESSING_II }; static void Allpass2_postprocessing_ai(Allpass2 *self) { POST_PROCESSING_AI }; static void Allpass2_postprocessing_ia(Allpass2 *self) { POST_PROCESSING_IA }; static void Allpass2_postprocessing_aa(Allpass2 *self) { POST_PROCESSING_AA }; static void Allpass2_postprocessing_ireva(Allpass2 *self) { POST_PROCESSING_IREVA }; static void Allpass2_postprocessing_areva(Allpass2 *self) { POST_PROCESSING_AREVA }; static void Allpass2_postprocessing_revai(Allpass2 *self) { POST_PROCESSING_REVAI }; static void Allpass2_postprocessing_revaa(Allpass2 *self) { POST_PROCESSING_REVAA }; static void Allpass2_postprocessing_revareva(Allpass2 *self) { POST_PROCESSING_REVAREVA }; static void Allpass2_setProcMode(Allpass2 *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: Allpass2_compute_variables(self, PyFloat_AS_DOUBLE(self->freq), PyFloat_AS_DOUBLE(self->bw)); self->proc_func_ptr = Allpass2_filters_ii; break; case 1: self->proc_func_ptr = Allpass2_filters_ai; break; case 10: self->proc_func_ptr = Allpass2_filters_ia; break; case 11: self->proc_func_ptr = Allpass2_filters_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Allpass2_postprocessing_ii; break; case 1: self->muladd_func_ptr = Allpass2_postprocessing_ai; break; case 2: self->muladd_func_ptr = Allpass2_postprocessing_revai; break; case 10: self->muladd_func_ptr = Allpass2_postprocessing_ia; break; case 11: self->muladd_func_ptr = Allpass2_postprocessing_aa; break; case 12: self->muladd_func_ptr = Allpass2_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Allpass2_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Allpass2_postprocessing_areva; break; case 22: self->muladd_func_ptr = Allpass2_postprocessing_revareva; break; } } static void Allpass2_compute_next_data_frame(Allpass2 *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Allpass2_traverse(Allpass2 *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->bw); Py_VISIT(self->bw_stream); return 0; } static int Allpass2_clear(Allpass2 *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->bw); Py_CLEAR(self->bw_stream); return 0; } static void Allpass2_dealloc(Allpass2* self) { pyo_DEALLOC Allpass2_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Allpass2_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *bwtmp=NULL, *multmp=NULL, *addtmp=NULL; Allpass2 *self; self = (Allpass2 *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->bw = PyFloat_FromDouble(100); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->init = 1; INIT_OBJECT_COMMON self->oneOnSr = 1.0 / self->sr; self->nyquist = (MYFLT)self->sr * 0.49; Stream_setFunctionPtr(self->stream, Allpass2_compute_next_data_frame); self->mode_func_ptr = Allpass2_setProcMode; static char *kwlist[] = {"input", "freq", "bw", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &freqtmp, &bwtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (bwtmp) { PyObject_CallMethod((PyObject *)self, "setBw", "O", bwtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Allpass2_getServer(Allpass2* self) { GET_SERVER }; static PyObject * Allpass2_getStream(Allpass2* self) { GET_STREAM }; static PyObject * Allpass2_setMul(Allpass2 *self, PyObject *arg) { SET_MUL }; static PyObject * Allpass2_setAdd(Allpass2 *self, PyObject *arg) { SET_ADD }; static PyObject * Allpass2_setSub(Allpass2 *self, PyObject *arg) { SET_SUB }; static PyObject * Allpass2_setDiv(Allpass2 *self, PyObject *arg) { SET_DIV }; static PyObject * Allpass2_play(Allpass2 *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Allpass2_out(Allpass2 *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Allpass2_stop(Allpass2 *self) { STOP }; static PyObject * Allpass2_multiply(Allpass2 *self, PyObject *arg) { MULTIPLY }; static PyObject * Allpass2_inplace_multiply(Allpass2 *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Allpass2_add(Allpass2 *self, PyObject *arg) { ADD }; static PyObject * Allpass2_inplace_add(Allpass2 *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Allpass2_sub(Allpass2 *self, PyObject *arg) { SUB }; static PyObject * Allpass2_inplace_sub(Allpass2 *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Allpass2_div(Allpass2 *self, PyObject *arg) { DIV }; static PyObject * Allpass2_inplace_div(Allpass2 *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Allpass2_setFreq(Allpass2 *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Allpass2_setBw(Allpass2 *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->bw); if (isNumber == 1) { self->bw = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->bw = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->bw, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->bw_stream); self->bw_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Allpass2_members[] = { {"server", T_OBJECT_EX, offsetof(Allpass2, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Allpass2, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Allpass2, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(Allpass2, freq), 0, "Cutoff frequency in cycle per second."}, {"bw", T_OBJECT_EX, offsetof(Allpass2, bw), 0, "Bandwidth."}, {"mul", T_OBJECT_EX, offsetof(Allpass2, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Allpass2, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Allpass2_methods[] = { {"getServer", (PyCFunction)Allpass2_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Allpass2_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Allpass2_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Allpass2_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Allpass2_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Allpass2_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setBw", (PyCFunction)Allpass2_setBw, METH_O, "Sets filter bandwidth."}, {"setMul", (PyCFunction)Allpass2_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Allpass2_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Allpass2_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Allpass2_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Allpass2_as_number = { (binaryfunc)Allpass2_add, /*nb_add*/ (binaryfunc)Allpass2_sub, /*nb_subtract*/ (binaryfunc)Allpass2_multiply, /*nb_multiply*/ (binaryfunc)Allpass2_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Allpass2_inplace_add, /*inplace_add*/ (binaryfunc)Allpass2_inplace_sub, /*inplace_subtract*/ (binaryfunc)Allpass2_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Allpass2_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject Allpass2Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Allpass2_base", /*tp_name*/ sizeof(Allpass2), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Allpass2_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Allpass2_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Allpass2 objects. Second order allpass filter.", /* tp_doc */ (traverseproc)Allpass2_traverse, /* tp_traverse */ (inquiry)Allpass2_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Allpass2_methods, /* tp_methods */ Allpass2_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Allpass2_new, /* tp_new */ }; /*******************/ /***** Phaser ******/ /*******************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *spread; Stream *spread_stream; PyObject *q; Stream *q_stream; PyObject *feedback; Stream *feedback_stream; int stages; int modebuffer[6]; // need at least 2 slots for mul & add MYFLT halfSr; MYFLT minusPiOnSr; MYFLT twoPiOnSr; MYFLT norm_arr_pos; MYFLT tmp; // sample memories MYFLT *y1; MYFLT *y2; // coefficients MYFLT *alpha; MYFLT *beta; } Phaser; static MYFLT Phaser_clip(MYFLT x) { if (x < -1.0) return -1.0; else if (x > 1.0) return 1.0; else return x; } static void Phaser_compute_variables(Phaser *self, MYFLT freq, MYFLT spread, MYFLT q) { int i, ipart; MYFLT radius, angle, fr, qfactor, pos, fpart; qfactor = 1.0 / q * self->minusPiOnSr; fr = freq; for (i=0; istages; i++) { if (fr <= 20) fr = 20; else if (fr >= self->halfSr) fr = self->halfSr; radius = MYPOW(E, fr * qfactor); angle = fr * self->twoPiOnSr; self->alpha[i] = radius * radius; pos = angle * self->norm_arr_pos; ipart = (int)pos; fpart = pos - ipart; self->beta[i] = -2.0 * radius * (HALF_COS_ARRAY[i] * (1.0 - fpart) + HALF_COS_ARRAY[i+1] * fpart); fr *= spread; } } static void Phaser_filters_iii(Phaser *self) { MYFLT val; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->modebuffer[5] == 0) { MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback)); for (i=0; ibufsize; i++) { self->tmp = in[i] + self->tmp * feed; for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } else { MYFLT *feed = Stream_getData((Stream *)self->feedback_stream); for (i=0; ibufsize; i++) { self->tmp = in[i] + self->tmp * Phaser_clip(feed[i]); for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } } static void Phaser_filters_aii(Phaser *self) { MYFLT val; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT spread = PyFloat_AS_DOUBLE(self->spread); MYFLT q = PyFloat_AS_DOUBLE(self->q); if (self->modebuffer[5] == 0) { MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback)); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq[i], spread, q); self->tmp = in[i] + self->tmp * feed; for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } else { MYFLT *feed = Stream_getData((Stream *)self->feedback_stream); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq[i], spread, q); self->tmp = in[i] + self->tmp * Phaser_clip(feed[i]); for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } } static void Phaser_filters_iai(Phaser *self) { MYFLT val; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT freq = PyFloat_AS_DOUBLE(self->freq); MYFLT *spread = Stream_getData((Stream *)self->spread_stream); MYFLT q = PyFloat_AS_DOUBLE(self->q); if (self->modebuffer[5] == 0) { MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback)); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq, spread[i], q); self->tmp = in[i] + self->tmp * feed; for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } else { MYFLT *feed = Stream_getData((Stream *)self->feedback_stream); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq, spread[i], q); self->tmp = in[i] + self->tmp * Phaser_clip(feed[i]); for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } } static void Phaser_filters_aai(Phaser *self) { MYFLT val; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT *spread = Stream_getData((Stream *)self->spread_stream); MYFLT q = PyFloat_AS_DOUBLE(self->q); if (self->modebuffer[5] == 0) { MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback)); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq[i], spread[i], q); self->tmp = in[i] + self->tmp * feed; for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } else { MYFLT *feed = Stream_getData((Stream *)self->feedback_stream); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq[i], spread[i], q); self->tmp = in[i] + self->tmp * Phaser_clip(feed[i]); for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } } static void Phaser_filters_iia(Phaser *self) { MYFLT val; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT freq = PyFloat_AS_DOUBLE(self->freq); MYFLT spread = PyFloat_AS_DOUBLE(self->spread); MYFLT *q = Stream_getData((Stream *)self->q_stream); if (self->modebuffer[5] == 0) { MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback)); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq, spread, q[i]); self->tmp = in[i] + self->tmp * feed; for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } else { MYFLT *feed = Stream_getData((Stream *)self->feedback_stream); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq, spread, q[i]); self->tmp = in[i] + self->tmp * Phaser_clip(feed[i]); for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } } static void Phaser_filters_aia(Phaser *self) { MYFLT val; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT spread = PyFloat_AS_DOUBLE(self->spread); MYFLT *q = Stream_getData((Stream *)self->q_stream); if (self->modebuffer[5] == 0) { MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback)); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq[i], spread, q[i]); self->tmp = in[i] + self->tmp * feed; for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } else { MYFLT *feed = Stream_getData((Stream *)self->feedback_stream); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq[i], spread, q[i]); self->tmp = in[i] + self->tmp * Phaser_clip(feed[i]); for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } } static void Phaser_filters_iaa(Phaser *self) { MYFLT val; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT freq = PyFloat_AS_DOUBLE(self->freq); MYFLT *spread = Stream_getData((Stream *)self->spread_stream); MYFLT *q = Stream_getData((Stream *)self->q_stream); if (self->modebuffer[5] == 0) { MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback)); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq, spread[i], q[i]); self->tmp = in[i] + self->tmp * feed; for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } else { MYFLT *feed = Stream_getData((Stream *)self->feedback_stream); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq, spread[i], q[i]); self->tmp = in[i] + self->tmp * Phaser_clip(feed[i]); for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } } static void Phaser_filters_aaa(Phaser *self) { MYFLT val; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT *spread = Stream_getData((Stream *)self->spread_stream); MYFLT *q = Stream_getData((Stream *)self->q_stream); if (self->modebuffer[5] == 0) { MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback)); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq[i], spread[i], q[i]); self->tmp = in[i] + self->tmp * feed; for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } else { MYFLT *feed = Stream_getData((Stream *)self->feedback_stream); for (i=0; ibufsize; i++) { Phaser_compute_variables(self, freq[i], spread[i], q[i]); self->tmp = in[i] + self->tmp * Phaser_clip(feed[i]); for (j=0; jstages; j++) { val = self->tmp + (self->y1[j] * -self->beta[j]) + (self->y2[j] * -self->alpha[j]); self->tmp = (val * self->alpha[j]) + (self->y1[j] * self->beta[j]) + self->y2[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; } self->data[i] = self->tmp; } } } static void Phaser_postprocessing_ii(Phaser *self) { POST_PROCESSING_II }; static void Phaser_postprocessing_ai(Phaser *self) { POST_PROCESSING_AI }; static void Phaser_postprocessing_ia(Phaser *self) { POST_PROCESSING_IA }; static void Phaser_postprocessing_aa(Phaser *self) { POST_PROCESSING_AA }; static void Phaser_postprocessing_ireva(Phaser *self) { POST_PROCESSING_IREVA }; static void Phaser_postprocessing_areva(Phaser *self) { POST_PROCESSING_AREVA }; static void Phaser_postprocessing_revai(Phaser *self) { POST_PROCESSING_REVAI }; static void Phaser_postprocessing_revaa(Phaser *self) { POST_PROCESSING_REVAA }; static void Phaser_postprocessing_revareva(Phaser *self) { POST_PROCESSING_REVAREVA }; static void Phaser_setProcMode(Phaser *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: Phaser_compute_variables(self, PyFloat_AS_DOUBLE(self->freq), PyFloat_AS_DOUBLE(self->spread), PyFloat_AS_DOUBLE(self->q)); self->proc_func_ptr = Phaser_filters_iii; break; case 1: self->proc_func_ptr = Phaser_filters_aii; break; case 10: self->proc_func_ptr = Phaser_filters_iai; break; case 11: self->proc_func_ptr = Phaser_filters_aai; break; case 100: self->proc_func_ptr = Phaser_filters_iia; break; case 101: self->proc_func_ptr = Phaser_filters_aia; break; case 110: self->proc_func_ptr = Phaser_filters_iaa; break; case 111: self->proc_func_ptr = Phaser_filters_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Phaser_postprocessing_ii; break; case 1: self->muladd_func_ptr = Phaser_postprocessing_ai; break; case 2: self->muladd_func_ptr = Phaser_postprocessing_revai; break; case 10: self->muladd_func_ptr = Phaser_postprocessing_ia; break; case 11: self->muladd_func_ptr = Phaser_postprocessing_aa; break; case 12: self->muladd_func_ptr = Phaser_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Phaser_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Phaser_postprocessing_areva; break; case 22: self->muladd_func_ptr = Phaser_postprocessing_revareva; break; } } static void Phaser_compute_next_data_frame(Phaser *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Phaser_traverse(Phaser *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->spread); Py_VISIT(self->spread_stream); Py_VISIT(self->q); Py_VISIT(self->q_stream); Py_VISIT(self->feedback); Py_VISIT(self->feedback_stream); return 0; } static int Phaser_clear(Phaser *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->spread); Py_CLEAR(self->spread_stream); Py_CLEAR(self->q); Py_CLEAR(self->q_stream); Py_CLEAR(self->feedback); Py_CLEAR(self->feedback_stream); return 0; } static void Phaser_dealloc(Phaser* self) { pyo_DEALLOC free(self->y1); free(self->y2); free(self->alpha); free(self->beta); Phaser_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Phaser_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *spreadtmp=NULL, *qtmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL; Phaser *self; self = (Phaser *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000.0); self->spread = PyFloat_FromDouble(1.0); self->q = PyFloat_FromDouble(10.0); self->feedback = PyFloat_FromDouble(0.0); self->tmp = 0.0; self->stages = 8; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->modebuffer[5] = 0; INIT_OBJECT_COMMON self->halfSr = (MYFLT)self->sr * 0.49; self->minusPiOnSr = -PI / self->sr; self->twoPiOnSr = TWOPI / self->sr; self->norm_arr_pos = 1.0 / PI * 512.0; Stream_setFunctionPtr(self->stream, Phaser_compute_next_data_frame); self->mode_func_ptr = Phaser_setProcMode; static char *kwlist[] = {"input", "freq", "spread", "q", "feedback", "num", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOiOO", kwlist, &inputtmp, &freqtmp, &spreadtmp, &qtmp, &feedbacktmp, &self->stages, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM self->y1 = (MYFLT *)realloc(self->y1, self->stages * sizeof(MYFLT)); self->y2 = (MYFLT *)realloc(self->y2, self->stages * sizeof(MYFLT)); self->alpha = (MYFLT *)realloc(self->alpha, self->stages * sizeof(MYFLT)); self->beta = (MYFLT *)realloc(self->beta, self->stages * sizeof(MYFLT)); if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (spreadtmp) { PyObject_CallMethod((PyObject *)self, "setSpread", "O", spreadtmp); } if (qtmp) { PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp); } if (feedbacktmp) { PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); for (i=0; istages; i++) { self->y1[i] = self->y2[i] = 0.0; } return (PyObject *)self; } static PyObject * Phaser_getServer(Phaser* self) { GET_SERVER }; static PyObject * Phaser_getStream(Phaser* self) { GET_STREAM }; static PyObject * Phaser_setMul(Phaser *self, PyObject *arg) { SET_MUL }; static PyObject * Phaser_setAdd(Phaser *self, PyObject *arg) { SET_ADD }; static PyObject * Phaser_setSub(Phaser *self, PyObject *arg) { SET_SUB }; static PyObject * Phaser_setDiv(Phaser *self, PyObject *arg) { SET_DIV }; static PyObject * Phaser_play(Phaser *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Phaser_out(Phaser *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Phaser_stop(Phaser *self) { STOP }; static PyObject * Phaser_multiply(Phaser *self, PyObject *arg) { MULTIPLY }; static PyObject * Phaser_inplace_multiply(Phaser *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Phaser_add(Phaser *self, PyObject *arg) { ADD }; static PyObject * Phaser_inplace_add(Phaser *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Phaser_sub(Phaser *self, PyObject *arg) { SUB }; static PyObject * Phaser_inplace_sub(Phaser *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Phaser_div(Phaser *self, PyObject *arg) { DIV }; static PyObject * Phaser_inplace_div(Phaser *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Phaser_setFreq(Phaser *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Phaser_setSpread(Phaser *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->spread); if (isNumber == 1) { self->spread = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->spread = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->spread, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->spread_stream); self->spread_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Phaser_setQ(Phaser *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->q); if (isNumber == 1) { self->q = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->q = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->q, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->q_stream); self->q_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Phaser_setFeedback(Phaser *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->feedback); if (isNumber == 1) { self->feedback = PyNumber_Float(tmp); self->modebuffer[5] = 0; } else { self->feedback = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->feedback_stream); self->feedback_stream = (Stream *)streamtmp; self->modebuffer[5] = 1; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Phaser_members[] = { {"server", T_OBJECT_EX, offsetof(Phaser, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Phaser, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Phaser, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(Phaser, freq), 0, "Base frequency in Hertz."}, {"spread", T_OBJECT_EX, offsetof(Phaser, spread), 0, "Frequencies spreading factor."}, {"q", T_OBJECT_EX, offsetof(Phaser, q), 0, "Q factor."}, {"feedback", T_OBJECT_EX, offsetof(Phaser, feedback), 0, "Feedback factor."}, {"mul", T_OBJECT_EX, offsetof(Phaser, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Phaser, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Phaser_methods[] = { {"getServer", (PyCFunction)Phaser_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Phaser_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Phaser_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Phaser_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Phaser_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Phaser_setFreq, METH_O, "Sets base frequency in Hertz."}, {"setSpread", (PyCFunction)Phaser_setSpread, METH_O, "Sets spreading factor."}, {"setQ", (PyCFunction)Phaser_setQ, METH_O, "Sets filter Q factor."}, {"setFeedback", (PyCFunction)Phaser_setFeedback, METH_O, "Sets filter Feedback factor."}, {"setMul", (PyCFunction)Phaser_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Phaser_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Phaser_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Phaser_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Phaser_as_number = { (binaryfunc)Phaser_add, /*nb_add*/ (binaryfunc)Phaser_sub, /*nb_subtract*/ (binaryfunc)Phaser_multiply, /*nb_multiply*/ (binaryfunc)Phaser_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Phaser_inplace_add, /*inplace_add*/ (binaryfunc)Phaser_inplace_sub, /*inplace_subtract*/ (binaryfunc)Phaser_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Phaser_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject PhaserType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Phaser_base", /*tp_name*/ sizeof(Phaser), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Phaser_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Phaser_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Phaser objects. Multi-stages second order allpass filters.", /* tp_doc */ (traverseproc)Phaser_traverse, /* tp_traverse */ (inquiry)Phaser_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Phaser_methods, /* tp_methods */ Phaser_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Phaser_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *input2; Stream *input2_stream; PyObject *freq; Stream *freq_stream; PyObject *spread; Stream *spread_stream; PyObject *q; Stream *q_stream; PyObject *slope; Stream *slope_stream; MYFLT last_freq; MYFLT last_spread; MYFLT last_q; MYFLT last_slope; MYFLT factor; int stages; int last_stages; int flag; MYFLT nyquist; MYFLT twoPiOnSr; int modebuffer[6]; // need at least 2 slots for mul & add // sample memories MYFLT *y1; MYFLT *y2; MYFLT *yy1; MYFLT *yy2; // follower memories MYFLT *follow; // coefficients MYFLT *b0; MYFLT *b2; MYFLT *a0; MYFLT *a1; MYFLT *a2; } Vocoder; static void Vocoder_allocate_memories(Vocoder *self) { int i, i2j, j; self->y1 = (MYFLT *)realloc(self->y1, self->stages * 2 * sizeof(MYFLT)); self->y2 = (MYFLT *)realloc(self->y2, self->stages * 2 * sizeof(MYFLT)); self->yy1 = (MYFLT *)realloc(self->yy1, self->stages * 2 * sizeof(MYFLT)); self->yy2 = (MYFLT *)realloc(self->yy2, self->stages * 2 * sizeof(MYFLT)); self->b0 = (MYFLT *)realloc(self->b0, self->stages * sizeof(MYFLT)); self->b2 = (MYFLT *)realloc(self->b2, self->stages * sizeof(MYFLT)); self->a0 = (MYFLT *)realloc(self->a0, self->stages * sizeof(MYFLT)); self->a1 = (MYFLT *)realloc(self->a1, self->stages * sizeof(MYFLT)); self->a2 = (MYFLT *)realloc(self->a2, self->stages * sizeof(MYFLT)); self->follow = (MYFLT *)realloc(self->follow, self->stages * sizeof(MYFLT)); for (i=0; istages; i++) { self->b0[i] = self->b2[i] = self->a0[i] = self->a1[i] = self->a2[i] = self->follow[i] = 0.0; for (j=0; j<2; j++) { i2j = i * 2 + j; self->yy1[i2j] = self->yy2[i2j] = self->y1[i2j] = self->y2[i2j] = 0.0; } } self->flag = 1; } static void Vocoder_compute_variables(Vocoder *self, MYFLT base, MYFLT spread, MYFLT q) { int i; MYFLT w0, c, alpha, freq, invqfac; invqfac = 1.0 / (2.0 * q); for (i=0; istages; i++) { freq = base * MYPOW(i+1, spread); if (freq <= 10) freq = 10.0; else if (freq >= self->nyquist) freq = self->nyquist; w0 = self->twoPiOnSr * freq; c = MYCOS(w0); alpha = MYSIN(w0) * invqfac; self->b0[i] = alpha; self->b2[i] = -alpha; self->a0[i] = 1.0 / (1.0 + alpha); /* Inversed to multiply */ self->a1[i] = -2.0 * c; self->a2[i] = 1.0 - alpha; } } static void Vocoder_filters_iii(Vocoder *self) { int i, j, j2; MYFLT vin, vout, vin2, vout2, w, w2, freq, spread, q, slope, output, amp; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); freq = PyFloat_AS_DOUBLE(self->freq); spread = PyFloat_AS_DOUBLE(self->spread); q = PyFloat_AS_DOUBLE(self->q); if (q < 0.1) q = 0.1; amp = q * 10.0; if (self->modebuffer[5] == 0) slope = PyFloat_AS_DOUBLE(self->slope); else slope = Stream_getData((Stream *)self->slope_stream)[0]; if (slope < 0.0) slope = 0.0; else if (slope > 1.0) slope = 1.0; if (slope != self->last_slope) { self->last_slope = slope; self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0))); } if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) { self->last_freq = freq; self->last_spread = spread; self->last_q = q; self->last_stages = self->stages; self->flag = 0; Vocoder_compute_variables(self, freq, spread, q); } for (i=0; ibufsize; i++) { output = 0.0; vin = in[i]; vin2 = in2[i]; for (j=0; jstages; j++) { j2 = j * 2; /* Analysis part filter 1 */ w = ( vin - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 1 */ w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; j2++; /* Analysis part filter 2 */ w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 2 */ w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; /* Follower */ if (vout < 0.0) vout = -vout; self->follow[j] = vout + self->factor * (self->follow[j] - vout); output += vout2 * self->follow[j]; } self->data[i] = output * amp; } } static void Vocoder_filters_aii(Vocoder *self) { int i, j, j2; int count = 0, maxcount = self->bufsize / 4; MYFLT vin, vout, vin2, vout2, w, w2, spread, q, slope, output, amp; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT freq = fr[0]; spread = PyFloat_AS_DOUBLE(self->spread); q = PyFloat_AS_DOUBLE(self->q); if (q < 0.1) q = 0.1; amp = q * 10.0; if (self->modebuffer[5] == 0) slope = PyFloat_AS_DOUBLE(self->slope); else slope = Stream_getData((Stream *)self->slope_stream)[0]; if (slope < 0.0) slope = 0.0; else if (slope > 1.0) slope = 1.0; if (slope != self->last_slope) { self->last_slope = slope; self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0))); } for (i=0; ibufsize; i++) { if (count == 0) freq = fr[i]; else if (count >= maxcount) count = 0; count++; if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) { self->last_freq = freq; self->last_spread = spread; self->last_q = q; self->last_stages = self->stages; self->flag = 0; Vocoder_compute_variables(self, freq, spread, q); } output = 0.0; vin = in[i]; vin2 = in2[i]; for (j=0; jstages; j++) { j2 = j * 2; /* Analysis part filter 1 */ w = ( vin - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 1 */ w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; j2++; /* Analysis part filter 2 */ w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 2 */ w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; /* Follower */ if (vout < 0.0) vout = -vout; self->follow[j] = vout + self->factor * (self->follow[j] - vout); output += vout2 * self->follow[j]; } self->data[i] = output * amp; } } static void Vocoder_filters_iai(Vocoder *self) { int i, j, j2; int count = 0, maxcount = self->bufsize / 4; MYFLT vin, vout, vin2, vout2, w, w2, freq, q, slope, output, amp; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); freq = PyFloat_AS_DOUBLE(self->freq); MYFLT *sprd = Stream_getData((Stream *)self->spread_stream); MYFLT spread = sprd[0]; q = PyFloat_AS_DOUBLE(self->q); if (q < 0.1) q = 0.1; amp = q * 10.0; if (self->modebuffer[5] == 0) slope = PyFloat_AS_DOUBLE(self->slope); else slope = Stream_getData((Stream *)self->slope_stream)[0]; if (slope < 0.0) slope = 0.0; else if (slope > 1.0) slope = 1.0; if (slope != self->last_slope) { self->last_slope = slope; self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0))); } for (i=0; ibufsize; i++) { if (count == 0) spread = sprd[i]; else if (count >= maxcount) count = 0; count++; if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) { self->last_freq = freq; self->last_spread = spread; self->last_q = q; self->last_stages = self->stages; self->flag = 0; Vocoder_compute_variables(self, freq, spread, q); } output = 0.0; vin = in[i]; vin2 = in2[i]; for (j=0; jstages; j++) { j2 = j * 2; /* Analysis part filter 1 */ w = ( vin - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 1 */ w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; j2++; /* Analysis part filter 2 */ w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 2 */ w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; /* Follower */ if (vout < 0.0) vout = -vout; self->follow[j] = vout + self->factor * (self->follow[j] - vout); output += vout2 * self->follow[j]; } self->data[i] = output * amp; } } static void Vocoder_filters_aai(Vocoder *self) { int i, j, j2; int count = 0, maxcount = self->bufsize / 4; MYFLT vin, vout, vin2, vout2, w, w2, q, slope, output, amp; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT freq = fr[0]; MYFLT *sprd = Stream_getData((Stream *)self->spread_stream); MYFLT spread = sprd[0]; q = PyFloat_AS_DOUBLE(self->q); if (q < 0.1) q = 0.1; amp = q * 10.0; if (self->modebuffer[5] == 0) slope = PyFloat_AS_DOUBLE(self->slope); else slope = Stream_getData((Stream *)self->slope_stream)[0]; if (slope < 0.0) slope = 0.0; else if (slope > 1.0) slope = 1.0; if (slope != self->last_slope) { self->last_slope = slope; self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0))); } for (i=0; ibufsize; i++) { if (count == 0) { freq = fr[i]; spread = sprd[i]; } else if (count >= maxcount) count = 0; count++; if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) { self->last_freq = freq; self->last_spread = spread; self->last_q = q; self->last_stages = self->stages; self->flag = 0; Vocoder_compute_variables(self, freq, spread, q); } output = 0.0; vin = in[i]; vin2 = in2[i]; for (j=0; jstages; j++) { j2 = j * 2; /* Analysis part filter 1 */ w = ( vin - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 1 */ w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; j2++; /* Analysis part filter 2 */ w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 2 */ w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; /* Follower */ if (vout < 0.0) vout = -vout; self->follow[j] = vout + self->factor * (self->follow[j] - vout); output += vout2 * self->follow[j]; } self->data[i] = output * amp; } } static void Vocoder_filters_iia(Vocoder *self) { int i, j, j2; int count = 0, maxcount = self->bufsize / 4; MYFLT vin, vout, vin2, vout2, w, w2, freq, spread, slope, output, amp = 1.0; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); freq = PyFloat_AS_DOUBLE(self->freq); spread = PyFloat_AS_DOUBLE(self->spread); MYFLT *qstr = Stream_getData((Stream *)self->q_stream); MYFLT q = qstr[0]; if (self->modebuffer[5] == 0) slope = PyFloat_AS_DOUBLE(self->slope); else slope = Stream_getData((Stream *)self->slope_stream)[0]; if (slope < 0.0) slope = 0.0; else if (slope > 1.0) slope = 1.0; if (slope != self->last_slope) { self->last_slope = slope; self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0))); } for (i=0; ibufsize; i++) { if (count == 0) { q = qstr[i]; if (q < 0.1) q = 0.1; amp = q * 10.0; } else if (count >= maxcount) count = 0; count++; if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) { self->last_freq = freq; self->last_spread = spread; self->last_q = q; self->last_stages = self->stages; self->flag = 0; Vocoder_compute_variables(self, freq, spread, q); } output = 0.0; vin = in[i]; vin2 = in2[i]; for (j=0; jstages; j++) { j2 = j * 2; /* Analysis part filter 1 */ w = ( vin - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 1 */ w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; j2++; /* Analysis part filter 2 */ w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 2 */ w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; /* Follower */ if (vout < 0.0) vout = -vout; self->follow[j] = vout + self->factor * (self->follow[j] - vout); output += vout2 * self->follow[j]; } self->data[i] = output * amp; } } static void Vocoder_filters_aia(Vocoder *self) { int i, j, j2; int count = 0, maxcount = self->bufsize / 4; MYFLT vin, vout, vin2, vout2, w, w2, spread, slope, output, amp = 1.0; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT freq = fr[0]; spread = PyFloat_AS_DOUBLE(self->spread); MYFLT *qstr = Stream_getData((Stream *)self->q_stream); MYFLT q = qstr[0]; if (self->modebuffer[5] == 0) slope = PyFloat_AS_DOUBLE(self->slope); else slope = Stream_getData((Stream *)self->slope_stream)[0]; if (slope < 0.0) slope = 0.0; else if (slope > 1.0) slope = 1.0; if (slope != self->last_slope) { self->last_slope = slope; self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0))); } for (i=0; ibufsize; i++) { if (count == 0) { freq = fr[i]; q = qstr[i]; if (q < 0.1) q = 0.1; amp = q * 10.0; } else if (count >= maxcount) count = 0; count++; if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) { self->last_freq = freq; self->last_spread = spread; self->last_q = q; self->last_stages = self->stages; self->flag = 0; Vocoder_compute_variables(self, freq, spread, q); } output = 0.0; vin = in[i]; vin2 = in2[i]; for (j=0; jstages; j++) { j2 = j * 2; /* Analysis part filter 1 */ w = ( vin - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 1 */ w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; j2++; /* Analysis part filter 2 */ w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 2 */ w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; /* Follower */ if (vout < 0.0) vout = -vout; self->follow[j] = vout + self->factor * (self->follow[j] - vout); output += vout2 * self->follow[j]; } self->data[i] = output * amp; } } static void Vocoder_filters_iaa(Vocoder *self) { int i, j, j2; int count = 0, maxcount = self->bufsize / 4; MYFLT vin, vout, vin2, vout2, w, w2, freq, slope, output, amp = 1.0; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); freq = PyFloat_AS_DOUBLE(self->freq); MYFLT *sprd = Stream_getData((Stream *)self->spread_stream); MYFLT spread = sprd[0]; MYFLT *qstr = Stream_getData((Stream *)self->q_stream); MYFLT q = qstr[0]; if (self->modebuffer[5] == 0) slope = PyFloat_AS_DOUBLE(self->slope); else slope = Stream_getData((Stream *)self->slope_stream)[0]; if (slope < 0.0) slope = 0.0; else if (slope > 1.0) slope = 1.0; if (slope != self->last_slope) { self->last_slope = slope; self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0))); } for (i=0; ibufsize; i++) { if (count == 0) { spread = sprd[i]; q = qstr[i]; if (q < 0.1) q = 0.1; amp = q * 10.0; } else if (count >= maxcount) count = 0; count++; if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) { self->last_freq = freq; self->last_spread = spread; self->last_q = q; self->last_stages = self->stages; self->flag = 0; Vocoder_compute_variables(self, freq, spread, q); } output = 0.0; vin = in[i]; vin2 = in2[i]; for (j=0; jstages; j++) { j2 = j * 2; /* Analysis part filter 1 */ w = ( vin - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 1 */ w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; j2++; /* Analysis part filter 2 */ w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 2 */ w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; /* Follower */ if (vout < 0.0) vout = -vout; self->follow[j] = vout + self->factor * (self->follow[j] - vout); output += vout2 * self->follow[j]; } self->data[i] = output * amp; } } static void Vocoder_filters_aaa(Vocoder *self) { int i, j, j2; int count = 0, maxcount = self->bufsize / 4; MYFLT vin, vout, vin2, vout2, w, w2, slope, output, amp = 1.0; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT freq = fr[0]; MYFLT *sprd = Stream_getData((Stream *)self->spread_stream); MYFLT spread = sprd[0]; MYFLT *qstr = Stream_getData((Stream *)self->q_stream); MYFLT q = qstr[0]; if (self->modebuffer[5] == 0) slope = PyFloat_AS_DOUBLE(self->slope); else slope = Stream_getData((Stream *)self->slope_stream)[0]; if (slope < 0.0) slope = 0.0; else if (slope > 1.0) slope = 1.0; if (slope != self->last_slope) { self->last_slope = slope; self->factor = MYEXP(-1.0 / (self->sr / ((slope * 99.0) + 1.0))); } for (i=0; ibufsize; i++) { if (count == 0) { freq = fr[i]; spread = sprd[i]; q = qstr[i]; if (q < 0.1) q = 0.1; amp = q * 10.0; } else if (count >= maxcount) count = 0; count++; if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) { self->last_freq = freq; self->last_spread = spread; self->last_q = q; self->last_stages = self->stages; self->flag = 0; Vocoder_compute_variables(self, freq, spread, q); } output = 0.0; vin = in[i]; vin2 = in2[i]; for (j=0; jstages; j++) { j2 = j * 2; /* Analysis part filter 1 */ w = ( vin - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 1 */ w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; j2++; /* Analysis part filter 2 */ w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j]; vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]); self->y2[j2] = self->y1[j2]; self->y1[j2] = w; /* Exciter part filter 2 */ w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j]; vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]); self->yy2[j2] = self->yy1[j2]; self->yy1[j2] = w2; /* Follower */ if (vout < 0.0) vout = -vout; self->follow[j] = vout + self->factor * (self->follow[j] - vout); output += vout2 * self->follow[j]; } self->data[i] = output * amp; } } static void Vocoder_postprocessing_ii(Vocoder *self) { POST_PROCESSING_II }; static void Vocoder_postprocessing_ai(Vocoder *self) { POST_PROCESSING_AI }; static void Vocoder_postprocessing_ia(Vocoder *self) { POST_PROCESSING_IA }; static void Vocoder_postprocessing_aa(Vocoder *self) { POST_PROCESSING_AA }; static void Vocoder_postprocessing_ireva(Vocoder *self) { POST_PROCESSING_IREVA }; static void Vocoder_postprocessing_areva(Vocoder *self) { POST_PROCESSING_AREVA }; static void Vocoder_postprocessing_revai(Vocoder *self) { POST_PROCESSING_REVAI }; static void Vocoder_postprocessing_revaa(Vocoder *self) { POST_PROCESSING_REVAA }; static void Vocoder_postprocessing_revareva(Vocoder *self) { POST_PROCESSING_REVAREVA }; static void Vocoder_setProcMode(Vocoder *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Vocoder_filters_iii; break; case 1: self->proc_func_ptr = Vocoder_filters_aii; break; case 10: self->proc_func_ptr = Vocoder_filters_iai; break; case 11: self->proc_func_ptr = Vocoder_filters_aai; break; case 100: self->proc_func_ptr = Vocoder_filters_iia; break; case 101: self->proc_func_ptr = Vocoder_filters_aia; break; case 110: self->proc_func_ptr = Vocoder_filters_iaa; break; case 111: self->proc_func_ptr = Vocoder_filters_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Vocoder_postprocessing_ii; break; case 1: self->muladd_func_ptr = Vocoder_postprocessing_ai; break; case 2: self->muladd_func_ptr = Vocoder_postprocessing_revai; break; case 10: self->muladd_func_ptr = Vocoder_postprocessing_ia; break; case 11: self->muladd_func_ptr = Vocoder_postprocessing_aa; break; case 12: self->muladd_func_ptr = Vocoder_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Vocoder_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Vocoder_postprocessing_areva; break; case 22: self->muladd_func_ptr = Vocoder_postprocessing_revareva; break; } } static void Vocoder_compute_next_data_frame(Vocoder *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Vocoder_traverse(Vocoder *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->input2); Py_VISIT(self->input2_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->spread); Py_VISIT(self->spread_stream); Py_VISIT(self->q); Py_VISIT(self->q_stream); Py_VISIT(self->slope); Py_VISIT(self->slope_stream); return 0; } static int Vocoder_clear(Vocoder *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->input2); Py_CLEAR(self->input2_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->spread); Py_CLEAR(self->spread_stream); Py_CLEAR(self->q); Py_CLEAR(self->q_stream); Py_CLEAR(self->slope); Py_CLEAR(self->slope_stream); return 0; } static void Vocoder_dealloc(Vocoder* self) { pyo_DEALLOC free(self->y1); free(self->y2); free(self->yy1); free(self->yy2); free(self->b0); free(self->b2); free(self->a0); free(self->a1); free(self->a2); free(self->follow); Vocoder_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Vocoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *freqtmp=NULL, *spreadtmp=NULL, *qtmp=NULL, *slopetmp=NULL, *multmp=NULL, *addtmp=NULL; Vocoder *self; self = (Vocoder *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(60); self->spread = PyFloat_FromDouble(1.25); self->q = PyFloat_FromDouble(20); self->slope = PyFloat_FromDouble(0.5); self->last_freq = self->last_spread = self->last_q = self->last_slope = -1.0; self->factor = 0.99; self->stages = 24; self->last_stages = -1; self->flag = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->modebuffer[5] = 0; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.49; self->twoPiOnSr = (MYFLT)(TWOPI / self->sr); Stream_setFunctionPtr(self->stream, Vocoder_compute_next_data_frame); self->mode_func_ptr = Vocoder_setProcMode; static char *kwlist[] = {"input", "input2", "freq", "spread", "q", "slope", "stages", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOOOiOO", kwlist, &inputtmp, &input2tmp, &freqtmp, &spreadtmp, &qtmp, &slopetmp, &self->stages, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if ( PyObject_HasAttrString((PyObject *)input2tmp, "server") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"input2\" argument of Vocoder must be a PyoObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->input2); self->input2 = input2tmp; input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL); Py_INCREF(input2_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (Stream *)input2_streamtmp; if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (spreadtmp) { PyObject_CallMethod((PyObject *)self, "setSpread", "O", spreadtmp); } if (qtmp) { PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp); } if (slopetmp) { PyObject_CallMethod((PyObject *)self, "setSlope", "O", slopetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Vocoder_allocate_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Vocoder_getServer(Vocoder* self) { GET_SERVER }; static PyObject * Vocoder_getStream(Vocoder* self) { GET_STREAM }; static PyObject * Vocoder_setMul(Vocoder *self, PyObject *arg) { SET_MUL }; static PyObject * Vocoder_setAdd(Vocoder *self, PyObject *arg) { SET_ADD }; static PyObject * Vocoder_setSub(Vocoder *self, PyObject *arg) { SET_SUB }; static PyObject * Vocoder_setDiv(Vocoder *self, PyObject *arg) { SET_DIV }; static PyObject * Vocoder_play(Vocoder *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Vocoder_out(Vocoder *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Vocoder_stop(Vocoder *self) { STOP }; static PyObject * Vocoder_multiply(Vocoder *self, PyObject *arg) { MULTIPLY }; static PyObject * Vocoder_inplace_multiply(Vocoder *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Vocoder_add(Vocoder *self, PyObject *arg) { ADD }; static PyObject * Vocoder_inplace_add(Vocoder *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Vocoder_sub(Vocoder *self, PyObject *arg) { SUB }; static PyObject * Vocoder_inplace_sub(Vocoder *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Vocoder_div(Vocoder *self, PyObject *arg) { DIV }; static PyObject * Vocoder_inplace_div(Vocoder *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Vocoder_setFreq(Vocoder *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Vocoder_setSpread(Vocoder *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->spread); if (isNumber == 1) { self->spread = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->spread = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->spread, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->spread_stream); self->spread_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Vocoder_setQ(Vocoder *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->q); if (isNumber == 1) { self->q = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->q = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->q, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->q_stream); self->q_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Vocoder_setSlope(Vocoder *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->slope); if (isNumber == 1) { self->slope = PyNumber_Float(tmp); self->modebuffer[5] = 0; } else { self->slope = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->slope, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->slope_stream); self->slope_stream = (Stream *)streamtmp; self->modebuffer[5] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Vocoder_setStages(Vocoder *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { self->stages = PyInt_AsLong(arg); Vocoder_allocate_memories(self); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Vocoder_members[] = { {"server", T_OBJECT_EX, offsetof(Vocoder, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Vocoder, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Vocoder, input), 0, "Spectral envelope signal."}, {"input2", T_OBJECT_EX, offsetof(Vocoder, input2), 0, "Exciter signal."}, {"freq", T_OBJECT_EX, offsetof(Vocoder, freq), 0, "Base frequency in cycle per second."}, {"spread", T_OBJECT_EX, offsetof(Vocoder, spread), 0, "Frequency expansion factor."}, {"q", T_OBJECT_EX, offsetof(Vocoder, q), 0, "Q factor."}, {"slope", T_OBJECT_EX, offsetof(Vocoder, slope), 0, "Responsiveness of the follower lowpass filter."}, {"mul", T_OBJECT_EX, offsetof(Vocoder, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Vocoder, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Vocoder_methods[] = { {"getServer", (PyCFunction)Vocoder_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Vocoder_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Vocoder_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Vocoder_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Vocoder_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Vocoder_setFreq, METH_O, "Sets filter base frequency in cycle per second."}, {"setSpread", (PyCFunction)Vocoder_setSpread, METH_O, "Sets frequency expansion factor."}, {"setQ", (PyCFunction)Vocoder_setQ, METH_O, "Sets filter Q factor."}, {"setSlope", (PyCFunction)Vocoder_setSlope, METH_O, "Sets responsiveness of the follower."}, {"setStages", (PyCFunction)Vocoder_setStages, METH_O, "Sets the number of filtering stages."}, {"setMul", (PyCFunction)Vocoder_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Vocoder_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Vocoder_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Vocoder_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Vocoder_as_number = { (binaryfunc)Vocoder_add, /*nb_add*/ (binaryfunc)Vocoder_sub, /*nb_subtract*/ (binaryfunc)Vocoder_multiply, /*nb_multiply*/ (binaryfunc)Vocoder_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Vocoder_inplace_add, /*inplace_add*/ (binaryfunc)Vocoder_inplace_sub, /*inplace_subtract*/ (binaryfunc)Vocoder_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Vocoder_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject VocoderType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Vocoder_base", /*tp_name*/ sizeof(Vocoder), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Vocoder_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Vocoder_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Vocoder objects. Bank of bandpass filters implementing the vocoder effect.", /* tp_doc */ (traverseproc)Vocoder_traverse, /* tp_traverse */ (inquiry)Vocoder_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Vocoder_methods, /* tp_methods */ Vocoder_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Vocoder_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *q; Stream *q_stream; PyObject *type; Stream *type_stream; int modebuffer[5]; // need at least 2 slots for mul & add MYFLT srOverSix; MYFLT last_freq; MYFLT piOverSr; // sample memories MYFLT y1; MYFLT y2; MYFLT y3; MYFLT y4; // variables MYFLT w; } SVF; static void SVF_filters_iii(SVF *self) { int i; MYFLT val, freq, q, type, q1, low, high, band, lowgain, highgain, bandgain; MYFLT *in = Stream_getData((Stream *)self->input_stream); freq = PyFloat_AS_DOUBLE(self->freq); q = PyFloat_AS_DOUBLE(self->q); type = PyFloat_AS_DOUBLE(self->type); if (freq < 0.1) freq = 0.1; else if (freq > self->srOverSix) freq = self->srOverSix; if (freq != self->last_freq) { self->last_freq = freq; self->w = 2.0 * MYSIN(freq * self->piOverSr); } if (q < 0.5) q = 0.5; q1 = 1.0 / q; if (type < 0.0) type = 0.0; else if (type > 1.0) type = 1.0; lowgain = (type <= 0.5) ? (0.5 - type) : 0.0; highgain = (type >= 0.5) ? (type - 0.5) : 0.0; bandgain = (type <= 0.5) ? type : (1.0 - type); for (i=0; ibufsize; i++) { low = self->y2 + self->w * self->y1; high = in[i] - low - q1 * self->y1; band = self->w * high + self->y1; self->y1 = band; self->y2 = low; val = low * lowgain + high * highgain + band * bandgain; low = self->y4 + self->w * self->y3; high = val - low - q1 * self->y3; band = self->w * high + self->y3; self->y3 = band; self->y4 = low; self->data[i] = low * lowgain + high * highgain + band * bandgain; } } static void SVF_filters_aii(SVF *self) { int i; MYFLT val, freq, q, type, q1, low, high, band, lowgain, highgain, bandgain; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); q = PyFloat_AS_DOUBLE(self->q); type = PyFloat_AS_DOUBLE(self->type); if (q < 0.5) q = 0.5; q1 = 1.0 / q; if (type < 0.0) type = 0.0; else if (type > 1.0) type = 1.0; lowgain = (type <= 0.5) ? (0.5 - type) : 0.0; highgain = (type >= 0.5) ? (type - 0.5) : 0.0; bandgain = (type <= 0.5) ? type : (1.0 - type); for (i=0; ibufsize; i++) { freq = fr[i]; if (freq < 0.1) freq = 0.1; else if (freq > self->srOverSix) freq = self->srOverSix; if (freq != self->last_freq) { self->last_freq = freq; self->w = 2.0 * MYSIN(freq * self->piOverSr); } low = self->y2 + self->w * self->y1; high = in[i] - low - q1 * self->y1; band = self->w * high + self->y1; self->y1 = band; self->y2 = low; val = low * lowgain + high * highgain + band * bandgain; low = self->y4 + self->w * self->y3; high = val - low - q1 * self->y3; band = self->w * high + self->y3; self->y3 = band; self->y4 = low; self->data[i] = low * lowgain + high * highgain + band * bandgain; } } static void SVF_filters_iai(SVF *self) { int i; MYFLT val, freq, q, type, q1, low, high, band, lowgain, highgain, bandgain; MYFLT *in = Stream_getData((Stream *)self->input_stream); freq = PyFloat_AS_DOUBLE(self->freq); MYFLT *qst = Stream_getData((Stream *)self->q_stream); type = PyFloat_AS_DOUBLE(self->type); if (freq < 0.1) freq = 0.1; else if (freq > self->srOverSix) freq = self->srOverSix; if (freq != self->last_freq) { self->last_freq = freq; self->w = 2.0 * MYSIN(freq * self->piOverSr); } if (type < 0.0) type = 0.0; else if (type > 1.0) type = 1.0; lowgain = (type <= 0.5) ? (0.5 - type) : 0.0; highgain = (type >= 0.5) ? (type - 0.5) : 0.0; bandgain = (type <= 0.5) ? type : (1.0 - type); for (i=0; ibufsize; i++) { q = qst[i]; if (q < 0.5) q = 0.5; q1 = 1.0 / q; low = self->y2 + self->w * self->y1; high = in[i] - low - q1 * self->y1; band = self->w * high + self->y1; self->y1 = band; self->y2 = low; val = low * lowgain + high * highgain + band * bandgain; low = self->y4 + self->w * self->y3; high = val - low - q1 * self->y3; band = self->w * high + self->y3; self->y3 = band; self->y4 = low; self->data[i] = low * lowgain + high * highgain + band * bandgain; } } static void SVF_filters_aai(SVF *self) { int i; MYFLT val, freq, q, type, q1, low, high, band, lowgain, highgain, bandgain; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *qst = Stream_getData((Stream *)self->q_stream); type = PyFloat_AS_DOUBLE(self->type); if (type < 0.0) type = 0.0; else if (type > 1.0) type = 1.0; lowgain = (type <= 0.5) ? (0.5 - type) : 0.0; highgain = (type >= 0.5) ? (type - 0.5) : 0.0; bandgain = (type <= 0.5) ? type : (1.0 - type); for (i=0; ibufsize; i++) { freq = fr[i]; q = qst[i]; if (freq < 0.1) freq = 0.1; else if (freq > self->srOverSix) freq = self->srOverSix; if (freq != self->last_freq) { self->last_freq = freq; self->w = 2.0 * MYSIN(freq * self->piOverSr); } if (q < 0.5) q = 0.5; q1 = 1.0 / q; low = self->y2 + self->w * self->y1; high = in[i] - low - q1 * self->y1; band = self->w * high + self->y1; self->y1 = band; self->y2 = low; val = low * lowgain + high * highgain + band * bandgain; low = self->y4 + self->w * self->y3; high = val - low - q1 * self->y3; band = self->w * high + self->y3; self->y3 = band; self->y4 = low; self->data[i] = low * lowgain + high * highgain + band * bandgain; } } static void SVF_filters_iia(SVF *self) { int i; MYFLT val, freq, q, type, q1, low, high, band, lowgain, highgain, bandgain; MYFLT *in = Stream_getData((Stream *)self->input_stream); freq = PyFloat_AS_DOUBLE(self->freq); q = PyFloat_AS_DOUBLE(self->q); MYFLT *tp = Stream_getData((Stream *)self->type_stream); if (freq < 0.1) freq = 0.1; else if (freq > self->srOverSix) freq = self->srOverSix; if (freq != self->last_freq) { self->last_freq = freq; self->w = 2.0 * MYSIN(freq * self->piOverSr); } if (q < 0.5) q = 0.5; q1 = 1.0 / q; for (i=0; ibufsize; i++) { type = tp[i]; if (type < 0.0) type = 0.0; else if (type > 1.0) type = 1.0; lowgain = (type <= 0.5) ? (0.5 - type) : 0.0; highgain = (type >= 0.5) ? (type - 0.5) : 0.0; bandgain = (type <= 0.5) ? type : (1.0 - type); low = self->y2 + self->w * self->y1; high = in[i] - low - q1 * self->y1; band = self->w * high + self->y1; self->y1 = band; self->y2 = low; val = low * lowgain + high * highgain + band * bandgain; low = self->y4 + self->w * self->y3; high = val - low - q1 * self->y3; band = self->w * high + self->y3; self->y3 = band; self->y4 = low; self->data[i] = low * lowgain + high * highgain + band * bandgain; } } static void SVF_filters_aia(SVF *self) { int i; MYFLT val, freq, q, type, q1, low, high, band, lowgain, highgain, bandgain; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); q = PyFloat_AS_DOUBLE(self->q); MYFLT *tp = Stream_getData((Stream *)self->type_stream); if (q < 0.5) q = 0.5; q1 = 1.0 / q; for (i=0; ibufsize; i++) { freq = fr[i]; type = tp[i]; if (freq < 0.1) freq = 0.1; else if (freq > self->srOverSix) freq = self->srOverSix; if (freq != self->last_freq) { self->last_freq = freq; self->w = 2.0 * MYSIN(freq * self->piOverSr); } if (type < 0.0) type = 0.0; else if (type > 1.0) type = 1.0; lowgain = (type <= 0.5) ? (0.5 - type) : 0.0; highgain = (type >= 0.5) ? (type - 0.5) : 0.0; bandgain = (type <= 0.5) ? type : (1.0 - type); low = self->y2 + self->w * self->y1; high = in[i] - low - q1 * self->y1; band = self->w * high + self->y1; self->y1 = band; self->y2 = low; val = low * lowgain + high * highgain + band * bandgain; low = self->y4 + self->w * self->y3; high = val - low - q1 * self->y3; band = self->w * high + self->y3; self->y3 = band; self->y4 = low; self->data[i] = low * lowgain + high * highgain + band * bandgain; } } static void SVF_filters_iaa(SVF *self) { int i; MYFLT val, freq, q, type, q1, low, high, band, lowgain, highgain, bandgain; MYFLT *in = Stream_getData((Stream *)self->input_stream); freq = PyFloat_AS_DOUBLE(self->freq); MYFLT *qst = Stream_getData((Stream *)self->q_stream); MYFLT *tp = Stream_getData((Stream *)self->type_stream); if (freq < 0.1) freq = 0.1; else if (freq > self->srOverSix) freq = self->srOverSix; if (freq != self->last_freq) { self->last_freq = freq; self->w = 2.0 * MYSIN(freq * self->piOverSr); } for (i=0; ibufsize; i++) { q = qst[i]; type = tp[i]; if (q < 0.5) q = 0.5; q1 = 1.0 / q; if (type < 0.0) type = 0.0; else if (type > 1.0) type = 1.0; lowgain = (type <= 0.5) ? (0.5 - type) : 0.0; highgain = (type >= 0.5) ? (type - 0.5) : 0.0; bandgain = (type <= 0.5) ? type : (1.0 - type); low = self->y2 + self->w * self->y1; high = in[i] - low - q1 * self->y1; band = self->w * high + self->y1; self->y1 = band; self->y2 = low; val = low * lowgain + high * highgain + band * bandgain; low = self->y4 + self->w * self->y3; high = val - low - q1 * self->y3; band = self->w * high + self->y3; self->y3 = band; self->y4 = low; self->data[i] = low * lowgain + high * highgain + band * bandgain; } } static void SVF_filters_aaa(SVF *self) { int i; MYFLT val, freq, q, type, q1, low, high, band, lowgain, highgain, bandgain; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *qst = Stream_getData((Stream *)self->q_stream); MYFLT *tp = Stream_getData((Stream *)self->type_stream); for (i=0; ibufsize; i++) { freq = fr[i]; q = qst[i]; type = tp[i]; if (freq < 0.1) freq = 0.1; else if (freq > self->srOverSix) freq = self->srOverSix; if (freq != self->last_freq) { self->last_freq = freq; self->w = 2.0 * MYSIN(freq * self->piOverSr); } if (q < 0.5) q = 0.5; q1 = 1.0 / q; if (type < 0.0) type = 0.0; else if (type > 1.0) type = 1.0; lowgain = (type <= 0.5) ? (0.5 - type) : 0.0; highgain = (type >= 0.5) ? (type - 0.5) : 0.0; bandgain = (type <= 0.5) ? type : (1.0 - type); low = self->y2 + self->w * self->y1; high = in[i] - low - q1 * self->y1; band = self->w * high + self->y1; self->y1 = band; self->y2 = low; val = low * lowgain + high * highgain + band * bandgain; low = self->y4 + self->w * self->y3; high = val - low - q1 * self->y3; band = self->w * high + self->y3; self->y3 = band; self->y4 = low; self->data[i] = low * lowgain + high * highgain + band * bandgain; } } static void SVF_postprocessing_ii(SVF *self) { POST_PROCESSING_II }; static void SVF_postprocessing_ai(SVF *self) { POST_PROCESSING_AI }; static void SVF_postprocessing_ia(SVF *self) { POST_PROCESSING_IA }; static void SVF_postprocessing_aa(SVF *self) { POST_PROCESSING_AA }; static void SVF_postprocessing_ireva(SVF *self) { POST_PROCESSING_IREVA }; static void SVF_postprocessing_areva(SVF *self) { POST_PROCESSING_AREVA }; static void SVF_postprocessing_revai(SVF *self) { POST_PROCESSING_REVAI }; static void SVF_postprocessing_revaa(SVF *self) { POST_PROCESSING_REVAA }; static void SVF_postprocessing_revareva(SVF *self) { POST_PROCESSING_REVAREVA }; static void SVF_setProcMode(SVF *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = SVF_filters_iii; break; case 1: self->proc_func_ptr = SVF_filters_aii; break; case 10: self->proc_func_ptr = SVF_filters_iai; break; case 11: self->proc_func_ptr = SVF_filters_aai; break; case 100: self->proc_func_ptr = SVF_filters_iia; break; case 101: self->proc_func_ptr = SVF_filters_aia; break; case 110: self->proc_func_ptr = SVF_filters_iaa; break; case 111: self->proc_func_ptr = SVF_filters_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = SVF_postprocessing_ii; break; case 1: self->muladd_func_ptr = SVF_postprocessing_ai; break; case 2: self->muladd_func_ptr = SVF_postprocessing_revai; break; case 10: self->muladd_func_ptr = SVF_postprocessing_ia; break; case 11: self->muladd_func_ptr = SVF_postprocessing_aa; break; case 12: self->muladd_func_ptr = SVF_postprocessing_revaa; break; case 20: self->muladd_func_ptr = SVF_postprocessing_ireva; break; case 21: self->muladd_func_ptr = SVF_postprocessing_areva; break; case 22: self->muladd_func_ptr = SVF_postprocessing_revareva; break; } } static void SVF_compute_next_data_frame(SVF *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int SVF_traverse(SVF *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->q); Py_VISIT(self->q_stream); Py_VISIT(self->type); Py_VISIT(self->type_stream); return 0; } static int SVF_clear(SVF *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->q); Py_CLEAR(self->q_stream); Py_CLEAR(self->type); Py_CLEAR(self->type_stream); return 0; } static void SVF_dealloc(SVF* self) { pyo_DEALLOC SVF_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SVF_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *typetmp=NULL, *multmp=NULL, *addtmp=NULL; SVF *self; self = (SVF *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->q = PyFloat_FromDouble(1); self->type = PyFloat_FromDouble(0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->y1 = self->y2 = self->y3 = self->y4 = self->w = 0.0; self->last_freq = -1.0; INIT_OBJECT_COMMON self->srOverSix = (MYFLT)self->sr / 6.0; self->piOverSr = PI / self->sr; Stream_setFunctionPtr(self->stream, SVF_compute_next_data_frame); self->mode_func_ptr = SVF_setProcMode; static char *kwlist[] = {"input", "freq", "q", "type", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOO", kwlist, &inputtmp, &freqtmp, &qtmp, &typetmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (qtmp) { PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp); } if (typetmp) { PyObject_CallMethod((PyObject *)self, "setType", "O", typetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * SVF_getServer(SVF* self) { GET_SERVER }; static PyObject * SVF_getStream(SVF* self) { GET_STREAM }; static PyObject * SVF_setMul(SVF *self, PyObject *arg) { SET_MUL }; static PyObject * SVF_setAdd(SVF *self, PyObject *arg) { SET_ADD }; static PyObject * SVF_setSub(SVF *self, PyObject *arg) { SET_SUB }; static PyObject * SVF_setDiv(SVF *self, PyObject *arg) { SET_DIV }; static PyObject * SVF_play(SVF *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SVF_out(SVF *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * SVF_stop(SVF *self) { STOP }; static PyObject * SVF_multiply(SVF *self, PyObject *arg) { MULTIPLY }; static PyObject * SVF_inplace_multiply(SVF *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * SVF_add(SVF *self, PyObject *arg) { ADD }; static PyObject * SVF_inplace_add(SVF *self, PyObject *arg) { INPLACE_ADD }; static PyObject * SVF_sub(SVF *self, PyObject *arg) { SUB }; static PyObject * SVF_inplace_sub(SVF *self, PyObject *arg) { INPLACE_SUB }; static PyObject * SVF_div(SVF *self, PyObject *arg) { DIV }; static PyObject * SVF_inplace_div(SVF *self, PyObject *arg) { INPLACE_DIV }; static PyObject * SVF_setFreq(SVF *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SVF_setQ(SVF *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->q); if (isNumber == 1) { self->q = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->q = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->q, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->q_stream); self->q_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SVF_setType(SVF *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->type); if (isNumber == 1) { self->type = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->type = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->type, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->type_stream); self->type_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef SVF_members[] = { {"server", T_OBJECT_EX, offsetof(SVF, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SVF, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(SVF, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(SVF, freq), 0, "Cutoff frequency in cycle per second."}, {"q", T_OBJECT_EX, offsetof(SVF, q), 0, "Q factor."}, {"type", T_OBJECT_EX, offsetof(SVF, type), 0, "Filter type."}, {"mul", T_OBJECT_EX, offsetof(SVF, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(SVF, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef SVF_methods[] = { {"getServer", (PyCFunction)SVF_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SVF_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SVF_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)SVF_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)SVF_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)SVF_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setQ", (PyCFunction)SVF_setQ, METH_O, "Sets filter Q factor."}, {"setType", (PyCFunction)SVF_setType, METH_O, "Sets filter type factor."}, {"setMul", (PyCFunction)SVF_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)SVF_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)SVF_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)SVF_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods SVF_as_number = { (binaryfunc)SVF_add, /*nb_add*/ (binaryfunc)SVF_sub, /*nb_subtract*/ (binaryfunc)SVF_multiply, /*nb_multiply*/ (binaryfunc)SVF_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)SVF_inplace_add, /*inplace_add*/ (binaryfunc)SVF_inplace_sub, /*inplace_subtract*/ (binaryfunc)SVF_inplace_multiply, /*inplace_multiply*/ (binaryfunc)SVF_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SVFType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SVF_base", /*tp_name*/ sizeof(SVF), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SVF_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &SVF_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SVF objects. Generates a state variable filter.", /* tp_doc */ (traverseproc)SVF_traverse, /* tp_traverse */ (inquiry)SVF_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SVF_methods, /* tp_methods */ SVF_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SVF_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int size; int halfSize; int in_count; int init; double currentValue; double oneOnSize; int modebuffer[2]; MYFLT *buffer; // samples memory } Average; static void Average_process_i(Average *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init) { for (i=0; ibufsize; i++) { if (self->init) { self->buffer[self->in_count] = in[i]; self->currentValue += (double)in[i]; self->in_count++; if (self->in_count < self->halfSize) self->data[i] = 0.0; else self->data[i] = (MYFLT)(self->currentValue * self->oneOnSize); if (self->in_count >= self->size) { self->in_count = 0; self->init = 0; } } else { self->buffer[self->in_count] = in[i]; self->currentValue += (double)in[i]; self->in_count++; if (self->in_count >= self->size) self->in_count = 0; self->currentValue -= (double)self->buffer[self->in_count]; self->data[i] = (MYFLT)(self->currentValue * self->oneOnSize); } } } else { for (i=0; ibufsize; i++) { self->buffer[self->in_count] = in[i]; self->currentValue += (double)in[i]; self->in_count++; if (self->in_count >= self->size) self->in_count = 0; self->currentValue -= (double)self->buffer[self->in_count]; self->data[i] = (MYFLT)(self->currentValue * self->oneOnSize); } } } static void Average_postprocessing_ii(Average *self) { POST_PROCESSING_II }; static void Average_postprocessing_ai(Average *self) { POST_PROCESSING_AI }; static void Average_postprocessing_ia(Average *self) { POST_PROCESSING_IA }; static void Average_postprocessing_aa(Average *self) { POST_PROCESSING_AA }; static void Average_postprocessing_ireva(Average *self) { POST_PROCESSING_IREVA }; static void Average_postprocessing_areva(Average *self) { POST_PROCESSING_AREVA }; static void Average_postprocessing_revai(Average *self) { POST_PROCESSING_REVAI }; static void Average_postprocessing_revaa(Average *self) { POST_PROCESSING_REVAA }; static void Average_postprocessing_revareva(Average *self) { POST_PROCESSING_REVAREVA }; static void Average_setProcMode(Average *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Average_process_i; switch (muladdmode) { case 0: self->muladd_func_ptr = Average_postprocessing_ii; break; case 1: self->muladd_func_ptr = Average_postprocessing_ai; break; case 2: self->muladd_func_ptr = Average_postprocessing_revai; break; case 10: self->muladd_func_ptr = Average_postprocessing_ia; break; case 11: self->muladd_func_ptr = Average_postprocessing_aa; break; case 12: self->muladd_func_ptr = Average_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Average_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Average_postprocessing_areva; break; case 22: self->muladd_func_ptr = Average_postprocessing_revareva; break; } } static void Average_compute_next_data_frame(Average *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Average_traverse(Average *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Average_clear(Average *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Average_dealloc(Average* self) { pyo_DEALLOC free(self->buffer); Average_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Average_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; Average *self; self = (Average *)type->tp_alloc(type, 0); self->size = 10; self->init = 1; self->in_count = 0; self->currentValue = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Average_compute_next_data_frame); self->mode_func_ptr = Average_setProcMode; static char *kwlist[] = {"input", "size", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &inputtmp, &self->size, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->halfSize = (int)(self->size / 2); self->oneOnSize = 1.0 / (double)self->size; self->buffer = (MYFLT *)realloc(self->buffer, (self->size) * sizeof(MYFLT)); for (i=0; i<(self->size); i++) { self->buffer[i] = 0.; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Average_getServer(Average* self) { GET_SERVER }; static PyObject * Average_getStream(Average* self) { GET_STREAM }; static PyObject * Average_setMul(Average *self, PyObject *arg) { SET_MUL }; static PyObject * Average_setAdd(Average *self, PyObject *arg) { SET_ADD }; static PyObject * Average_setSub(Average *self, PyObject *arg) { SET_SUB }; static PyObject * Average_setDiv(Average *self, PyObject *arg) { SET_DIV }; static PyObject * Average_play(Average *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Average_out(Average *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Average_stop(Average *self) { STOP }; static PyObject * Average_multiply(Average *self, PyObject *arg) { MULTIPLY }; static PyObject * Average_inplace_multiply(Average *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Average_add(Average *self, PyObject *arg) { ADD }; static PyObject * Average_inplace_add(Average *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Average_sub(Average *self, PyObject *arg) { SUB }; static PyObject * Average_inplace_sub(Average *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Average_div(Average *self, PyObject *arg) { DIV }; static PyObject * Average_inplace_div(Average *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Average_setSize(Average *self, PyObject *arg) { int i; ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { self->size = PyInt_AsLong(arg); self->halfSize = (int)(self->size / 2); self->oneOnSize = 1.0 / (double)self->size; self->init = 1; self->in_count = 0; self->currentValue = 0.0; self->buffer = (MYFLT *)realloc(self->buffer, (self->size) * sizeof(MYFLT)); for (i=0; i<(self->size); i++) { self->buffer[i] = 0.; } } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Average_members[] = { {"server", T_OBJECT_EX, offsetof(Average, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Average, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Average, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(Average, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Average, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Average_methods[] = { {"getServer", (PyCFunction)Average_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Average_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Average_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Average_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Average_stop, METH_NOARGS, "Stops computing."}, {"setSize", (PyCFunction)Average_setSize, METH_O, "Sets filter kernel size."}, {"setMul", (PyCFunction)Average_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Average_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Average_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Average_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Average_as_number = { (binaryfunc)Average_add, /*nb_add*/ (binaryfunc)Average_sub, /*nb_subtract*/ (binaryfunc)Average_multiply, /*nb_multiply*/ (binaryfunc)Average_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Average_inplace_add, /*inplace_add*/ (binaryfunc)Average_inplace_sub, /*inplace_subtract*/ (binaryfunc)Average_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Average_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject AverageType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Average_base", /*tp_name*/ sizeof(Average), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Average_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Average_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Average objects. Moving average filter.", /* tp_doc */ (traverseproc)Average_traverse, /* tp_traverse */ (inquiry)Average_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Average_methods, /* tp_methods */ Average_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Average_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *q; Stream *q_stream; int modebuffer[4]; // need at least 2 slots for mul & add MYFLT nyquist; MYFLT last_freq; MYFLT last_q; MYFLT twopiOverSr; // sample memories MYFLT x1; MYFLT x2; MYFLT y1; MYFLT y2; // coefficients MYFLT b1; MYFLT b2; MYFLT a; } Reson; static void Reson_compute_coeffs(Reson *self, MYFLT freq, MYFLT q) { MYFLT bw; if (freq < 0.1) freq = 0.1; else if (freq > self->nyquist) freq = self->nyquist; if (q < 0.1) q = 0.1; bw = freq / q; self->b2 = MYEXP(-self->twopiOverSr * bw); self->b1 = (-4.0 * self->b2) / (1.0 + self->b2) * MYCOS(freq * self->twopiOverSr); self->a = 1.0 - MYSQRT(self->b2); } static void Reson_filters_ii(Reson *self) { MYFLT val, fr, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); fr = PyFloat_AS_DOUBLE(self->freq); q = PyFloat_AS_DOUBLE(self->q); if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; Reson_compute_coeffs(self, fr, q); } for (i=0; ibufsize; i++) { val = (self->a * in[i]) - (self->a * self->x2) - (self->b1 * self->y1) - (self->b2 * self->y2); self->y2 = self->y1; self->data[i] = self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; } } static void Reson_filters_ai(Reson *self) { MYFLT val, fr, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); q = PyFloat_AS_DOUBLE(self->q); for (i=0; ibufsize; i++) { fr = freq[i]; if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; Reson_compute_coeffs(self, fr, q); } val = (self->a * in[i]) - (self->a * self->x2) - (self->b1 * self->y1) - (self->b2 * self->y2); self->y2 = self->y1; self->data[i] = self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; } } static void Reson_filters_ia(Reson *self) { MYFLT val, fr, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *qst = Stream_getData((Stream *)self->q_stream); for (i=0; ibufsize; i++) { q = qst[i]; if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; Reson_compute_coeffs(self, fr, q); } val = (self->a * in[i]) - (self->a * self->x2) - (self->b1 * self->y1) - (self->b2 * self->y2); self->y2 = self->y1; self->data[i] = self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; } } static void Reson_filters_aa(Reson *self) { MYFLT val, fr, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT *qst = Stream_getData((Stream *)self->q_stream); for (i=0; ibufsize; i++) { fr = freq[i]; q = qst[i]; if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; Reson_compute_coeffs(self, fr, q); } val = (self->a * in[i]) - (self->a * self->x2) - (self->b1 * self->y1) - (self->b2 * self->y2); self->y2 = self->y1; self->data[i] = self->y1 = val; self->x2 = self->x1; self->x1 = in[i]; } } static void Reson_postprocessing_ii(Reson *self) { POST_PROCESSING_II }; static void Reson_postprocessing_ai(Reson *self) { POST_PROCESSING_AI }; static void Reson_postprocessing_ia(Reson *self) { POST_PROCESSING_IA }; static void Reson_postprocessing_aa(Reson *self) { POST_PROCESSING_AA }; static void Reson_postprocessing_ireva(Reson *self) { POST_PROCESSING_IREVA }; static void Reson_postprocessing_areva(Reson *self) { POST_PROCESSING_AREVA }; static void Reson_postprocessing_revai(Reson *self) { POST_PROCESSING_REVAI }; static void Reson_postprocessing_revaa(Reson *self) { POST_PROCESSING_REVAA }; static void Reson_postprocessing_revareva(Reson *self) { POST_PROCESSING_REVAREVA }; static void Reson_setProcMode(Reson *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Reson_filters_ii; break; case 1: self->proc_func_ptr = Reson_filters_ai; break; case 10: self->proc_func_ptr = Reson_filters_ia; break; case 11: self->proc_func_ptr = Reson_filters_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Reson_postprocessing_ii; break; case 1: self->muladd_func_ptr = Reson_postprocessing_ai; break; case 2: self->muladd_func_ptr = Reson_postprocessing_revai; break; case 10: self->muladd_func_ptr = Reson_postprocessing_ia; break; case 11: self->muladd_func_ptr = Reson_postprocessing_aa; break; case 12: self->muladd_func_ptr = Reson_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Reson_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Reson_postprocessing_areva; break; case 22: self->muladd_func_ptr = Reson_postprocessing_revareva; break; } } static void Reson_compute_next_data_frame(Reson *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Reson_traverse(Reson *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->q); Py_VISIT(self->q_stream); return 0; } static int Reson_clear(Reson *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->q); Py_CLEAR(self->q_stream); return 0; } static void Reson_dealloc(Reson* self) { pyo_DEALLOC Reson_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Reson_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *multmp=NULL, *addtmp=NULL; Reson *self; self = (Reson *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->q = PyFloat_FromDouble(1); self->last_freq = self->last_q = -1.0; self->x1 = self->x2 = self->y1 = self->y2 = 0.0; self->a = self->b1 = self->b2 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.49; self->twopiOverSr = TWOPI / (MYFLT)self->sr; Stream_setFunctionPtr(self->stream, Reson_compute_next_data_frame); self->mode_func_ptr = Reson_setProcMode; static char *kwlist[] = {"input", "freq", "q", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &freqtmp, &qtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (qtmp) { PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Reson_getServer(Reson* self) { GET_SERVER }; static PyObject * Reson_getStream(Reson* self) { GET_STREAM }; static PyObject * Reson_setMul(Reson *self, PyObject *arg) { SET_MUL }; static PyObject * Reson_setAdd(Reson *self, PyObject *arg) { SET_ADD }; static PyObject * Reson_setSub(Reson *self, PyObject *arg) { SET_SUB }; static PyObject * Reson_setDiv(Reson *self, PyObject *arg) { SET_DIV }; static PyObject * Reson_play(Reson *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Reson_out(Reson *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Reson_stop(Reson *self) { STOP }; static PyObject * Reson_multiply(Reson *self, PyObject *arg) { MULTIPLY }; static PyObject * Reson_inplace_multiply(Reson *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Reson_add(Reson *self, PyObject *arg) { ADD }; static PyObject * Reson_inplace_add(Reson *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Reson_sub(Reson *self, PyObject *arg) { SUB }; static PyObject * Reson_inplace_sub(Reson *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Reson_div(Reson *self, PyObject *arg) { DIV }; static PyObject * Reson_inplace_div(Reson *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Reson_setFreq(Reson *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Reson_setQ(Reson *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->q); if (isNumber == 1) { self->q = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->q = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->q, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->q_stream); self->q_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Reson_members[] = { {"server", T_OBJECT_EX, offsetof(Reson, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Reson, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Reson, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(Reson, freq), 0, "Cutoff frequency in cycle per second."}, {"q", T_OBJECT_EX, offsetof(Reson, q), 0, "Q factor."}, {"mul", T_OBJECT_EX, offsetof(Reson, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Reson, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Reson_methods[] = { {"getServer", (PyCFunction)Reson_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Reson_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Reson_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Reson_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Reson_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Reson_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setQ", (PyCFunction)Reson_setQ, METH_O, "Sets filter Q factor."}, {"setMul", (PyCFunction)Reson_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Reson_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Reson_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Reson_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Reson_as_number = { (binaryfunc)Reson_add, /*nb_add*/ (binaryfunc)Reson_sub, /*nb_subtract*/ (binaryfunc)Reson_multiply, /*nb_multiply*/ (binaryfunc)Reson_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Reson_inplace_add, /*inplace_add*/ (binaryfunc)Reson_inplace_sub, /*inplace_subtract*/ (binaryfunc)Reson_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Reson_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ResonType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Reson_base", /*tp_name*/ sizeof(Reson), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Reson_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Reson_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Reson objects. Second-order resonant bandpass filter.", /* tp_doc */ (traverseproc)Reson_traverse, /* tp_traverse */ (inquiry)Reson_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Reson_methods, /* tp_methods */ Reson_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Reson_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *q; Stream *q_stream; int modebuffer[4]; // need at least 2 slots for mul & add int stages; MYFLT nyquist; MYFLT last_freq; MYFLT last_q; MYFLT twopiOverSr; // sample memories MYFLT *x1; MYFLT *x2; MYFLT *y1; MYFLT *y2; // coefficients MYFLT b1; MYFLT b2; MYFLT a; } Resonx; static void Resonx_allocate_memories(Resonx *self) { int i; self->x1 = (MYFLT *)realloc(self->x1, self->stages * sizeof(MYFLT)); self->x2 = (MYFLT *)realloc(self->x2, self->stages * sizeof(MYFLT)); self->y1 = (MYFLT *)realloc(self->y1, self->stages * sizeof(MYFLT)); self->y2 = (MYFLT *)realloc(self->y2, self->stages * sizeof(MYFLT)); for (i=0; i < self->stages; i++) { self->x1[i] = self->x2[i] = self->y1[i] = self->y2[i] = 0.0; } } static void Resonx_compute_coeffs(Resonx *self, MYFLT freq, MYFLT q) { MYFLT bw; if (freq < 0.1) freq = 0.1; else if (freq > self->nyquist) freq = self->nyquist; if (q < 0.1) q = 0.1; bw = freq / q; self->b2 = MYEXP(-self->twopiOverSr * bw); self->b1 = (-4.0 * self->b2) / (1.0 + self->b2) * MYCOS(freq * self->twopiOverSr); self->a = 1.0 - MYSQRT(self->b2); } static void Resonx_filters_ii(Resonx *self) { MYFLT vin, vout, fr, q; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); fr = PyFloat_AS_DOUBLE(self->freq); q = PyFloat_AS_DOUBLE(self->q); if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; Resonx_compute_coeffs(self, fr, q); } vout = 0.0; for (i=0; ibufsize; i++) { vin = in[i]; for (j=0; jstages; j++) { vout = (self->a * vin) - (self->a * self->x2[j]) - (self->b1 * self->y1[j]) - (self->b2 * self->y2[j]); self->x2[j] = self->x1[j]; self->x1[j] = vin; self->y2[j] = self->y1[j]; self->y1[j] = vin = vout; } self->data[i] = vout; } } static void Resonx_filters_ai(Resonx *self) { MYFLT vin, vout, fr, q; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); q = PyFloat_AS_DOUBLE(self->q); vout = 0.0; for (i=0; ibufsize; i++) { vin = in[i]; fr = freq[i]; if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; Resonx_compute_coeffs(self, fr, q); } for (j=0; jstages; j++) { vout = (self->a * vin) - (self->a * self->x2[j]) - (self->b1 * self->y1[j]) - (self->b2 * self->y2[j]); self->x2[j] = self->x1[j]; self->x1[j] = vin; self->y2[j] = self->y1[j]; self->y1[j] = vin = vout; } self->data[i] = vout; } } static void Resonx_filters_ia(Resonx *self) { MYFLT vin, vout, fr, q; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *qst = Stream_getData((Stream *)self->q_stream); vout = 0.0; for (i=0; ibufsize; i++) { vin = in[i]; q = qst[i]; if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; Resonx_compute_coeffs(self, fr, q); } for (j=0; jstages; j++) { vout = (self->a * vin) - (self->a * self->x2[j]) - (self->b1 * self->y1[j]) - (self->b2 * self->y2[j]); self->x2[j] = self->x1[j]; self->x1[j] = vin; self->y2[j] = self->y1[j]; self->y1[j] = vin = vout; } self->data[i] = vout; } } static void Resonx_filters_aa(Resonx *self) { MYFLT vin, vout, fr, q; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT *qst = Stream_getData((Stream *)self->q_stream); vout = 0.0; for (i=0; ibufsize; i++) { vin = in[i]; fr = freq[i]; q = qst[i]; if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; Resonx_compute_coeffs(self, fr, q); } for (j=0; jstages; j++) { vout = (self->a * vin) - (self->a * self->x2[j]) - (self->b1 * self->y1[j]) - (self->b2 * self->y2[j]); self->x2[j] = self->x1[j]; self->x1[j] = vin; self->y2[j] = self->y1[j]; self->y1[j] = vin = vout; } self->data[i] = vout; } } static void Resonx_postprocessing_ii(Resonx *self) { POST_PROCESSING_II }; static void Resonx_postprocessing_ai(Resonx *self) { POST_PROCESSING_AI }; static void Resonx_postprocessing_ia(Resonx *self) { POST_PROCESSING_IA }; static void Resonx_postprocessing_aa(Resonx *self) { POST_PROCESSING_AA }; static void Resonx_postprocessing_ireva(Resonx *self) { POST_PROCESSING_IREVA }; static void Resonx_postprocessing_areva(Resonx *self) { POST_PROCESSING_AREVA }; static void Resonx_postprocessing_revai(Resonx *self) { POST_PROCESSING_REVAI }; static void Resonx_postprocessing_revaa(Resonx *self) { POST_PROCESSING_REVAA }; static void Resonx_postprocessing_revareva(Resonx *self) { POST_PROCESSING_REVAREVA }; static void Resonx_setProcMode(Resonx *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Resonx_filters_ii; break; case 1: self->proc_func_ptr = Resonx_filters_ai; break; case 10: self->proc_func_ptr = Resonx_filters_ia; break; case 11: self->proc_func_ptr = Resonx_filters_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Resonx_postprocessing_ii; break; case 1: self->muladd_func_ptr = Resonx_postprocessing_ai; break; case 2: self->muladd_func_ptr = Resonx_postprocessing_revai; break; case 10: self->muladd_func_ptr = Resonx_postprocessing_ia; break; case 11: self->muladd_func_ptr = Resonx_postprocessing_aa; break; case 12: self->muladd_func_ptr = Resonx_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Resonx_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Resonx_postprocessing_areva; break; case 22: self->muladd_func_ptr = Resonx_postprocessing_revareva; break; } } static void Resonx_compute_next_data_frame(Resonx *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Resonx_traverse(Resonx *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->q); Py_VISIT(self->q_stream); return 0; } static int Resonx_clear(Resonx *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->q); Py_CLEAR(self->q_stream); return 0; } static void Resonx_dealloc(Resonx* self) { pyo_DEALLOC free(self->x1); free(self->x2); free(self->y1); free(self->y2); Resonx_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Resonx_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *multmp=NULL, *addtmp=NULL; Resonx *self; self = (Resonx *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->q = PyFloat_FromDouble(1); self->last_freq = self->last_q = -1.0; self->stages = 4; self->a = self->b1 = self->b2 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.49; self->twopiOverSr = TWOPI / (MYFLT)self->sr; Stream_setFunctionPtr(self->stream, Resonx_compute_next_data_frame); self->mode_func_ptr = Resonx_setProcMode; static char *kwlist[] = {"input", "freq", "q", "stages", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOiOO", kwlist, &inputtmp, &freqtmp, &qtmp, &self->stages, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (qtmp) { PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Resonx_allocate_memories(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Resonx_getServer(Resonx* self) { GET_SERVER }; static PyObject * Resonx_getStream(Resonx* self) { GET_STREAM }; static PyObject * Resonx_setMul(Resonx *self, PyObject *arg) { SET_MUL }; static PyObject * Resonx_setAdd(Resonx *self, PyObject *arg) { SET_ADD }; static PyObject * Resonx_setSub(Resonx *self, PyObject *arg) { SET_SUB }; static PyObject * Resonx_setDiv(Resonx *self, PyObject *arg) { SET_DIV }; static PyObject * Resonx_play(Resonx *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Resonx_out(Resonx *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Resonx_stop(Resonx *self) { STOP }; static PyObject * Resonx_multiply(Resonx *self, PyObject *arg) { MULTIPLY }; static PyObject * Resonx_inplace_multiply(Resonx *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Resonx_add(Resonx *self, PyObject *arg) { ADD }; static PyObject * Resonx_inplace_add(Resonx *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Resonx_sub(Resonx *self, PyObject *arg) { SUB }; static PyObject * Resonx_inplace_sub(Resonx *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Resonx_div(Resonx *self, PyObject *arg) { DIV }; static PyObject * Resonx_inplace_div(Resonx *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Resonx_setFreq(Resonx *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Resonx_setQ(Resonx *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->q); if (isNumber == 1) { self->q = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->q = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->q, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->q_stream); self->q_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Resonx_setStages(Resonx *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { self->stages = PyInt_AsLong(arg); Resonx_allocate_memories(self); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Resonx_members[] = { {"server", T_OBJECT_EX, offsetof(Resonx, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Resonx, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Resonx, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(Resonx, freq), 0, "Cutoff frequency in cycle per second."}, {"q", T_OBJECT_EX, offsetof(Resonx, q), 0, "Q factor."}, {"mul", T_OBJECT_EX, offsetof(Resonx, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Resonx, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Resonx_methods[] = { {"getServer", (PyCFunction)Resonx_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Resonx_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Resonx_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Resonx_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Resonx_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Resonx_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setQ", (PyCFunction)Resonx_setQ, METH_O, "Sets filter Q factor."}, {"setStages", (PyCFunction)Resonx_setStages, METH_O, "Sets the number of stages of the filter."}, {"setMul", (PyCFunction)Resonx_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Resonx_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Resonx_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Resonx_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Resonx_as_number = { (binaryfunc)Resonx_add, /*nb_add*/ (binaryfunc)Resonx_sub, /*nb_subtract*/ (binaryfunc)Resonx_multiply, /*nb_multiply*/ (binaryfunc)Resonx_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Resonx_inplace_add, /*inplace_add*/ (binaryfunc)Resonx_inplace_sub, /*inplace_subtract*/ (binaryfunc)Resonx_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Resonx_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ResonxType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Resonx_base", /*tp_name*/ sizeof(Resonx), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Resonx_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Resonx_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Resonx objects. Cascade of second-order Resonant bandpass filter.", /* tp_doc */ (traverseproc)Resonx_traverse, /* tp_traverse */ (inquiry)Resonx_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Resonx_methods, /* tp_methods */ Resonx_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Resonx_new, /* tp_new */ }; /************/ /* ButLP */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; int modebuffer[3]; // need at least 2 slots for mul & add MYFLT lastFreq; MYFLT nyquist; MYFLT piOnSr; MYFLT sqrt2; // sample memories MYFLT x1; MYFLT x2; MYFLT y1; MYFLT y2; // variables MYFLT a0; MYFLT a1; MYFLT a2; MYFLT b1; MYFLT b2; } ButLP; static void ButLP_filters_i(ButLP *self) { MYFLT val, c, c2; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); if (fr != self->lastFreq) { if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; self->lastFreq = fr; c = 1.0 / MYTAN(self->piOnSr * fr); c2 = c * c; self->a0 = self->a2 = 1.0 / (1.0 + self->sqrt2 * c + c2); self->a1 = 2.0 * self->a0; self->b1 = self->a1 * (1.0 - c2); self->b2 = self->a0 * (1.0 - self->sqrt2 * c + c2); } for (i=0; ibufsize; i++) { val = self->a0 * in[i] + self->a1 * self->x1 + self->a2 * self->x2 - self->b1 * self->y1 - self->b2 * self->y2; self->x2 = self->x1; self->x1 = in[i]; self->y2 = self->y1; self->data[i] = self->y1 = val; } } static void ButLP_filters_a(ButLP *self) { MYFLT val, fr, c, c2; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { fr = freq[i]; if (fr != self->lastFreq) { if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; self->lastFreq = fr; c = 1.0 / MYTAN(self->piOnSr * fr); c2 = c * c; self->a0 = self->a2 = 1.0 / (1.0 + self->sqrt2 * c + c2); self->a1 = 2.0 * self->a0; self->b1 = self->a1 * (1.0 - c2); self->b2 = self->a0 * (1.0 - self->sqrt2 * c + c2); } val = self->a0 * in[i] + self->a1 * self->x1 + self->a2 * self->x2 - self->b1 * self->y1 - self->b2 * self->y2; self->x2 = self->x1; self->x1 = in[i]; self->y2 = self->y1; self->data[i] = self->y1 = val; } } static void ButLP_postprocessing_ii(ButLP *self) { POST_PROCESSING_II }; static void ButLP_postprocessing_ai(ButLP *self) { POST_PROCESSING_AI }; static void ButLP_postprocessing_ia(ButLP *self) { POST_PROCESSING_IA }; static void ButLP_postprocessing_aa(ButLP *self) { POST_PROCESSING_AA }; static void ButLP_postprocessing_ireva(ButLP *self) { POST_PROCESSING_IREVA }; static void ButLP_postprocessing_areva(ButLP *self) { POST_PROCESSING_AREVA }; static void ButLP_postprocessing_revai(ButLP *self) { POST_PROCESSING_REVAI }; static void ButLP_postprocessing_revaa(ButLP *self) { POST_PROCESSING_REVAA }; static void ButLP_postprocessing_revareva(ButLP *self) { POST_PROCESSING_REVAREVA }; static void ButLP_setProcMode(ButLP *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = ButLP_filters_i; break; case 1: self->proc_func_ptr = ButLP_filters_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = ButLP_postprocessing_ii; break; case 1: self->muladd_func_ptr = ButLP_postprocessing_ai; break; case 2: self->muladd_func_ptr = ButLP_postprocessing_revai; break; case 10: self->muladd_func_ptr = ButLP_postprocessing_ia; break; case 11: self->muladd_func_ptr = ButLP_postprocessing_aa; break; case 12: self->muladd_func_ptr = ButLP_postprocessing_revaa; break; case 20: self->muladd_func_ptr = ButLP_postprocessing_ireva; break; case 21: self->muladd_func_ptr = ButLP_postprocessing_areva; break; case 22: self->muladd_func_ptr = ButLP_postprocessing_revareva; break; } } static void ButLP_compute_next_data_frame(ButLP *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int ButLP_traverse(ButLP *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); return 0; } static int ButLP_clear(ButLP *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); return 0; } static void ButLP_dealloc(ButLP* self) { pyo_DEALLOC ButLP_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * ButLP_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL; ButLP *self; self = (ButLP *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->lastFreq = -1.0; self->x1 = self->x2 = self->y1 = self->y2 = self->a0 = self->a1 = self->a2 = self->b1 = self->b2 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.49; self->piOnSr = PI / (MYFLT)self->sr; self->sqrt2 = MYSQRT(2.0); Stream_setFunctionPtr(self->stream, ButLP_compute_next_data_frame); self->mode_func_ptr = ButLP_setProcMode; static char *kwlist[] = {"input", "freq", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &freqtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * ButLP_getServer(ButLP* self) { GET_SERVER }; static PyObject * ButLP_getStream(ButLP* self) { GET_STREAM }; static PyObject * ButLP_setMul(ButLP *self, PyObject *arg) { SET_MUL }; static PyObject * ButLP_setAdd(ButLP *self, PyObject *arg) { SET_ADD }; static PyObject * ButLP_setSub(ButLP *self, PyObject *arg) { SET_SUB }; static PyObject * ButLP_setDiv(ButLP *self, PyObject *arg) { SET_DIV }; static PyObject * ButLP_play(ButLP *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * ButLP_out(ButLP *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * ButLP_stop(ButLP *self) { STOP }; static PyObject * ButLP_multiply(ButLP *self, PyObject *arg) { MULTIPLY }; static PyObject * ButLP_inplace_multiply(ButLP *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * ButLP_add(ButLP *self, PyObject *arg) { ADD }; static PyObject * ButLP_inplace_add(ButLP *self, PyObject *arg) { INPLACE_ADD }; static PyObject * ButLP_sub(ButLP *self, PyObject *arg) { SUB }; static PyObject * ButLP_inplace_sub(ButLP *self, PyObject *arg) { INPLACE_SUB }; static PyObject * ButLP_div(ButLP *self, PyObject *arg) { DIV }; static PyObject * ButLP_inplace_div(ButLP *self, PyObject *arg) { INPLACE_DIV }; static PyObject * ButLP_setFreq(ButLP *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef ButLP_members[] = { {"server", T_OBJECT_EX, offsetof(ButLP, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(ButLP, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(ButLP, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(ButLP, freq), 0, "Cutoff frequency in cycle per second."}, {"mul", T_OBJECT_EX, offsetof(ButLP, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(ButLP, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef ButLP_methods[] = { {"getServer", (PyCFunction)ButLP_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)ButLP_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)ButLP_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)ButLP_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)ButLP_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)ButLP_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setMul", (PyCFunction)ButLP_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)ButLP_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)ButLP_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)ButLP_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods ButLP_as_number = { (binaryfunc)ButLP_add, /*nb_add*/ (binaryfunc)ButLP_sub, /*nb_subtract*/ (binaryfunc)ButLP_multiply, /*nb_multiply*/ (binaryfunc)ButLP_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)ButLP_inplace_add, /*inplace_add*/ (binaryfunc)ButLP_inplace_sub, /*inplace_subtract*/ (binaryfunc)ButLP_inplace_multiply, /*inplace_multiply*/ (binaryfunc)ButLP_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ButLPType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.ButLP_base", /*tp_name*/ sizeof(ButLP), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)ButLP_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &ButLP_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "ButLP objects. Second-order Butterworth lowpass filter.", /* tp_doc */ (traverseproc)ButLP_traverse, /* tp_traverse */ (inquiry)ButLP_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ ButLP_methods, /* tp_methods */ ButLP_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ ButLP_new, /* tp_new */ }; /************/ /* ButHP */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; int modebuffer[3]; // need at least 2 slots for mul & add MYFLT lastFreq; MYFLT nyquist; MYFLT piOnSr; MYFLT sqrt2; // sample memories MYFLT x1; MYFLT x2; MYFLT y1; MYFLT y2; // variables MYFLT a0; MYFLT a1; MYFLT a2; MYFLT b1; MYFLT b2; } ButHP; static void ButHP_filters_i(ButHP *self) { MYFLT val, c, c2; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); if (fr != self->lastFreq) { if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; self->lastFreq = fr; c = MYTAN(self->piOnSr * fr); c2 = c * c; self->a0 = self->a2 = 1.0 / (1.0 + self->sqrt2 * c + c2); self->a1 = -2.0 * self->a0; self->b1 = 2.0 * self->a0 * (c2 - 1.0); self->b2 = self->a0 * (1.0 - self->sqrt2 * c + c2); } for (i=0; ibufsize; i++) { val = self->a0 * in[i] + self->a1 * self->x1 + self->a2 * self->x2 - self->b1 * self->y1 - self->b2 * self->y2; self->x2 = self->x1; self->x1 = in[i]; self->y2 = self->y1; self->data[i] = self->y1 = val; } } static void ButHP_filters_a(ButHP *self) { MYFLT val, fr, c, c2; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { fr = freq[i]; if (fr != self->lastFreq) { if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; self->lastFreq = fr; c = MYTAN(self->piOnSr * fr); c2 = c * c; self->a0 = self->a2 = 1.0 / (1.0 + self->sqrt2 * c + c2); self->a1 = -2.0 * self->a0; self->b1 = 2.0 * self->a0 * (c2 - 1.0); self->b2 = self->a0 * (1.0 - self->sqrt2 * c + c2); } val = self->a0 * in[i] + self->a1 * self->x1 + self->a2 * self->x2 - self->b1 * self->y1 - self->b2 * self->y2; self->x2 = self->x1; self->x1 = in[i]; self->y2 = self->y1; self->data[i] = self->y1 = val; } } static void ButHP_postprocessing_ii(ButHP *self) { POST_PROCESSING_II }; static void ButHP_postprocessing_ai(ButHP *self) { POST_PROCESSING_AI }; static void ButHP_postprocessing_ia(ButHP *self) { POST_PROCESSING_IA }; static void ButHP_postprocessing_aa(ButHP *self) { POST_PROCESSING_AA }; static void ButHP_postprocessing_ireva(ButHP *self) { POST_PROCESSING_IREVA }; static void ButHP_postprocessing_areva(ButHP *self) { POST_PROCESSING_AREVA }; static void ButHP_postprocessing_revai(ButHP *self) { POST_PROCESSING_REVAI }; static void ButHP_postprocessing_revaa(ButHP *self) { POST_PROCESSING_REVAA }; static void ButHP_postprocessing_revareva(ButHP *self) { POST_PROCESSING_REVAREVA }; static void ButHP_setProcMode(ButHP *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = ButHP_filters_i; break; case 1: self->proc_func_ptr = ButHP_filters_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = ButHP_postprocessing_ii; break; case 1: self->muladd_func_ptr = ButHP_postprocessing_ai; break; case 2: self->muladd_func_ptr = ButHP_postprocessing_revai; break; case 10: self->muladd_func_ptr = ButHP_postprocessing_ia; break; case 11: self->muladd_func_ptr = ButHP_postprocessing_aa; break; case 12: self->muladd_func_ptr = ButHP_postprocessing_revaa; break; case 20: self->muladd_func_ptr = ButHP_postprocessing_ireva; break; case 21: self->muladd_func_ptr = ButHP_postprocessing_areva; break; case 22: self->muladd_func_ptr = ButHP_postprocessing_revareva; break; } } static void ButHP_compute_next_data_frame(ButHP *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int ButHP_traverse(ButHP *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); return 0; } static int ButHP_clear(ButHP *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); return 0; } static void ButHP_dealloc(ButHP* self) { pyo_DEALLOC ButHP_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * ButHP_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL; ButHP *self; self = (ButHP *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->lastFreq = -1.0; self->x1 = self->x2 = self->y1 = self->y2 = self->a0 = self->a1 = self->a2 = self->b1 = self->b2 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.49; self->piOnSr = PI / (MYFLT)self->sr; self->sqrt2 = MYSQRT(2.0); Stream_setFunctionPtr(self->stream, ButHP_compute_next_data_frame); self->mode_func_ptr = ButHP_setProcMode; static char *kwlist[] = {"input", "freq", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &freqtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * ButHP_getServer(ButHP* self) { GET_SERVER }; static PyObject * ButHP_getStream(ButHP* self) { GET_STREAM }; static PyObject * ButHP_setMul(ButHP *self, PyObject *arg) { SET_MUL }; static PyObject * ButHP_setAdd(ButHP *self, PyObject *arg) { SET_ADD }; static PyObject * ButHP_setSub(ButHP *self, PyObject *arg) { SET_SUB }; static PyObject * ButHP_setDiv(ButHP *self, PyObject *arg) { SET_DIV }; static PyObject * ButHP_play(ButHP *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * ButHP_out(ButHP *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * ButHP_stop(ButHP *self) { STOP }; static PyObject * ButHP_multiply(ButHP *self, PyObject *arg) { MULTIPLY }; static PyObject * ButHP_inplace_multiply(ButHP *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * ButHP_add(ButHP *self, PyObject *arg) { ADD }; static PyObject * ButHP_inplace_add(ButHP *self, PyObject *arg) { INPLACE_ADD }; static PyObject * ButHP_sub(ButHP *self, PyObject *arg) { SUB }; static PyObject * ButHP_inplace_sub(ButHP *self, PyObject *arg) { INPLACE_SUB }; static PyObject * ButHP_div(ButHP *self, PyObject *arg) { DIV }; static PyObject * ButHP_inplace_div(ButHP *self, PyObject *arg) { INPLACE_DIV }; static PyObject * ButHP_setFreq(ButHP *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef ButHP_members[] = { {"server", T_OBJECT_EX, offsetof(ButHP, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(ButHP, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(ButHP, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(ButHP, freq), 0, "Cutoff frequency in cycle per second."}, {"mul", T_OBJECT_EX, offsetof(ButHP, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(ButHP, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef ButHP_methods[] = { {"getServer", (PyCFunction)ButHP_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)ButHP_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)ButHP_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)ButHP_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)ButHP_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)ButHP_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setMul", (PyCFunction)ButHP_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)ButHP_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)ButHP_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)ButHP_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods ButHP_as_number = { (binaryfunc)ButHP_add, /*nb_add*/ (binaryfunc)ButHP_sub, /*nb_subtract*/ (binaryfunc)ButHP_multiply, /*nb_multiply*/ (binaryfunc)ButHP_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)ButHP_inplace_add, /*inplace_add*/ (binaryfunc)ButHP_inplace_sub, /*inplace_subtract*/ (binaryfunc)ButHP_inplace_multiply, /*inplace_multiply*/ (binaryfunc)ButHP_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ButHPType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.ButHP_base", /*tp_name*/ sizeof(ButHP), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)ButHP_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &ButHP_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "ButHP objects. Second-order Butterworth highpass filter.", /* tp_doc */ (traverseproc)ButHP_traverse, /* tp_traverse */ (inquiry)ButHP_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ ButHP_methods, /* tp_methods */ ButHP_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ ButHP_new, /* tp_new */ }; /************/ /* ButBP */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *q; Stream *q_stream; int modebuffer[4]; // need at least 2 slots for mul & add MYFLT nyquist; MYFLT last_freq; MYFLT last_q; MYFLT piOnSr; // sample memories MYFLT x1; MYFLT x2; MYFLT y1; MYFLT y2; // coefficients MYFLT a0; MYFLT a2; MYFLT b1; MYFLT b2; } ButBP; static void ButBP_compute_coeffs(ButBP *self, MYFLT freq, MYFLT q) { MYFLT bw, c, d; if (freq < 1.0) freq = 1.0; else if (freq > self->nyquist) freq = self->nyquist; if (q < 1.0) q = 1.0; bw = freq / q; c = 1.0 / MYTAN(self->piOnSr * bw); d = 2.0 * MYCOS(2.0 * self->piOnSr * freq); self->a0 = 1.0 / (1.0 + c); self->a2 = -self->a0; self->b1 = self->a2 * c * d; self->b2 = self->a0 * (c - 1.0); } static void ButBP_filters_ii(ButBP *self) { MYFLT val, fr, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); fr = PyFloat_AS_DOUBLE(self->freq); q = PyFloat_AS_DOUBLE(self->q); if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; ButBP_compute_coeffs(self, fr, q); } for (i=0; ibufsize; i++) { val = self->a0 * in[i] + self->a2 * self->x2 - self->b1 * self->y1 - self->b2 * self->y2; self->x2 = self->x1; self->x1 = in[i]; self->y2 = self->y1; self->data[i] = self->y1 = val; } } static void ButBP_filters_ai(ButBP *self) { MYFLT val, fr, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); q = PyFloat_AS_DOUBLE(self->q); for (i=0; ibufsize; i++) { fr = freq[i]; if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; ButBP_compute_coeffs(self, fr, q); } val = self->a0 * in[i] + self->a2 * self->x2 - self->b1 * self->y1 - self->b2 * self->y2; self->x2 = self->x1; self->x1 = in[i]; self->y2 = self->y1; self->data[i] = self->y1 = val; } } static void ButBP_filters_ia(ButBP *self) { MYFLT val, fr, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *qst = Stream_getData((Stream *)self->q_stream); for (i=0; ibufsize; i++) { q = qst[i]; if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; ButBP_compute_coeffs(self, fr, q); } val = self->a0 * in[i] + self->a2 * self->x2 - self->b1 * self->y1 - self->b2 * self->y2; self->x2 = self->x1; self->x1 = in[i]; self->y2 = self->y1; self->data[i] = self->y1 = val; } } static void ButBP_filters_aa(ButBP *self) { MYFLT val, fr, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT *qst = Stream_getData((Stream *)self->q_stream); for (i=0; ibufsize; i++) { fr = freq[i]; q = qst[i]; if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; ButBP_compute_coeffs(self, fr, q); } val = self->a0 * in[i] + self->a2 * self->x2 - self->b1 * self->y1 - self->b2 * self->y2; self->x2 = self->x1; self->x1 = in[i]; self->y2 = self->y1; self->data[i] = self->y1 = val; } } static void ButBP_postprocessing_ii(ButBP *self) { POST_PROCESSING_II }; static void ButBP_postprocessing_ai(ButBP *self) { POST_PROCESSING_AI }; static void ButBP_postprocessing_ia(ButBP *self) { POST_PROCESSING_IA }; static void ButBP_postprocessing_aa(ButBP *self) { POST_PROCESSING_AA }; static void ButBP_postprocessing_ireva(ButBP *self) { POST_PROCESSING_IREVA }; static void ButBP_postprocessing_areva(ButBP *self) { POST_PROCESSING_AREVA }; static void ButBP_postprocessing_revai(ButBP *self) { POST_PROCESSING_REVAI }; static void ButBP_postprocessing_revaa(ButBP *self) { POST_PROCESSING_REVAA }; static void ButBP_postprocessing_revareva(ButBP *self) { POST_PROCESSING_REVAREVA }; static void ButBP_setProcMode(ButBP *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = ButBP_filters_ii; break; case 1: self->proc_func_ptr = ButBP_filters_ai; break; case 10: self->proc_func_ptr = ButBP_filters_ia; break; case 11: self->proc_func_ptr = ButBP_filters_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = ButBP_postprocessing_ii; break; case 1: self->muladd_func_ptr = ButBP_postprocessing_ai; break; case 2: self->muladd_func_ptr = ButBP_postprocessing_revai; break; case 10: self->muladd_func_ptr = ButBP_postprocessing_ia; break; case 11: self->muladd_func_ptr = ButBP_postprocessing_aa; break; case 12: self->muladd_func_ptr = ButBP_postprocessing_revaa; break; case 20: self->muladd_func_ptr = ButBP_postprocessing_ireva; break; case 21: self->muladd_func_ptr = ButBP_postprocessing_areva; break; case 22: self->muladd_func_ptr = ButBP_postprocessing_revareva; break; } } static void ButBP_compute_next_data_frame(ButBP *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int ButBP_traverse(ButBP *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->q); Py_VISIT(self->q_stream); return 0; } static int ButBP_clear(ButBP *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->q); Py_CLEAR(self->q_stream); return 0; } static void ButBP_dealloc(ButBP* self) { pyo_DEALLOC ButBP_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * ButBP_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *multmp=NULL, *addtmp=NULL; ButBP *self; self = (ButBP *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->q = PyFloat_FromDouble(1); self->last_freq = self->last_q = -1.0; self->x1 = self->x2 = self->y1 = self->y2 = 0.0; self->a0 = self->a2 = self->b1 = self->b2 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.49; self->piOnSr = PI / (MYFLT)self->sr; Stream_setFunctionPtr(self->stream, ButBP_compute_next_data_frame); self->mode_func_ptr = ButBP_setProcMode; static char *kwlist[] = {"input", "freq", "q", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &freqtmp, &qtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (qtmp) { PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * ButBP_getServer(ButBP* self) { GET_SERVER }; static PyObject * ButBP_getStream(ButBP* self) { GET_STREAM }; static PyObject * ButBP_setMul(ButBP *self, PyObject *arg) { SET_MUL }; static PyObject * ButBP_setAdd(ButBP *self, PyObject *arg) { SET_ADD }; static PyObject * ButBP_setSub(ButBP *self, PyObject *arg) { SET_SUB }; static PyObject * ButBP_setDiv(ButBP *self, PyObject *arg) { SET_DIV }; static PyObject * ButBP_play(ButBP *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * ButBP_out(ButBP *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * ButBP_stop(ButBP *self) { STOP }; static PyObject * ButBP_multiply(ButBP *self, PyObject *arg) { MULTIPLY }; static PyObject * ButBP_inplace_multiply(ButBP *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * ButBP_add(ButBP *self, PyObject *arg) { ADD }; static PyObject * ButBP_inplace_add(ButBP *self, PyObject *arg) { INPLACE_ADD }; static PyObject * ButBP_sub(ButBP *self, PyObject *arg) { SUB }; static PyObject * ButBP_inplace_sub(ButBP *self, PyObject *arg) { INPLACE_SUB }; static PyObject * ButBP_div(ButBP *self, PyObject *arg) { DIV }; static PyObject * ButBP_inplace_div(ButBP *self, PyObject *arg) { INPLACE_DIV }; static PyObject * ButBP_setFreq(ButBP *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * ButBP_setQ(ButBP *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->q); if (isNumber == 1) { self->q = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->q = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->q, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->q_stream); self->q_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef ButBP_members[] = { {"server", T_OBJECT_EX, offsetof(ButBP, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(ButBP, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(ButBP, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(ButBP, freq), 0, "Cutoff frequency in cycle per second."}, {"q", T_OBJECT_EX, offsetof(ButBP, q), 0, "Q factor."}, {"mul", T_OBJECT_EX, offsetof(ButBP, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(ButBP, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef ButBP_methods[] = { {"getServer", (PyCFunction)ButBP_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)ButBP_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)ButBP_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)ButBP_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)ButBP_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)ButBP_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setQ", (PyCFunction)ButBP_setQ, METH_O, "Sets filter Q factor."}, {"setMul", (PyCFunction)ButBP_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)ButBP_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)ButBP_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)ButBP_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods ButBP_as_number = { (binaryfunc)ButBP_add, /*nb_add*/ (binaryfunc)ButBP_sub, /*nb_subtract*/ (binaryfunc)ButBP_multiply, /*nb_multiply*/ (binaryfunc)ButBP_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)ButBP_inplace_add, /*inplace_add*/ (binaryfunc)ButBP_inplace_sub, /*inplace_subtract*/ (binaryfunc)ButBP_inplace_multiply, /*inplace_multiply*/ (binaryfunc)ButBP_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ButBPType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.ButBP_base", /*tp_name*/ sizeof(ButBP), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)ButBP_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &ButBP_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "ButBP objects. Second-order Butterworth bandpass filter.", /* tp_doc */ (traverseproc)ButBP_traverse, /* tp_traverse */ (inquiry)ButBP_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ ButBP_methods, /* tp_methods */ ButBP_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ ButBP_new, /* tp_new */ }; /************/ /* ButBR */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *q; Stream *q_stream; int modebuffer[4]; // need at least 2 slots for mul & add MYFLT nyquist; MYFLT last_freq; MYFLT last_q; MYFLT piOnSr; // sample memories MYFLT x1; MYFLT x2; MYFLT y1; MYFLT y2; // coefficients MYFLT a0; MYFLT a1; MYFLT a2; MYFLT b1; MYFLT b2; } ButBR; static void ButBR_compute_coeffs(ButBR *self, MYFLT freq, MYFLT q) { MYFLT bw, c, d; if (freq < 1.0) freq = 1.0; else if (freq > self->nyquist) freq = self->nyquist; if (q < 1.0) q = 1.0; bw = freq / q; c = MYTAN(self->piOnSr * bw); d = 2.0 * MYCOS(2.0 * self->piOnSr * freq); self->a0 = self->a2 = 1.0 / (1.0 + c); self->a1 = self->b1 = -self->a0 * d; self->b2 = self->a0 * (1.0 - c); } static void ButBR_filters_ii(ButBR *self) { MYFLT val, fr, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); fr = PyFloat_AS_DOUBLE(self->freq); q = PyFloat_AS_DOUBLE(self->q); if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; ButBR_compute_coeffs(self, fr, q); } for (i=0; ibufsize; i++) { val = self->a0 * in[i] + self->a1 * self->x1 + self->a2 * self->x2 - self->b1 * self->y1 - self->b2 * self->y2; self->x2 = self->x1; self->x1 = in[i]; self->y2 = self->y1; self->data[i] = self->y1 = val; } } static void ButBR_filters_ai(ButBR *self) { MYFLT val, fr, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); q = PyFloat_AS_DOUBLE(self->q); for (i=0; ibufsize; i++) { fr = freq[i]; if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; ButBR_compute_coeffs(self, fr, q); } val = self->a0 * in[i] + self->a1 * self->x1 + self->a2 * self->x2 - self->b1 * self->y1 - self->b2 * self->y2; self->x2 = self->x1; self->x1 = in[i]; self->y2 = self->y1; self->data[i] = self->y1 = val; } } static void ButBR_filters_ia(ButBR *self) { MYFLT val, fr, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *qst = Stream_getData((Stream *)self->q_stream); for (i=0; ibufsize; i++) { q = qst[i]; if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; ButBR_compute_coeffs(self, fr, q); } val = self->a0 * in[i] + self->a1 * self->x1 + self->a2 * self->x2 - self->b1 * self->y1 - self->b2 * self->y2; self->x2 = self->x1; self->x1 = in[i]; self->y2 = self->y1; self->data[i] = self->y1 = val; } } static void ButBR_filters_aa(ButBR *self) { MYFLT val, fr, q; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT *qst = Stream_getData((Stream *)self->q_stream); for (i=0; ibufsize; i++) { fr = freq[i]; q = qst[i]; if (fr != self->last_freq || q != self->last_q) { self->last_freq = fr; self->last_q = q; ButBR_compute_coeffs(self, fr, q); } val = self->a0 * in[i] + self->a1 * self->x1 + self->a2 * self->x2 - self->b1 * self->y1 - self->b2 * self->y2; self->x2 = self->x1; self->x1 = in[i]; self->y2 = self->y1; self->data[i] = self->y1 = val; } } static void ButBR_postprocessing_ii(ButBR *self) { POST_PROCESSING_II }; static void ButBR_postprocessing_ai(ButBR *self) { POST_PROCESSING_AI }; static void ButBR_postprocessing_ia(ButBR *self) { POST_PROCESSING_IA }; static void ButBR_postprocessing_aa(ButBR *self) { POST_PROCESSING_AA }; static void ButBR_postprocessing_ireva(ButBR *self) { POST_PROCESSING_IREVA }; static void ButBR_postprocessing_areva(ButBR *self) { POST_PROCESSING_AREVA }; static void ButBR_postprocessing_revai(ButBR *self) { POST_PROCESSING_REVAI }; static void ButBR_postprocessing_revaa(ButBR *self) { POST_PROCESSING_REVAA }; static void ButBR_postprocessing_revareva(ButBR *self) { POST_PROCESSING_REVAREVA }; static void ButBR_setProcMode(ButBR *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = ButBR_filters_ii; break; case 1: self->proc_func_ptr = ButBR_filters_ai; break; case 10: self->proc_func_ptr = ButBR_filters_ia; break; case 11: self->proc_func_ptr = ButBR_filters_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = ButBR_postprocessing_ii; break; case 1: self->muladd_func_ptr = ButBR_postprocessing_ai; break; case 2: self->muladd_func_ptr = ButBR_postprocessing_revai; break; case 10: self->muladd_func_ptr = ButBR_postprocessing_ia; break; case 11: self->muladd_func_ptr = ButBR_postprocessing_aa; break; case 12: self->muladd_func_ptr = ButBR_postprocessing_revaa; break; case 20: self->muladd_func_ptr = ButBR_postprocessing_ireva; break; case 21: self->muladd_func_ptr = ButBR_postprocessing_areva; break; case 22: self->muladd_func_ptr = ButBR_postprocessing_revareva; break; } } static void ButBR_compute_next_data_frame(ButBR *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int ButBR_traverse(ButBR *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->q); Py_VISIT(self->q_stream); return 0; } static int ButBR_clear(ButBR *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->q); Py_CLEAR(self->q_stream); return 0; } static void ButBR_dealloc(ButBR* self) { pyo_DEALLOC ButBR_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * ButBR_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *multmp=NULL, *addtmp=NULL; ButBR *self; self = (ButBR *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->q = PyFloat_FromDouble(1); self->last_freq = self->last_q = -1.0; self->x1 = self->x2 = self->y1 = self->y2 = 0.0; self->a0 = self->a1 = self->a2 = self->b1 = self->b2 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.49; self->piOnSr = PI / (MYFLT)self->sr; Stream_setFunctionPtr(self->stream, ButBR_compute_next_data_frame); self->mode_func_ptr = ButBR_setProcMode; static char *kwlist[] = {"input", "freq", "q", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &freqtmp, &qtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (qtmp) { PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * ButBR_getServer(ButBR* self) { GET_SERVER }; static PyObject * ButBR_getStream(ButBR* self) { GET_STREAM }; static PyObject * ButBR_setMul(ButBR *self, PyObject *arg) { SET_MUL }; static PyObject * ButBR_setAdd(ButBR *self, PyObject *arg) { SET_ADD }; static PyObject * ButBR_setSub(ButBR *self, PyObject *arg) { SET_SUB }; static PyObject * ButBR_setDiv(ButBR *self, PyObject *arg) { SET_DIV }; static PyObject * ButBR_play(ButBR *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * ButBR_out(ButBR *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * ButBR_stop(ButBR *self) { STOP }; static PyObject * ButBR_multiply(ButBR *self, PyObject *arg) { MULTIPLY }; static PyObject * ButBR_inplace_multiply(ButBR *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * ButBR_add(ButBR *self, PyObject *arg) { ADD }; static PyObject * ButBR_inplace_add(ButBR *self, PyObject *arg) { INPLACE_ADD }; static PyObject * ButBR_sub(ButBR *self, PyObject *arg) { SUB }; static PyObject * ButBR_inplace_sub(ButBR *self, PyObject *arg) { INPLACE_SUB }; static PyObject * ButBR_div(ButBR *self, PyObject *arg) { DIV }; static PyObject * ButBR_inplace_div(ButBR *self, PyObject *arg) { INPLACE_DIV }; static PyObject * ButBR_setFreq(ButBR *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * ButBR_setQ(ButBR *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->q); if (isNumber == 1) { self->q = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->q = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->q, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->q_stream); self->q_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef ButBR_members[] = { {"server", T_OBJECT_EX, offsetof(ButBR, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(ButBR, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(ButBR, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(ButBR, freq), 0, "Cutoff frequency in cycle per second."}, {"q", T_OBJECT_EX, offsetof(ButBR, q), 0, "Q factor."}, {"mul", T_OBJECT_EX, offsetof(ButBR, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(ButBR, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef ButBR_methods[] = { {"getServer", (PyCFunction)ButBR_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)ButBR_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)ButBR_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)ButBR_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)ButBR_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)ButBR_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setQ", (PyCFunction)ButBR_setQ, METH_O, "Sets filter Q factor."}, {"setMul", (PyCFunction)ButBR_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)ButBR_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)ButBR_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)ButBR_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods ButBR_as_number = { (binaryfunc)ButBR_add, /*nb_add*/ (binaryfunc)ButBR_sub, /*nb_subtract*/ (binaryfunc)ButBR_multiply, /*nb_multiply*/ (binaryfunc)ButBR_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)ButBR_inplace_add, /*inplace_add*/ (binaryfunc)ButBR_inplace_sub, /*inplace_subtract*/ (binaryfunc)ButBR_inplace_multiply, /*inplace_multiply*/ (binaryfunc)ButBR_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ButBRType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.ButBR_base", /*tp_name*/ sizeof(ButBR), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)ButBR_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &ButBR_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "ButBR objects. Second-order Butterworth band-reject filter.", /* tp_doc */ (traverseproc)ButBR_traverse, /* tp_traverse */ (inquiry)ButBR_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ ButBR_methods, /* tp_methods */ ButBR_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ ButBR_new, /* tp_new */ }; /****************/ /** ComplexRes **/ /****************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; PyObject *decay; Stream *decay_stream; int modebuffer[4]; // need at least 2 slots for mul & add MYFLT last_freq; MYFLT last_decay; MYFLT oneOnSr; // variables MYFLT res; MYFLT norm; MYFLT coeffx; MYFLT coeffy; // sample memories MYFLT x; MYFLT y; } ComplexRes; static void ComplexRes_filters_ii(ComplexRes *self) { int i; MYFLT ang, x, y; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT freq = PyFloat_AS_DOUBLE(self->freq); MYFLT decay = PyFloat_AS_DOUBLE(self->decay); if (decay <= 0.0001) decay = 0.0001; if (decay != self->last_decay || freq != self->last_freq) { self->res = MYEXP(-1.0/(decay*self->sr)); //self->norm = (1.0-self->res*self->res)/self->res; self->last_decay = decay; ang = (freq*self->oneOnSr)*TWOPI; self->coeffx = self->res * MYCOS(ang); self->coeffy = self->res * MYSIN(ang); self->last_freq = freq; } for (i=0; ibufsize; i++) { x = self->coeffx * self->x - self->coeffy * self->y + in[i]; y = self->coeffy * self->x + self->coeffx * self->y; self->data[i] = y * self->norm; self->x = x; self->y = y; } } static void ComplexRes_filters_ai(ComplexRes *self) { int i, check = 0; MYFLT freq, ang, x, y; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT decay = PyFloat_AS_DOUBLE(self->decay); if (decay <= 0.0001) decay = 0.0001; if (decay != self->last_decay) { self->res = MYEXP(-1.0/(decay*self->sr)); //self->norm = (1.0-self->res*self->res)/self->res; self->last_decay = decay; check = 1; } for (i=0; ibufsize; i++) { freq = fr[i]; if (freq != self->last_freq || check) { ang = (freq*self->oneOnSr)*TWOPI; self->coeffx = self->res * MYCOS(ang); self->coeffy = self->res * MYSIN(ang); self->last_freq = freq; check = 0; } x = self->coeffx * self->x - self->coeffy * self->y + in[i]; y = self->coeffy * self->x + self->coeffx * self->y; self->data[i] = y * self->norm; self->x = x; self->y = y; } } static void ComplexRes_filters_ia(ComplexRes *self) { int i; MYFLT decay, ang, x, y; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT freq = PyFloat_AS_DOUBLE(self->freq); MYFLT *dec = Stream_getData((Stream *)self->decay_stream); for (i=0; ibufsize; i++) { decay = dec[i]; if (decay <= 0.0001) decay = 0.0001; if (freq != self->last_freq || decay != self->last_decay) { self->res = MYEXP(-1.0/(decay*self->sr)); //self->norm = (1.0-self->res*self->res)/self->res; self->last_decay = decay; ang = (freq*self->oneOnSr)*TWOPI; self->coeffx = self->res * MYCOS(ang); self->coeffy = self->res * MYSIN(ang); self->last_freq = freq; } x = self->coeffx * self->x - self->coeffy * self->y + in[i]; y = self->coeffy * self->x + self->coeffx * self->y; self->data[i] = y * self->norm; self->x = x; self->y = y; } } static void ComplexRes_filters_aa(ComplexRes *self) { int i; MYFLT freq, decay, ang, x, y; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *dec = Stream_getData((Stream *)self->decay_stream); for (i=0; ibufsize; i++) { freq = fr[i]; decay = dec[i]; if (decay <= 0.0001) decay = 0.0001; if (freq != self->last_freq || decay != self->last_decay) { self->res = MYEXP(-1.0/(decay*self->sr)); //self->norm = (1.0-self->res*self->res)/self->res; self->last_decay = decay; ang = (freq*self->oneOnSr)*TWOPI; self->coeffx = self->res * MYCOS(ang); self->coeffy = self->res * MYSIN(ang); self->last_freq = freq; } x = self->coeffx * self->x - self->coeffy * self->y + in[i]; y = self->coeffy * self->x + self->coeffx * self->y; self->data[i] = y * self->norm; self->x = x; self->y = y; } } static void ComplexRes_postprocessing_ii(ComplexRes *self) { POST_PROCESSING_II }; static void ComplexRes_postprocessing_ai(ComplexRes *self) { POST_PROCESSING_AI }; static void ComplexRes_postprocessing_ia(ComplexRes *self) { POST_PROCESSING_IA }; static void ComplexRes_postprocessing_aa(ComplexRes *self) { POST_PROCESSING_AA }; static void ComplexRes_postprocessing_ireva(ComplexRes *self) { POST_PROCESSING_IREVA }; static void ComplexRes_postprocessing_areva(ComplexRes *self) { POST_PROCESSING_AREVA }; static void ComplexRes_postprocessing_revai(ComplexRes *self) { POST_PROCESSING_REVAI }; static void ComplexRes_postprocessing_revaa(ComplexRes *self) { POST_PROCESSING_REVAA }; static void ComplexRes_postprocessing_revareva(ComplexRes *self) { POST_PROCESSING_REVAREVA }; static void ComplexRes_setProcMode(ComplexRes *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = ComplexRes_filters_ii; break; case 1: self->proc_func_ptr = ComplexRes_filters_ai; break; case 10: self->proc_func_ptr = ComplexRes_filters_ia; break; case 11: self->proc_func_ptr = ComplexRes_filters_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = ComplexRes_postprocessing_ii; break; case 1: self->muladd_func_ptr = ComplexRes_postprocessing_ai; break; case 2: self->muladd_func_ptr = ComplexRes_postprocessing_revai; break; case 10: self->muladd_func_ptr = ComplexRes_postprocessing_ia; break; case 11: self->muladd_func_ptr = ComplexRes_postprocessing_aa; break; case 12: self->muladd_func_ptr = ComplexRes_postprocessing_revaa; break; case 20: self->muladd_func_ptr = ComplexRes_postprocessing_ireva; break; case 21: self->muladd_func_ptr = ComplexRes_postprocessing_areva; break; case 22: self->muladd_func_ptr = ComplexRes_postprocessing_revareva; break; } } static void ComplexRes_compute_next_data_frame(ComplexRes *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int ComplexRes_traverse(ComplexRes *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->decay); Py_VISIT(self->decay_stream); return 0; } static int ComplexRes_clear(ComplexRes *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->decay); Py_CLEAR(self->decay_stream); return 0; } static void ComplexRes_dealloc(ComplexRes* self) { pyo_DEALLOC ComplexRes_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * ComplexRes_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *decaytmp=NULL, *multmp=NULL, *addtmp=NULL; ComplexRes *self; self = (ComplexRes *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->decay = PyFloat_FromDouble(.25); self->last_freq = self->last_decay = -1.0; self->x = self->y = 0.0; self->res = 1.0; self->norm = 0.01; /* normalization factor fixed at -40 dB */ self->coeffx = self->coeffy = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON self->oneOnSr = 1.0 / self->sr; Stream_setFunctionPtr(self->stream, ComplexRes_compute_next_data_frame); self->mode_func_ptr = ComplexRes_setProcMode; static char *kwlist[] = {"input", "freq", "decay", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &freqtmp, &decaytmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (decaytmp) { PyObject_CallMethod((PyObject *)self, "setDecay", "O", decaytmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * ComplexRes_getServer(ComplexRes* self) { GET_SERVER }; static PyObject * ComplexRes_getStream(ComplexRes* self) { GET_STREAM }; static PyObject * ComplexRes_setMul(ComplexRes *self, PyObject *arg) { SET_MUL }; static PyObject * ComplexRes_setAdd(ComplexRes *self, PyObject *arg) { SET_ADD }; static PyObject * ComplexRes_setSub(ComplexRes *self, PyObject *arg) { SET_SUB }; static PyObject * ComplexRes_setDiv(ComplexRes *self, PyObject *arg) { SET_DIV }; static PyObject * ComplexRes_play(ComplexRes *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * ComplexRes_out(ComplexRes *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * ComplexRes_stop(ComplexRes *self) { STOP }; static PyObject * ComplexRes_multiply(ComplexRes *self, PyObject *arg) { MULTIPLY }; static PyObject * ComplexRes_inplace_multiply(ComplexRes *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * ComplexRes_add(ComplexRes *self, PyObject *arg) { ADD }; static PyObject * ComplexRes_inplace_add(ComplexRes *self, PyObject *arg) { INPLACE_ADD }; static PyObject * ComplexRes_sub(ComplexRes *self, PyObject *arg) { SUB }; static PyObject * ComplexRes_inplace_sub(ComplexRes *self, PyObject *arg) { INPLACE_SUB }; static PyObject * ComplexRes_div(ComplexRes *self, PyObject *arg) { DIV }; static PyObject * ComplexRes_inplace_div(ComplexRes *self, PyObject *arg) { INPLACE_DIV }; static PyObject * ComplexRes_setFreq(ComplexRes *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * ComplexRes_setDecay(ComplexRes *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->decay); if (isNumber == 1) { self->decay = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->decay = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->decay, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->decay_stream); self->decay_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef ComplexRes_members[] = { {"server", T_OBJECT_EX, offsetof(ComplexRes, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(ComplexRes, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(ComplexRes, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(ComplexRes, freq), 0, "Center frequency in cycle per second."}, {"decay", T_OBJECT_EX, offsetof(ComplexRes, decay), 0, "Decaying envelope time in seconds."}, {"mul", T_OBJECT_EX, offsetof(ComplexRes, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(ComplexRes, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef ComplexRes_methods[] = { {"getServer", (PyCFunction)ComplexRes_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)ComplexRes_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)ComplexRes_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)ComplexRes_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)ComplexRes_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)ComplexRes_setFreq, METH_O, "Sets filter center frequency in cycle per second."}, {"setDecay", (PyCFunction)ComplexRes_setDecay, METH_O, "Sets filter decaying envelope time."}, {"setMul", (PyCFunction)ComplexRes_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)ComplexRes_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)ComplexRes_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)ComplexRes_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods ComplexRes_as_number = { (binaryfunc)ComplexRes_add, /*nb_add*/ (binaryfunc)ComplexRes_sub, /*nb_subtract*/ (binaryfunc)ComplexRes_multiply, /*nb_multiply*/ (binaryfunc)ComplexRes_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)ComplexRes_inplace_add, /*inplace_add*/ (binaryfunc)ComplexRes_inplace_sub, /*inplace_subtract*/ (binaryfunc)ComplexRes_inplace_multiply, /*inplace_multiply*/ (binaryfunc)ComplexRes_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ComplexResType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.ComplexRes_base", /*tp_name*/ sizeof(ComplexRes), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)ComplexRes_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &ComplexRes_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "ComplexRes objects. Second order allpass filter.", /* tp_doc */ (traverseproc)ComplexRes_traverse, /* tp_traverse */ (inquiry)ComplexRes_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ ComplexRes_methods, /* tp_methods */ ComplexRes_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ ComplexRes_new, /* tp_new */ };pyo/src/objects/chorusmodule.c0000644000175000017500000010445612652732202015765 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" static MYFLT LFO_ARRAY[513] = {0.0, 0.012271538285719925, 0.024541228522912288, 0.036807222941358832, 0.049067674327418015, 0.061320736302208578, 0.073564563599667426, 0.085797312344439894, 0.098017140329560604, 0.11022220729388306, 0.1224106751992162, 0.13458070850712617, 0.14673047445536175, 0.15885814333386145, 0.17096188876030122, 0.18303988795514095, 0.19509032201612825, 0.20711137619221856, 0.2191012401568698, 0.23105810828067111, 0.24298017990326387, 0.25486565960451457, 0.26671275747489837, 0.27851968938505306, 0.29028467725446233, 0.30200594931922808, 0.31368174039889152, 0.32531029216226293, 0.33688985339222005, 0.34841868024943456, 0.35989503653498811, 0.37131719395183754, 0.38268343236508978, 0.3939920400610481, 0.40524131400498986, 0.41642956009763715, 0.42755509343028208, 0.43861623853852766, 0.44961132965460654, 0.46053871095824001, 0.47139673682599764, 0.48218377207912272, 0.49289819222978404, 0.50353838372571758, 0.51410274419322166, 0.52458968267846895, 0.53499761988709715, 0.54532498842204646, 0.55557023301960218, 0.56573181078361312, 0.57580819141784534, 0.58579785745643886, 0.59569930449243336, 0.60551104140432555, 0.61523159058062682, 0.62485948814238634, 0.63439328416364549, 0.64383154288979139, 0.65317284295377676, 0.66241577759017178, 0.67155895484701833, 0.68060099779545302, 0.68954054473706683, 0.69837624940897292, 0.70710678118654746, 0.71573082528381859, 0.72424708295146689, 0.7326542716724127, 0.74095112535495899, 0.74913639452345926, 0.75720884650648446, 0.76516726562245885, 0.77301045336273688, 0.78073722857209438, 0.78834642762660623, 0.79583690460888346, 0.80320753148064483, 0.81045719825259477, 0.81758481315158371, 0.82458930278502529, 0.83146961230254512, 0.83822470555483797, 0.84485356524970701, 0.8513551931052652, 0.85772861000027212, 0.8639728561215867, 0.87008699110871135, 0.87607009419540649, 0.88192126434835494, 0.88763962040285393, 0.89322430119551532, 0.89867446569395382, 0.90398929312344334, 0.90916798309052238, 0.91420975570353069, 0.91911385169005777, 0.92387953251128674, 0.92850608047321548, 0.93299279883473885, 0.93733901191257496, 0.94154406518302081, 0.94560732538052128, 0.94952818059303667, 0.95330604035419375, 0.95694033573220894, 0.96043051941556579, 0.96377606579543984, 0.96697647104485207, 0.97003125319454397, 0.97293995220556007, 0.97570213003852857, 0.97831737071962765, 0.98078528040323043, 0.98310548743121629, 0.98527764238894122, 0.98730141815785843, 0.98917650996478101, 0.99090263542778001, 0.99247953459870997, 0.99390697000235606, 0.99518472667219682, 0.996312612182778, 0.99729045667869021, 0.99811811290014918, 0.99879545620517241, 0.99932238458834954, 0.99969881869620425, 0.9999247018391445, 1.0, 0.9999247018391445, 0.99969881869620425, 0.99932238458834954, 0.99879545620517241, 0.99811811290014918, 0.99729045667869021, 0.996312612182778, 0.99518472667219693, 0.99390697000235606, 0.99247953459870997, 0.99090263542778001, 0.98917650996478101, 0.98730141815785843, 0.98527764238894122, 0.98310548743121629, 0.98078528040323043, 0.97831737071962765, 0.97570213003852857, 0.97293995220556018, 0.97003125319454397, 0.96697647104485207, 0.96377606579543984, 0.9604305194155659, 0.95694033573220894, 0.95330604035419386, 0.94952818059303667, 0.94560732538052139, 0.94154406518302081, 0.93733901191257496, 0.93299279883473885, 0.92850608047321559, 0.92387953251128674, 0.91911385169005777, 0.91420975570353069, 0.90916798309052249, 0.90398929312344345, 0.89867446569395393, 0.89322430119551521, 0.88763962040285393, 0.88192126434835505, 0.8760700941954066, 0.87008699110871146, 0.86397285612158681, 0.85772861000027212, 0.8513551931052652, 0.84485356524970723, 0.83822470555483819, 0.83146961230254546, 0.82458930278502529, 0.81758481315158371, 0.81045719825259477, 0.80320753148064494, 0.79583690460888357, 0.78834642762660634, 0.7807372285720946, 0.7730104533627371, 0.76516726562245907, 0.75720884650648479, 0.74913639452345926, 0.74095112535495899, 0.73265427167241282, 0.724247082951467, 0.71573082528381871, 0.70710678118654757, 0.69837624940897292, 0.68954054473706705, 0.68060099779545324, 0.67155895484701855, 0.66241577759017201, 0.65317284295377664, 0.64383154288979139, 0.63439328416364549, 0.62485948814238634, 0.61523159058062693, 0.60551104140432555, 0.59569930449243347, 0.58579785745643898, 0.57580819141784545, 0.56573181078361345, 0.55557023301960218, 0.54532498842204635, 0.53499761988709715, 0.52458968267846895, 0.51410274419322177, 0.50353838372571758, 0.49289819222978415, 0.48218377207912289, 0.47139673682599781, 0.46053871095824023, 0.44961132965460687, 0.43861623853852755, 0.42755509343028203, 0.41642956009763715, 0.40524131400498986, 0.39399204006104815, 0.38268343236508984, 0.37131719395183765, 0.35989503653498833, 0.34841868024943479, 0.33688985339222027, 0.3253102921622632, 0.31368174039889141, 0.30200594931922803, 0.29028467725446233, 0.27851968938505312, 0.26671275747489848, 0.25486565960451468, 0.24298017990326404, 0.2310581082806713, 0.21910124015687002, 0.20711137619221884, 0.19509032201612858, 0.1830398879551409, 0.17096188876030119, 0.15885814333386145, 0.1467304744553618, 0.13458070850712628, 0.12241067519921635, 0.11022220729388325, 0.09801714032956084, 0.085797312344440158, 0.073564563599667745, 0.061320736302208495, 0.049067674327417973, 0.036807222941358832, 0.024541228522912326, 0.012271538285720007, 1.2246467991473532e-16, -0.012271538285719761, -0.024541228522912083, -0.036807222941358582, -0.049067674327417724, -0.061320736302208245, -0.073564563599667496, -0.085797312344439922, -0.09801714032956059, -0.110222207293883, -0.1224106751992161, -0.13458070850712606, -0.14673047445536158, -0.15885814333386122, -0.17096188876030097, -0.18303988795514067, -0.19509032201612836, -0.20711137619221862, -0.21910124015686983, -0.23105810828067111, -0.24298017990326382, -0.25486565960451446, -0.26671275747489825, -0.27851968938505289, -0.29028467725446216, -0.30200594931922781, -0.31368174039889118, -0.32531029216226304, -0.33688985339222011, -0.34841868024943456, -0.35989503653498811, -0.37131719395183749, -0.38268343236508967, -0.39399204006104793, -0.40524131400498969, -0.41642956009763693, -0.42755509343028181, -0.43861623853852733, -0.44961132965460665, -0.46053871095824006, -0.47139673682599764, -0.48218377207912272, -0.49289819222978393, -0.50353838372571746, -0.51410274419322155, -0.52458968267846873, -0.53499761988709693, -0.54532498842204613, -0.55557023301960196, -0.56573181078361323, -0.57580819141784534, -0.58579785745643886, -0.59569930449243325, -0.60551104140432543, -0.61523159058062671, -0.62485948814238623, -0.63439328416364527, -0.64383154288979128, -0.65317284295377653, -0.66241577759017178, -0.67155895484701844, -0.68060099779545302, -0.68954054473706683, -0.6983762494089728, -0.70710678118654746, -0.71573082528381848, -0.72424708295146667, -0.73265427167241259, -0.74095112535495877, -0.74913639452345904, -0.75720884650648423, -0.76516726562245885, -0.77301045336273666, -0.78073722857209438, -0.78834642762660589, -0.79583690460888334, -0.80320753148064505, -0.81045719825259466, -0.81758481315158371, -0.82458930278502507, -0.83146961230254524, -0.83822470555483775, -0.84485356524970712, -0.85135519310526486, -0.85772861000027201, -0.86397285612158647, -0.87008699110871135, -0.87607009419540671, -0.88192126434835494, -0.88763962040285405, -0.89322430119551521, -0.89867446569395382, -0.90398929312344312, -0.90916798309052238, -0.91420975570353047, -0.91911385169005766, -0.92387953251128652, -0.92850608047321548, -0.93299279883473896, -0.93733901191257485, -0.94154406518302081, -0.94560732538052117, -0.94952818059303667, -0.95330604035419375, -0.95694033573220882, -0.96043051941556568, -0.96377606579543984, -0.96697647104485218, -0.97003125319454397, -0.97293995220556018, -0.97570213003852846, -0.97831737071962765, -0.98078528040323032, -0.98310548743121629, -0.98527764238894111, -0.98730141815785832, -0.9891765099647809, -0.99090263542778001, -0.99247953459871008, -0.99390697000235606, -0.99518472667219693, -0.996312612182778, -0.99729045667869021, -0.99811811290014918, -0.99879545620517241, -0.99932238458834943, -0.99969881869620425, -0.9999247018391445, -1.0, -0.9999247018391445, -0.99969881869620425, -0.99932238458834954, -0.99879545620517241, -0.99811811290014918, -0.99729045667869021, -0.996312612182778, -0.99518472667219693, -0.99390697000235606, -0.99247953459871008, -0.99090263542778001, -0.9891765099647809, -0.98730141815785843, -0.98527764238894122, -0.9831054874312164, -0.98078528040323043, -0.97831737071962777, -0.97570213003852857, -0.97293995220556029, -0.97003125319454397, -0.96697647104485229, -0.96377606579543995, -0.96043051941556579, -0.95694033573220894, -0.95330604035419375, -0.94952818059303679, -0.94560732538052128, -0.94154406518302092, -0.93733901191257496, -0.93299279883473907, -0.92850608047321559, -0.92387953251128663, -0.91911385169005788, -0.91420975570353058, -0.90916798309052249, -0.90398929312344334, -0.89867446569395404, -0.89322430119551532, -0.88763962040285416, -0.88192126434835505, -0.87607009419540693, -0.87008699110871146, -0.8639728561215867, -0.85772861000027223, -0.85135519310526508, -0.84485356524970734, -0.83822470555483797, -0.83146961230254557, -0.82458930278502529, -0.81758481315158404, -0.81045719825259488, -0.80320753148064528, -0.79583690460888368, -0.78834642762660612, -0.78073722857209471, -0.77301045336273688, -0.76516726562245918, -0.75720884650648457, -0.7491363945234597, -0.74095112535495922, -0.73265427167241315, -0.72424708295146711, -0.71573082528381904, -0.70710678118654768, -0.69837624940897269, -0.68954054473706716, -0.68060099779545302, -0.67155895484701866, -0.66241577759017178, -0.65317284295377709, -0.6438315428897915, -0.63439328416364593, -0.62485948814238645, -0.61523159058062737, -0.60551104140432566, -0.59569930449243325, -0.58579785745643909, -0.57580819141784523, -0.56573181078361356, -0.55557023301960218, -0.5453249884220468, -0.53499761988709726, -0.52458968267846939, -0.51410274419322188, -0.50353838372571813, -0.49289819222978426, -0.48218377207912261, -0.47139673682599792, -0.46053871095823995, -0.44961132965460698, -0.43861623853852766, -0.42755509343028253, -0.41642956009763726, -0.40524131400499042, -0.39399204006104827, -0.38268343236509039, -0.37131719395183777, -0.359895036534988, -0.3484186802494349, -0.33688985339222, -0.32531029216226331, -0.31368174039889152, -0.30200594931922853, -0.29028467725446244, -0.27851968938505367, -0.26671275747489859, -0.25486565960451435, -0.24298017990326418, -0.23105810828067103, -0.21910124015687016, -0.20711137619221853, -0.19509032201612872, -0.18303988795514103, -0.17096188876030177, -0.15885814333386158, -0.14673047445536239, -0.13458070850712642, -0.12241067519921603, -0.11022220729388338, -0.09801714032956052, -0.085797312344440282, -0.073564563599667426, -0.06132073630220905, -0.049067674327418091, -0.036807222941359394, -0.024541228522912451, -0.012271538285720572, 0.0}; /* center delay time, delay time deviation, lfo frequency */ static const MYFLT chorusParams[8][3] = { { 384.0, 44.0, 1.879 }, { 450.0, 53.0, 1.654 }, { 489.0, 57.0, 1.342 }, { 553.0, 62.0, 1.231 }, { 591.0, 66.0, 0.879 }, { 662.0, 71.0, 0.657 }, { 753.0, 88.0, 0.465 }, { 785.0, 101.0, 0.254 } }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *feedback; Stream *feedback_stream; PyObject *depth; Stream *depth_stream; PyObject *mix; Stream *mix_stream; void (*mix_func_ptr)(); int modebuffer[5]; MYFLT total_signal; MYFLT delays[8]; MYFLT delay_devs[8]; long size[8]; long in_count[8]; MYFLT *buffer[8]; // jitters MYFLT pointerPos[8]; MYFLT inc[8]; } Chorus; static void Chorus_process_ii(Chorus *self) { MYFLT lfo, pos, val, fpart, inval; int i, j, ipart; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT dpth = PyFloat_AS_DOUBLE(self->depth); MYFLT feed = PyFloat_AS_DOUBLE(self->feedback); if (dpth < 0) dpth = 0; else if (dpth > 5) dpth = 5; if (feed < 0) feed = 0; else if (feed > 1) feed = 1; for (i=0; ibufsize; i++) { inval = in[i]; self->total_signal = 0.0; for (j=0; j<8; j++) { if (self->pointerPos[j] < 0.0) self->pointerPos[j] += 512.0; else if (self->pointerPos[j] >= 512.0) self->pointerPos[j] -= 512.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; lfo = self->delay_devs[j] * dpth * (LFO_ARRAY[ipart] * (1.0 - fpart) + LFO_ARRAY[ipart+1] * fpart) + self->delays[j]; self->pointerPos[j] += self->inc[j]; pos = self->in_count[j] - lfo; if (pos < 0) pos += self->size[j]; ipart = (int)pos; fpart = pos - ipart; val = (self->buffer[j][ipart] * (1.0 - fpart) + self->buffer[j][ipart+1] * fpart); self->total_signal += val; self->buffer[j][self->in_count[j]] = inval + val * feed; if (self->in_count[j] == 0) self->buffer[j][self->size[j]] = self->buffer[j][self->in_count[j]]; self->in_count[j]++; if (self->in_count[j] >= self->size[j]) self->in_count[j] = 0; } self->data[i] = self->total_signal * 0.25; } } static void Chorus_process_ai(Chorus *self) { MYFLT lfo, pos, val, fpart, inval, dpth; int i, j, ipart; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *depth = Stream_getData((Stream *)self->depth_stream); MYFLT feed = PyFloat_AS_DOUBLE(self->feedback); for (i=0; ibufsize; i++) { inval = in[i]; dpth = depth[i]; if (dpth < 0) dpth = 0; else if (dpth > 5) dpth = 5; self->total_signal = 0.0; for (j=0; j<8; j++) { if (self->pointerPos[j] < 0.0) self->pointerPos[j] += 512.0; else if (self->pointerPos[j] >= 512.0) self->pointerPos[j] -= 512.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; lfo = self->delay_devs[j] * dpth * (LFO_ARRAY[ipart] * (1.0 - fpart) + LFO_ARRAY[ipart+1] * fpart) + self->delays[j]; self->pointerPos[j] += self->inc[j]; pos = self->in_count[j] - lfo; if (pos < 0) pos += self->size[j]; ipart = (int)pos; fpart = pos - ipart; val = (self->buffer[j][ipart] * (1.0 - fpart) + self->buffer[j][ipart+1] * fpart); self->total_signal += val; self->buffer[j][self->in_count[j]] = inval + val * feed; if (self->in_count[j] == 0) self->buffer[j][self->size[j]] = self->buffer[j][self->in_count[j]]; self->in_count[j]++; if (self->in_count[j] >= self->size[j]) self->in_count[j] = 0; } self->data[i] = self->total_signal * 0.25; } } static void Chorus_process_ia(Chorus *self) { MYFLT lfo, pos, val, fpart, inval, feed; int i, j, ipart; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT dpth = PyFloat_AS_DOUBLE(self->depth); MYFLT *feedback = Stream_getData((Stream *)self->feedback_stream); for (i=0; ibufsize; i++) { inval = in[i]; feed = feedback[i]; if (feed < 0) feed = 0; else if (feed > 1) feed = 1; self->total_signal = 0.0; for (j=0; j<8; j++) { if (self->pointerPos[j] < 0.0) self->pointerPos[j] += 512.0; else if (self->pointerPos[j] >= 512.0) self->pointerPos[j] -= 512.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; lfo = self->delay_devs[j] * dpth * (LFO_ARRAY[ipart] * (1.0 - fpart) + LFO_ARRAY[ipart+1] * fpart) + self->delays[j]; self->pointerPos[j] += self->inc[j]; pos = self->in_count[j] - lfo; if (pos < 0) pos += self->size[j]; ipart = (int)pos; fpart = pos - ipart; val = (self->buffer[j][ipart] * (1.0 - fpart) + self->buffer[j][ipart+1] * fpart); self->total_signal += val; self->buffer[j][self->in_count[j]] = inval + val * feed; if (self->in_count[j] == 0) self->buffer[j][self->size[j]] = self->buffer[j][self->in_count[j]]; self->in_count[j]++; if (self->in_count[j] >= self->size[j]) self->in_count[j] = 0; } self->data[i] = self->total_signal * 0.25; } } static void Chorus_process_aa(Chorus *self) { MYFLT lfo, pos, val, fpart, inval, dpth, feed; int i, j, ipart; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *depth = Stream_getData((Stream *)self->depth_stream); MYFLT *feedback = Stream_getData((Stream *)self->feedback_stream); for (i=0; ibufsize; i++) { inval = in[i]; dpth = depth[i]; feed = feedback[i]; if (dpth < 0) dpth = 0; else if (dpth > 5) dpth = 5; if (feed < 0) feed = 0; else if (feed > 1) feed = 1; self->total_signal = 0.0; for (j=0; j<8; j++) { if (self->pointerPos[j] < 0.0) self->pointerPos[j] += 512.0; else if (self->pointerPos[j] >= 512.0) self->pointerPos[j] -= 512.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; lfo = self->delay_devs[j] * dpth * (LFO_ARRAY[ipart] * (1.0 - fpart) + LFO_ARRAY[ipart+1] * fpart) + self->delays[j]; self->pointerPos[j] += self->inc[j]; pos = self->in_count[j] - lfo; if (pos < 0) pos += self->size[j]; ipart = (int)pos; fpart = pos - ipart; val = (self->buffer[j][ipart] * (1.0 - fpart) + self->buffer[j][ipart+1] * fpart); self->total_signal += val; self->buffer[j][self->in_count[j]] = inval + val * feed; if (self->in_count[j] == 0) self->buffer[j][self->size[j]] = self->buffer[j][self->in_count[j]]; self->in_count[j]++; if (self->in_count[j] >= self->size[j]) self->in_count[j] = 0; } self->data[i] = self->total_signal * 0.25; } } static void Chorus_mix_i(Chorus *self) { int i; MYFLT val; MYFLT mix = PyFloat_AS_DOUBLE(self->mix); MYFLT *in = Stream_getData((Stream *)self->input_stream); if (mix < 0.0) mix = 0.0; else if (mix > 1.0) mix = 1.0; for (i=0; ibufsize; i++) { val = in[i] * (1.0 - mix) + self->data[i] * mix; self->data[i] = val; } } static void Chorus_mix_a(Chorus *self) { int i; MYFLT mix, val; MYFLT *mi = Stream_getData((Stream *)self->mix_stream); MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { mix = mi[i]; if (mix < 0.0) mix = 0.0; else if (mix > 1.0) mix = 1.0; val = in[i] * (1.0 - mix) + self->data[i] * mix; self->data[i] = val; } } static void Chorus_postprocessing_ii(Chorus *self) { POST_PROCESSING_II }; static void Chorus_postprocessing_ai(Chorus *self) { POST_PROCESSING_AI }; static void Chorus_postprocessing_ia(Chorus *self) { POST_PROCESSING_IA }; static void Chorus_postprocessing_aa(Chorus *self) { POST_PROCESSING_AA }; static void Chorus_postprocessing_ireva(Chorus *self) { POST_PROCESSING_IREVA }; static void Chorus_postprocessing_areva(Chorus *self) { POST_PROCESSING_AREVA }; static void Chorus_postprocessing_revai(Chorus *self) { POST_PROCESSING_REVAI }; static void Chorus_postprocessing_revaa(Chorus *self) { POST_PROCESSING_REVAA }; static void Chorus_postprocessing_revareva(Chorus *self) { POST_PROCESSING_REVAREVA }; static void Chorus_setProcMode(Chorus *self) { int procmode, muladdmode, mixmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; mixmode = self->modebuffer[4]; switch (procmode) { case 0: self->proc_func_ptr = Chorus_process_ii; break; case 1: self->proc_func_ptr = Chorus_process_ai; break; case 10: self->proc_func_ptr = Chorus_process_ia; break; case 11: self->proc_func_ptr = Chorus_process_aa; break; } switch (mixmode) { case 0: self->mix_func_ptr = Chorus_mix_i; break; case 1: self->mix_func_ptr = Chorus_mix_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Chorus_postprocessing_ii; break; case 1: self->muladd_func_ptr = Chorus_postprocessing_ai; break; case 2: self->muladd_func_ptr = Chorus_postprocessing_revai; break; case 10: self->muladd_func_ptr = Chorus_postprocessing_ia; break; case 11: self->muladd_func_ptr = Chorus_postprocessing_aa; break; case 12: self->muladd_func_ptr = Chorus_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Chorus_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Chorus_postprocessing_areva; break; case 22: self->muladd_func_ptr = Chorus_postprocessing_revareva; break; } } static void Chorus_compute_next_data_frame(Chorus *self) { (*self->proc_func_ptr)(self); (*self->mix_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Chorus_traverse(Chorus *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->feedback); Py_VISIT(self->feedback_stream); Py_VISIT(self->depth); Py_VISIT(self->depth_stream); Py_VISIT(self->mix); Py_VISIT(self->mix_stream); return 0; } static int Chorus_clear(Chorus *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->feedback); Py_CLEAR(self->feedback_stream); Py_CLEAR(self->depth); Py_CLEAR(self->depth_stream); Py_CLEAR(self->mix); Py_CLEAR(self->mix_stream); return 0; } static void Chorus_dealloc(Chorus* self) { int i; pyo_DEALLOC for (i=0; i<8; i++) { free(self->buffer[i]); } Chorus_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Chorus_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; long j; MYFLT srfac; PyObject *inputtmp, *input_streamtmp, *depthtmp=NULL, *feedbacktmp=NULL, *mixtmp=NULL, *multmp=NULL, *addtmp=NULL; Chorus *self; self = (Chorus *)type->tp_alloc(type, 0); self->feedback = PyFloat_FromDouble(0.5); self->depth = PyFloat_FromDouble(1.0); self->mix = PyFloat_FromDouble(0.5); self->total_signal = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Chorus_compute_next_data_frame); self->mode_func_ptr = Chorus_setProcMode; srfac = self->sr / 44100.0; for (i=0; i<8; i++) { self->in_count[i] = 0; self->delays[i] = chorusParams[i][0] * srfac; self->delay_devs[i] = chorusParams[i][1] * srfac; self->inc[i] = chorusParams[i][2] * 512 / self->sr; } static char *kwlist[] = {"input", "depth", "feedback", "mix", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOO", kwlist, &inputtmp, &depthtmp, &feedbacktmp, &mixtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (depthtmp) { PyObject_CallMethod((PyObject *)self, "setDepth", "O", depthtmp); } if (feedbacktmp) { PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp); } if (mixtmp) { PyObject_CallMethod((PyObject *)self, "setMix", "O", mixtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); for (i=0; i<8; i++) { self->size[i] = (long)(chorusParams[i][0] * srfac * 2 + 0.5); self->buffer[i] = (MYFLT *)realloc(self->buffer[i], (self->size[i]+1) * sizeof(MYFLT)); for (j=0; j<(self->size[i]+1); j++) { self->buffer[i][j] = 0.; } } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Chorus_getServer(Chorus* self) { GET_SERVER }; static PyObject * Chorus_getStream(Chorus* self) { GET_STREAM }; static PyObject * Chorus_setMul(Chorus *self, PyObject *arg) { SET_MUL }; static PyObject * Chorus_setAdd(Chorus *self, PyObject *arg) { SET_ADD }; static PyObject * Chorus_setSub(Chorus *self, PyObject *arg) { SET_SUB }; static PyObject * Chorus_setDiv(Chorus *self, PyObject *arg) { SET_DIV }; static PyObject * Chorus_play(Chorus *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Chorus_out(Chorus *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Chorus_stop(Chorus *self) { STOP }; static PyObject * Chorus_multiply(Chorus *self, PyObject *arg) { MULTIPLY }; static PyObject * Chorus_inplace_multiply(Chorus *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Chorus_add(Chorus *self, PyObject *arg) { ADD }; static PyObject * Chorus_inplace_add(Chorus *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Chorus_sub(Chorus *self, PyObject *arg) { SUB }; static PyObject * Chorus_inplace_sub(Chorus *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Chorus_div(Chorus *self, PyObject *arg) { DIV }; static PyObject * Chorus_inplace_div(Chorus *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Chorus_setDepth(Chorus *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->depth); if (isNumber == 1) { self->depth = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->depth = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->depth, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->depth_stream); self->depth_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Chorus_setFeedback(Chorus *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->feedback); if (isNumber == 1) { self->feedback = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->feedback = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->feedback_stream); self->feedback_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Chorus_setMix(Chorus *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->mix); if (isNumber == 1) { self->mix = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->mix = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->mix, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->mix_stream); self->mix_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Chorus_members[] = { {"server", T_OBJECT_EX, offsetof(Chorus, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Chorus, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Chorus, input), 0, "Input sound object."}, {"feedback", T_OBJECT_EX, offsetof(Chorus, feedback), 0, "Feedback value."}, {"depth", T_OBJECT_EX, offsetof(Chorus, depth), 0, "Chorus depth."}, {"mix", T_OBJECT_EX, offsetof(Chorus, mix), 0, "Balance between dry and wet signals."}, {"mul", T_OBJECT_EX, offsetof(Chorus, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Chorus, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Chorus_methods[] = { {"getServer", (PyCFunction)Chorus_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Chorus_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Chorus_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Chorus_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Chorus_stop, METH_NOARGS, "Stops computing."}, {"setFeedback", (PyCFunction)Chorus_setFeedback, METH_O, "Sets feedback value between 0 -> 1."}, {"setDepth", (PyCFunction)Chorus_setDepth, METH_O, "Sets chorus depth."}, {"setMix", (PyCFunction)Chorus_setMix, METH_O, "Sets balance between dry and wet signals."}, {"setMul", (PyCFunction)Chorus_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Chorus_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Chorus_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Chorus_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Chorus_as_number = { (binaryfunc)Chorus_add, /*nb_add*/ (binaryfunc)Chorus_sub, /*nb_subtract*/ (binaryfunc)Chorus_multiply, /*nb_multiply*/ (binaryfunc)Chorus_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Chorus_inplace_add, /*inplace_add*/ (binaryfunc)Chorus_inplace_sub, /*inplace_subtract*/ (binaryfunc)Chorus_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Chorus_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ChorusType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Chorus_base", /*tp_name*/ sizeof(Chorus), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Chorus_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Chorus_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Chorus objects. 8 delay lines chorus.", /* tp_doc */ (traverseproc)Chorus_traverse, /* tp_traverse */ (inquiry)Chorus_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Chorus_methods, /* tp_methods */ Chorus_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Chorus_new, /* tp_new */ };pyo/src/objects/wgverbmodule.c0000644000175000017500000021651512652732202015756 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #define NUM_REFS 13 static const MYFLT randomScaling = 0.5; static const MYFLT reverbParams[8][4] = { { 2473.0, 0.0010, 3.100, 2503.0 }, { 2767.0, 0.0011, 3.500, 2749.0 }, { 3217.0, 0.0017, 1.110, 3187.0 }, { 3557.0, 0.0006, 3.973, 3583.0 }, { 3907.0, 0.0010, 2.341, 3929.0 }, { 4127.0, 0.0011, 1.897, 4093.0 }, { 2143.0, 0.0017, 0.891, 2131.0 }, { 1933.0, 0.0006, 3.221, 1951.0 }}; static const MYFLT first_ref_delays[NUM_REFS] = {283, 467, 587, 677, 757, 911, 1117, 1223, 1307, 1429, 1553, 1613, 1783}; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *feedback; Stream *feedback_stream; PyObject *cutoff; Stream *cutoff_stream; PyObject *mix; Stream *mix_stream; void (*mix_func_ptr)(); int modebuffer[5]; MYFLT total_signal; MYFLT delays[8]; long size[8]; int in_count[8]; MYFLT *buffer[8]; // lowpass MYFLT damp; MYFLT lastFreq; // sample memories MYFLT lastSamples[8]; // jitters MYFLT rnd[8]; MYFLT rnd_value[8]; MYFLT rnd_oldValue[8]; MYFLT rnd_diff[8]; MYFLT rnd_time[8]; MYFLT rnd_timeInc[8]; MYFLT rnd_range[8]; MYFLT rnd_halfRange[8]; } WGVerb; static void WGVerb_process_ii(WGVerb *self) { MYFLT val, x, x1, xind, frac, junction, inval, filt; int i, j, ind; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT feed = PyFloat_AS_DOUBLE(self->feedback); MYFLT freq = PyFloat_AS_DOUBLE(self->cutoff); if (feed < 0) feed = 0; else if (feed > 1) feed = 1; if (freq != self->lastFreq) { self->lastFreq = freq; self->damp = 2.0 - MYCOS(TWOPI * freq / self->sr); self->damp = (self->damp - MYSQRT(self->damp * self->damp - 1.0)); } for (i=0; ibufsize; i++) { inval = in[i]; junction = self->total_signal * .25; self->total_signal = 0.0; for (j=0; j<8; j++) { self->rnd_time[j] += self->rnd_timeInc[j]; if (self->rnd_time[j] < 0.0) self->rnd_time[j] += 1.0; else if (self->rnd_time[j] >= 1.0) { self->rnd_time[j] -= 1.0; self->rnd_oldValue[j] = self->rnd_value[j]; self->rnd_value[j] = self->rnd_range[j] * (rand()/((MYFLT)(RAND_MAX)+1)) - self->rnd_halfRange[j]; self->rnd_diff[j] = self->rnd_value[j] - self->rnd_oldValue[j]; } self->rnd[j] = self->rnd_oldValue[j] + self->rnd_diff[j] * self->rnd_time[j]; xind = self->in_count[j] - (self->delays[j] + self->rnd[j]); if (xind < 0) xind += self->size[j]; ind = (int)xind; frac = xind - ind; x = self->buffer[j][ind]; x1 = self->buffer[j][ind+1]; val = x + (x1 - x) * frac; val *= feed; filt = (self->lastSamples[j] - val) * self->damp + val; self->total_signal += filt; self->buffer[j][self->in_count[j]] = inval + junction - self->lastSamples[j]; self->lastSamples[j] = filt; if(self->in_count[j] == 0) self->buffer[j][self->size[j]] = self->buffer[j][0]; self->in_count[j]++; if (self->in_count[j] >= self->size[j]) self->in_count[j] = 0; } self->data[i] = self->total_signal * 0.25; } } static void WGVerb_process_ai(WGVerb *self) { MYFLT val, x, x1, xind, frac, junction, inval, filt, feed; int i, j, ind; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *feedback = Stream_getData((Stream *)self->feedback_stream); MYFLT freq = PyFloat_AS_DOUBLE(self->cutoff); if (freq != self->lastFreq) { self->lastFreq = freq; self->damp = 2.0 - MYCOS(TWOPI * freq / self->sr); self->damp = (self->damp - MYSQRT(self->damp * self->damp - 1.0)); } for (i=0; ibufsize; i++) { inval = in[i]; feed = feedback[i]; if (feed < 0) feed = 0; else if (feed > 1) feed = 1; junction = self->total_signal * .25; self->total_signal = 0.0; for (j=0; j<8; j++) { self->rnd_time[j] += self->rnd_timeInc[j]; if (self->rnd_time[j] < 0.0) self->rnd_time[j] += 1.0; else if (self->rnd_time[j] >= 1.0) { self->rnd_time[j] -= 1.0; self->rnd_oldValue[j] = self->rnd_value[j]; self->rnd_value[j] = self->rnd_range[j] * (rand()/((MYFLT)(RAND_MAX)+1)) - self->rnd_halfRange[j]; self->rnd_diff[j] = self->rnd_value[j] - self->rnd_oldValue[j]; } self->rnd[j] = self->rnd_oldValue[j] + self->rnd_diff[j] * self->rnd_time[j]; xind = self->in_count[j] - (self->delays[j] + self->rnd[j]); if (xind < 0) xind += self->size[j]; ind = (int)xind; frac = xind - ind; x = self->buffer[j][ind]; x1 = self->buffer[j][ind+1]; val = x + (x1 - x) * frac; val *= feed; filt = (self->lastSamples[j] - val) * self->damp + val; self->total_signal += filt; self->buffer[j][self->in_count[j]] = inval + junction - self->lastSamples[j]; self->lastSamples[j] = filt; if(self->in_count[j] == 0) self->buffer[j][self->size[j]] = self->buffer[j][0]; self->in_count[j]++; if (self->in_count[j] >= self->size[j]) self->in_count[j] = 0; } self->data[i] = self->total_signal * 0.25; } } static void WGVerb_process_ia(WGVerb *self) { MYFLT val, x, x1, xind, frac, junction, inval, filt, freq; int i, j, ind; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT feed = PyFloat_AS_DOUBLE(self->feedback); MYFLT *cutoff = Stream_getData((Stream *)self->cutoff_stream); if (feed < 0) feed = 0; else if (feed > 1) feed = 1; for (i=0; ibufsize; i++) { inval = in[i]; freq = cutoff[i]; if (freq != self->lastFreq) { self->lastFreq = freq; self->damp = 2.0 - MYCOS(TWOPI * freq / self->sr); self->damp = (self->damp - MYSQRT(self->damp * self->damp - 1.0)); } junction = self->total_signal * .25; self->total_signal = 0.0; for (j=0; j<8; j++) { self->rnd_time[j] += self->rnd_timeInc[j]; if (self->rnd_time[j] < 0.0) self->rnd_time[j] += 1.0; else if (self->rnd_time[j] >= 1.0) { self->rnd_time[j] -= 1.0; self->rnd_oldValue[j] = self->rnd_value[j]; self->rnd_value[j] = self->rnd_range[j] * (rand()/((MYFLT)(RAND_MAX)+1)) - self->rnd_halfRange[j]; self->rnd_diff[j] = self->rnd_value[j] - self->rnd_oldValue[j]; } self->rnd[j] = self->rnd_oldValue[j] + self->rnd_diff[j] * self->rnd_time[j]; xind = self->in_count[j] - (self->delays[j] + self->rnd[j]); if (xind < 0) xind += self->size[j]; ind = (int)xind; frac = xind - ind; x = self->buffer[j][ind]; x1 = self->buffer[j][ind+1]; val = x + (x1 - x) * frac; val *= feed; filt = (self->lastSamples[j] - val) * self->damp + val; self->total_signal += filt; self->buffer[j][self->in_count[j]] = inval + junction - self->lastSamples[j]; self->lastSamples[j] = filt; if(self->in_count[j] == 0) self->buffer[j][self->size[j]] = self->buffer[j][0]; self->in_count[j]++; if (self->in_count[j] >= self->size[j]) self->in_count[j] = 0; } self->data[i] = self->total_signal * 0.25; } } static void WGVerb_process_aa(WGVerb *self) { MYFLT val, x, x1, xind, frac, junction, inval, filt, feed, freq; int i, j, ind; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *feedback = Stream_getData((Stream *)self->feedback_stream); MYFLT *cutoff = Stream_getData((Stream *)self->cutoff_stream); for (i=0; ibufsize; i++) { inval = in[i]; feed = feedback[i]; freq = cutoff[i]; if (feed < 0) feed = 0; else if (feed > 1) feed = 1; if (freq != self->lastFreq) { self->lastFreq = freq; self->damp = 2.0 - MYCOS(TWOPI * freq / self->sr); self->damp = (self->damp - MYSQRT(self->damp * self->damp - 1.0)); } junction = self->total_signal * .25; self->total_signal = 0.0; for (j=0; j<8; j++) { self->rnd_time[j] += self->rnd_timeInc[j]; if (self->rnd_time[j] < 0.0) self->rnd_time[j] += 1.0; else if (self->rnd_time[j] >= 1.0) { self->rnd_time[j] -= 1.0; self->rnd_oldValue[j] = self->rnd_value[j]; self->rnd_value[j] = self->rnd_range[j] * (rand()/((MYFLT)(RAND_MAX)+1)) - self->rnd_halfRange[j]; self->rnd_diff[j] = self->rnd_value[j] - self->rnd_oldValue[j]; } self->rnd[j] = self->rnd_oldValue[j] + self->rnd_diff[j] * self->rnd_time[j]; xind = self->in_count[j] - (self->delays[j] + self->rnd[j]); if (xind < 0) xind += self->size[j]; ind = (int)xind; frac = xind - ind; x = self->buffer[j][ind]; x1 = self->buffer[j][ind+1]; val = x + (x1 - x) * frac; val *= feed; filt = (self->lastSamples[j] - val) * self->damp + val; self->total_signal += filt; self->buffer[j][self->in_count[j]] = inval + junction - self->lastSamples[j]; self->lastSamples[j] = filt; if(self->in_count[j] == 0) self->buffer[j][self->size[j]] = self->buffer[j][0]; self->in_count[j]++; if (self->in_count[j] >= self->size[j]) self->in_count[j] = 0; } self->data[i] = self->total_signal * 0.25; } } static void WGVerb_mix_i(WGVerb *self) { int i; MYFLT val; MYFLT mix = PyFloat_AS_DOUBLE(self->mix); MYFLT *in = Stream_getData((Stream *)self->input_stream); if (mix < 0.0) mix = 0.0; else if (mix > 1.0) mix = 1.0; for (i=0; ibufsize; i++) { val = in[i] * (1.0 - mix) + self->data[i] * mix; self->data[i] = val; } } static void WGVerb_mix_a(WGVerb *self) { int i; MYFLT mix, val; MYFLT *mi = Stream_getData((Stream *)self->mix_stream); MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { mix = mi[i]; if (mix < 0.0) mix = 0.0; else if (mix > 1.0) mix = 1.0; val = in[i] * (1.0 - mix) + self->data[i] * mix; self->data[i] = val; } } static void WGVerb_postprocessing_ii(WGVerb *self) { POST_PROCESSING_II }; static void WGVerb_postprocessing_ai(WGVerb *self) { POST_PROCESSING_AI }; static void WGVerb_postprocessing_ia(WGVerb *self) { POST_PROCESSING_IA }; static void WGVerb_postprocessing_aa(WGVerb *self) { POST_PROCESSING_AA }; static void WGVerb_postprocessing_ireva(WGVerb *self) { POST_PROCESSING_IREVA }; static void WGVerb_postprocessing_areva(WGVerb *self) { POST_PROCESSING_AREVA }; static void WGVerb_postprocessing_revai(WGVerb *self) { POST_PROCESSING_REVAI }; static void WGVerb_postprocessing_revaa(WGVerb *self) { POST_PROCESSING_REVAA }; static void WGVerb_postprocessing_revareva(WGVerb *self) { POST_PROCESSING_REVAREVA }; static void WGVerb_setProcMode(WGVerb *self) { int procmode, muladdmode, mixmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; mixmode = self->modebuffer[4]; switch (procmode) { case 0: self->proc_func_ptr = WGVerb_process_ii; break; case 1: self->proc_func_ptr = WGVerb_process_ai; break; case 10: self->proc_func_ptr = WGVerb_process_ia; break; case 11: self->proc_func_ptr = WGVerb_process_aa; break; } switch (mixmode) { case 0: self->mix_func_ptr = WGVerb_mix_i; break; case 1: self->mix_func_ptr = WGVerb_mix_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = WGVerb_postprocessing_ii; break; case 1: self->muladd_func_ptr = WGVerb_postprocessing_ai; break; case 2: self->muladd_func_ptr = WGVerb_postprocessing_revai; break; case 10: self->muladd_func_ptr = WGVerb_postprocessing_ia; break; case 11: self->muladd_func_ptr = WGVerb_postprocessing_aa; break; case 12: self->muladd_func_ptr = WGVerb_postprocessing_revaa; break; case 20: self->muladd_func_ptr = WGVerb_postprocessing_ireva; break; case 21: self->muladd_func_ptr = WGVerb_postprocessing_areva; break; case 22: self->muladd_func_ptr = WGVerb_postprocessing_revareva; break; } } static void WGVerb_compute_next_data_frame(WGVerb *self) { (*self->proc_func_ptr)(self); (*self->mix_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int WGVerb_traverse(WGVerb *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->feedback); Py_VISIT(self->feedback_stream); Py_VISIT(self->cutoff); Py_VISIT(self->cutoff_stream); Py_VISIT(self->mix); Py_VISIT(self->mix_stream); return 0; } static int WGVerb_clear(WGVerb *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->feedback); Py_CLEAR(self->feedback_stream); Py_CLEAR(self->cutoff); Py_CLEAR(self->cutoff_stream); Py_CLEAR(self->mix); Py_CLEAR(self->mix_stream); return 0; } static void WGVerb_dealloc(WGVerb* self) { int i; pyo_DEALLOC for (i=0; i<8; i++) { free(self->buffer[i]); } WGVerb_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * WGVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, j; PyObject *inputtmp, *input_streamtmp, *feedbacktmp=NULL, *cutofftmp=NULL, *mixtmp=NULL, *multmp=NULL, *addtmp=NULL; WGVerb *self; self = (WGVerb *)type->tp_alloc(type, 0); self->feedback = PyFloat_FromDouble(0.5); self->cutoff = PyFloat_FromDouble(5000.0); self->mix = PyFloat_FromDouble(0.5); self->lastFreq = self->damp = 0.0; self->total_signal = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, WGVerb_compute_next_data_frame); self->mode_func_ptr = WGVerb_setProcMode; for (i=0; i<8; i++) { self->in_count[i] = 0; self->lastSamples[i] = 0.0; self->rnd[i] = self->rnd_value[i] = self->rnd_oldValue[i] = self->rnd_diff[i] = 0.0; self->rnd_time[i] = 1.0; self->rnd_timeInc[i] = reverbParams[i][2] * randomScaling / self->sr; self->rnd_range[i] = reverbParams[i][1] * randomScaling * self->sr; self->rnd_halfRange[i] = self->rnd_range[i] * 0.5; self->delays[i] = reverbParams[i][0] * (self->sr / 44100.0); } static char *kwlist[] = {"input", "feedback", "cutoff", "mix", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOO", kwlist, &inputtmp, &feedbacktmp, &cutofftmp, &mixtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (feedbacktmp) { PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp); } if (cutofftmp) { PyObject_CallMethod((PyObject *)self, "setCutoff", "O", cutofftmp); } if (mixtmp) { PyObject_CallMethod((PyObject *)self, "setMix", "O", mixtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); for (i=0; i<8; i++) { self->size[i] = reverbParams[i][0] * (self->sr / 44100.0) + (int)(reverbParams[i][1] * self->sr + 0.5); self->buffer[i] = (MYFLT *)realloc(self->buffer[i], (self->size[i]+1) * sizeof(MYFLT)); for (j=0; j<(self->size[i]+1); j++) { self->buffer[i][j] = 0.; } } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * WGVerb_getServer(WGVerb* self) { GET_SERVER }; static PyObject * WGVerb_getStream(WGVerb* self) { GET_STREAM }; static PyObject * WGVerb_setMul(WGVerb *self, PyObject *arg) { SET_MUL }; static PyObject * WGVerb_setAdd(WGVerb *self, PyObject *arg) { SET_ADD }; static PyObject * WGVerb_setSub(WGVerb *self, PyObject *arg) { SET_SUB }; static PyObject * WGVerb_setDiv(WGVerb *self, PyObject *arg) { SET_DIV }; static PyObject * WGVerb_play(WGVerb *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * WGVerb_out(WGVerb *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * WGVerb_stop(WGVerb *self) { STOP }; static PyObject * WGVerb_multiply(WGVerb *self, PyObject *arg) { MULTIPLY }; static PyObject * WGVerb_inplace_multiply(WGVerb *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * WGVerb_add(WGVerb *self, PyObject *arg) { ADD }; static PyObject * WGVerb_inplace_add(WGVerb *self, PyObject *arg) { INPLACE_ADD }; static PyObject * WGVerb_sub(WGVerb *self, PyObject *arg) { SUB }; static PyObject * WGVerb_inplace_sub(WGVerb *self, PyObject *arg) { INPLACE_SUB }; static PyObject * WGVerb_div(WGVerb *self, PyObject *arg) { DIV }; static PyObject * WGVerb_inplace_div(WGVerb *self, PyObject *arg) { INPLACE_DIV }; static PyObject * WGVerb_setFeedback(WGVerb *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->feedback); if (isNumber == 1) { self->feedback = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->feedback = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->feedback_stream); self->feedback_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * WGVerb_setCutoff(WGVerb *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->cutoff); if (isNumber == 1) { self->cutoff = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->cutoff = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->cutoff, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->cutoff_stream); self->cutoff_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * WGVerb_setMix(WGVerb *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->mix); if (isNumber == 1) { self->mix = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->mix = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->mix, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->mix_stream); self->mix_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef WGVerb_members[] = { {"server", T_OBJECT_EX, offsetof(WGVerb, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(WGVerb, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(WGVerb, input), 0, "Input sound object."}, {"feedback", T_OBJECT_EX, offsetof(WGVerb, feedback), 0, "Feedback value."}, {"cutoff", T_OBJECT_EX, offsetof(WGVerb, cutoff), 0, "WGVerb lowpass filter cutoff."}, {"mix", T_OBJECT_EX, offsetof(WGVerb, mix), 0, "Balance between dry and wet signals."}, {"mul", T_OBJECT_EX, offsetof(WGVerb, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(WGVerb, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef WGVerb_methods[] = { {"getServer", (PyCFunction)WGVerb_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)WGVerb_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)WGVerb_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)WGVerb_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)WGVerb_stop, METH_NOARGS, "Stops computing."}, {"setFeedback", (PyCFunction)WGVerb_setFeedback, METH_O, "Sets feedback value between 0 -> 1."}, {"setCutoff", (PyCFunction)WGVerb_setCutoff, METH_O, "Sets lowpass filter cutoff."}, {"setMix", (PyCFunction)WGVerb_setMix, METH_O, "Sets balance between dry and wet signals."}, {"setMul", (PyCFunction)WGVerb_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)WGVerb_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)WGVerb_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)WGVerb_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods WGVerb_as_number = { (binaryfunc)WGVerb_add, /*nb_add*/ (binaryfunc)WGVerb_sub, /*nb_subtract*/ (binaryfunc)WGVerb_multiply, /*nb_multiply*/ (binaryfunc)WGVerb_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)WGVerb_inplace_add, /*inplace_add*/ (binaryfunc)WGVerb_inplace_sub, /*inplace_subtract*/ (binaryfunc)WGVerb_inplace_multiply, /*inplace_multiply*/ (binaryfunc)WGVerb_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject WGVerbType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.WGVerb_base", /*tp_name*/ sizeof(WGVerb), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)WGVerb_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &WGVerb_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "WGVerb objects. Waveguide-based reverberation network.", /* tp_doc */ (traverseproc)WGVerb_traverse, /* tp_traverse */ (inquiry)WGVerb_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ WGVerb_methods, /* tp_methods */ WGVerb_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ WGVerb_new, /* tp_new */ }; /***************/ /**** STRev ****/ /***************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *inpos; Stream *inpos_stream; PyObject *revtime; Stream *revtime_stream; PyObject *cutoff; Stream *cutoff_stream; PyObject *mix; Stream *mix_stream; void (*mix_func_ptr)(); int modebuffer[4]; MYFLT firstRefGain; MYFLT total_signal[2]; MYFLT delays[2][8]; long size[2][8]; int in_count[2][8]; MYFLT *buffer[2][8]; MYFLT *ref_buffer[NUM_REFS]; int ref_size[NUM_REFS]; int ref_in_count[NUM_REFS]; MYFLT avg_time; MYFLT srfac; // lowpass MYFLT damp[2]; MYFLT lastFreq; MYFLT nyquist; MYFLT lastInpos; // sample memories MYFLT lastSamples[2][8]; // jitters MYFLT rnd[2][8]; MYFLT rnd_value[2][8]; MYFLT rnd_oldValue[2][8]; MYFLT rnd_diff[2][8]; MYFLT rnd_time[2][8]; MYFLT rnd_timeInc[2][8]; MYFLT rnd_range[2][8]; MYFLT rnd_halfRange[2][8]; MYFLT *buffer_streams; MYFLT *input_buffer[2]; } STReverb; static void STReverb_process_ii(STReverb *self) { int i, j, k, k2, ind, half; MYFLT val, x, x1, xind, frac, junction, inval, filt, amp1, amp2, b, f, sum_ref, feed, step, invp; MYFLT ref_amp_l[NUM_REFS]; MYFLT ref_amp_r[NUM_REFS]; MYFLT ref_buf[2]; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT inpos = PyFloat_AS_DOUBLE(self->inpos); if (self->modebuffer[1] == 0) feed = PyFloat_AS_DOUBLE(self->revtime); else feed = Stream_getData((Stream *)self->revtime_stream)[0]; MYFLT freq = PyFloat_AS_DOUBLE(self->cutoff); if (inpos < 0.0) inpos = 0.0; else if (inpos > 1.0) inpos = 1.0; if (feed < 0.01) feed = 0.01; feed = MYPOW(100.0, -self->avg_time/feed); if (freq < 20.0) freq = 20.0; else if (freq > self->nyquist) freq = self->nyquist; if (freq != self->lastFreq || inpos != self->lastInpos) { self->lastFreq = freq; self->lastInpos = inpos; f = ((1.0 - inpos) * 0.3 + 0.7) * freq; b = 2.0 - MYCOS(TWOPI * f / self->sr); self->damp[0] = (b - MYSQRT(b * b - 1.0)); f = (inpos * 0.3 + 0.7) * freq; b = 2.0 - MYCOS(TWOPI * f / self->sr); self->damp[1] = (b - MYSQRT(b * b - 1.0)); } /* position of the source and first reflexions */ amp1 = 1.0 - inpos; amp2 = inpos; half = (NUM_REFS - 1) / 2; if (inpos <= 0.5) { step = (0.5 - inpos) / half; ref_amp_l[half] = ref_amp_r[half] = 0.5; for (k=0; kbufsize; i++) { self->input_buffer[0][i] = in[i] * amp1; self->input_buffer[1][i] = in[i] * amp2; ref_buf[0] = ref_buf[1] = 0.0; for (k=0; kref_buffer[k][self->ref_in_count[k]]; self->ref_buffer[k][self->ref_in_count[k]] = in[i]; self->ref_in_count[k]++; if (self->ref_in_count[k] == self->ref_size[k]) self->ref_in_count[k] = 0; ref_buf[0] += sum_ref * ref_amp_l[k]; ref_buf[1] += sum_ref * ref_amp_r[k]; } for (k=0; k<2; k++) { inval = self->input_buffer[k][i] * 0.8 + self->input_buffer[1-k][i] * 0.2 + ref_buf[k] * 0.1; junction = self->total_signal[k] * .25; self->total_signal[k] = ref_buf[k] * self->firstRefGain; for (j=0; j<8; j++) { self->rnd_time[k][j] += self->rnd_timeInc[k][j]; if (self->rnd_time[k][j] < 0.0) self->rnd_time[k][j] += 1.0; else if (self->rnd_time[k][j] >= 1.0) { self->rnd_time[k][j] -= 1.0; self->rnd_oldValue[k][j] = self->rnd_value[k][j]; self->rnd_value[k][j] = self->rnd_range[k][j] * (rand()/((MYFLT)(RAND_MAX)+1)) - self->rnd_halfRange[k][j]; self->rnd_diff[k][j] = self->rnd_value[k][j] - self->rnd_oldValue[k][j]; } self->rnd[k][j] = self->rnd_oldValue[k][j] + self->rnd_diff[k][j] * self->rnd_time[k][j]; xind = self->in_count[k][j] - (self->delays[k][j] + self->rnd[k][j]); if (xind < 0) xind += self->size[k][j]; ind = (int)xind; frac = xind - ind; x = self->buffer[k][j][ind]; x1 = self->buffer[k][j][ind+1]; val = x + (x1 - x) * frac; val *= feed; filt = val + (self->lastSamples[k][j] - val) * self->damp[k]; self->total_signal[k] += filt; self->buffer[k][j][self->in_count[k][j]] = inval + junction - self->lastSamples[k][j]; self->lastSamples[k][j] = filt; if(self->in_count[k][j] == 0) self->buffer[k][j][self->size[k][j]] = self->buffer[k][j][0]; self->in_count[k][j]++; if (self->in_count[k][j] >= self->size[k][j]) self->in_count[k][j] = 0; } self->buffer_streams[i+k*self->bufsize] = self->total_signal[k] * 0.25; } } } static void STReverb_process_ai(STReverb *self) { MYFLT val, x, x1, xind, frac, junction, inval, filt, amp1, amp2, b, f, sum_ref, inpos, feed, step, invp; MYFLT ref_amp_l[NUM_REFS]; MYFLT ref_amp_r[NUM_REFS]; MYFLT ref_buf[2]; int i, j, k, k2, ind, half; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *pos = Stream_getData((Stream *)self->inpos_stream); if (self->modebuffer[1] == 0) feed = PyFloat_AS_DOUBLE(self->revtime); else feed = Stream_getData((Stream *)self->revtime_stream)[0]; MYFLT freq = PyFloat_AS_DOUBLE(self->cutoff); if (feed < 0.01) feed = 0.01; feed = MYPOW(100.0, -self->avg_time/feed); if (freq < 20.0) freq = 20.0; else if (freq > self->nyquist) freq = self->nyquist; for (i=0; ibufsize; i++) { inpos = pos[i]; if (inpos < 0.0) inpos = 0.0; else if (inpos > 1.0) inpos = 1.0; if (freq != self->lastFreq || inpos != self->lastInpos) { self->lastFreq = freq; self->lastInpos = inpos; f = ((1.0 - inpos) * 0.3 + 0.7) * freq; b = 2.0 - MYCOS(TWOPI * f / self->sr); self->damp[0] = (b - MYSQRT(b * b - 1.0)); f = (inpos * 0.3 + 0.7) * freq; b = 2.0 - MYCOS(TWOPI * f / self->sr); self->damp[1] = (b - MYSQRT(b * b - 1.0)); } /* position of the source and first reflexions */ amp1 = 1.0 - inpos; amp2 = inpos; half = (NUM_REFS - 1) / 2; if (inpos <= 0.5) { step = (0.5 - inpos) / half; ref_amp_l[half] = ref_amp_r[half] = 0.5; for (k=0; kinput_buffer[0][i] = in[i] * amp1; self->input_buffer[1][i] = in[i] * amp2; ref_buf[0] = ref_buf[1] = 0.0; for (k=0; kref_buffer[k][self->ref_in_count[k]]; self->ref_buffer[k][self->ref_in_count[k]] = in[i]; self->ref_in_count[k]++; if (self->ref_in_count[k] == self->ref_size[k]) self->ref_in_count[k] = 0; ref_buf[0] += sum_ref * ref_amp_l[k]; ref_buf[1] += sum_ref * ref_amp_r[k]; } for (k=0; k<2; k++) { inval = self->input_buffer[k][i] * 0.8 + self->input_buffer[1-k][i] * 0.2 + ref_buf[k] * 0.1; junction = self->total_signal[k] * .25; self->total_signal[k] = ref_buf[k] * self->firstRefGain; for (j=0; j<8; j++) { self->rnd_time[k][j] += self->rnd_timeInc[k][j]; if (self->rnd_time[k][j] < 0.0) self->rnd_time[k][j] += 1.0; else if (self->rnd_time[k][j] >= 1.0) { self->rnd_time[k][j] -= 1.0; self->rnd_oldValue[k][j] = self->rnd_value[k][j]; self->rnd_value[k][j] = self->rnd_range[k][j] * (rand()/((MYFLT)(RAND_MAX)+1)) - self->rnd_halfRange[k][j]; self->rnd_diff[k][j] = self->rnd_value[k][j] - self->rnd_oldValue[k][j]; } self->rnd[k][j] = self->rnd_oldValue[k][j] + self->rnd_diff[k][j] * self->rnd_time[k][j]; xind = self->in_count[k][j] - (self->delays[k][j] + self->rnd[k][j]); if (xind < 0) xind += self->size[k][j]; ind = (int)xind; frac = xind - ind; x = self->buffer[k][j][ind]; x1 = self->buffer[k][j][ind+1]; val = x + (x1 - x) * frac; val *= feed; filt = val + (self->lastSamples[k][j] - val) * self->damp[k]; self->total_signal[k] += filt; self->buffer[k][j][self->in_count[k][j]] = inval + junction - self->lastSamples[k][j]; self->lastSamples[k][j] = filt; if(self->in_count[k][j] == 0) self->buffer[k][j][self->size[k][j]] = self->buffer[k][j][0]; self->in_count[k][j]++; if (self->in_count[k][j] >= self->size[k][j]) self->in_count[k][j] = 0; } self->buffer_streams[i+k*self->bufsize] = self->total_signal[k] * 0.25; } } } static void STReverb_process_ia(STReverb *self) { MYFLT val, x, x1, xind, frac, junction, inval, filt, amp1, amp2, b, f, sum_ref, feed, freq, step, invp; MYFLT ref_amp_l[NUM_REFS]; MYFLT ref_amp_r[NUM_REFS]; MYFLT ref_buf[2]; int i, j, k, k2, ind, half; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT inpos = PyFloat_AS_DOUBLE(self->inpos); if (self->modebuffer[1] == 0) feed = PyFloat_AS_DOUBLE(self->revtime); else feed = Stream_getData((Stream *)self->revtime_stream)[0]; MYFLT *fr = Stream_getData((Stream *)self->cutoff_stream); if (inpos < 0.0) inpos = 0.0; else if (inpos > 1.0) inpos = 1.0; if (feed < 0.01) feed = 0.01; feed = MYPOW(100.0, -self->avg_time/feed); /* position of the source and first reflexions */ amp1 = 1.0 - inpos; amp2 = inpos; half = (NUM_REFS - 1) / 2; if (inpos <= 0.5) { step = (0.5 - inpos) / half; ref_amp_l[half] = ref_amp_r[half] = 0.5; for (k=0; kbufsize; i++) { freq = fr[i]; if (freq < 20.0) freq = 20.0; else if (freq > self->nyquist) freq = self->nyquist; if (freq != self->lastFreq || inpos != self->lastInpos) { self->lastFreq = freq; self->lastInpos = inpos; f = ((1.0 - inpos) * 0.3 + 0.7) * freq; b = 2.0 - MYCOS(TWOPI * f / self->sr); self->damp[0] = (b - MYSQRT(b * b - 1.0)); f = (inpos * 0.3 + 0.7) * freq; b = 2.0 - MYCOS(TWOPI * f / self->sr); self->damp[1] = (b - MYSQRT(b * b - 1.0)); } self->input_buffer[0][i] = in[i] * amp1; self->input_buffer[1][i] = in[i] * amp2; ref_buf[0] = ref_buf[1] = 0.0; for (k=0; kref_buffer[k][self->ref_in_count[k]]; self->ref_buffer[k][self->ref_in_count[k]] = in[i]; self->ref_in_count[k]++; if (self->ref_in_count[k] == self->ref_size[k]) self->ref_in_count[k] = 0; ref_buf[0] += sum_ref * ref_amp_l[k]; ref_buf[1] += sum_ref * ref_amp_r[k]; } for (k=0; k<2; k++) { inval = self->input_buffer[k][i] * 0.8 + self->input_buffer[1-k][i] * 0.2 + ref_buf[k] * 0.1; junction = self->total_signal[k] * .25; self->total_signal[k] = ref_buf[k] * self->firstRefGain; for (j=0; j<8; j++) { self->rnd_time[k][j] += self->rnd_timeInc[k][j]; if (self->rnd_time[k][j] < 0.0) self->rnd_time[k][j] += 1.0; else if (self->rnd_time[k][j] >= 1.0) { self->rnd_time[k][j] -= 1.0; self->rnd_oldValue[k][j] = self->rnd_value[k][j]; self->rnd_value[k][j] = self->rnd_range[k][j] * (rand()/((MYFLT)(RAND_MAX)+1)) - self->rnd_halfRange[k][j]; self->rnd_diff[k][j] = self->rnd_value[k][j] - self->rnd_oldValue[k][j]; } self->rnd[k][j] = self->rnd_oldValue[k][j] + self->rnd_diff[k][j] * self->rnd_time[k][j]; xind = self->in_count[k][j] - (self->delays[k][j] + self->rnd[k][j]); if (xind < 0) xind += self->size[k][j]; ind = (int)xind; frac = xind - ind; x = self->buffer[k][j][ind]; x1 = self->buffer[k][j][ind+1]; val = x + (x1 - x) * frac; val *= feed; filt = val + (self->lastSamples[k][j] - val) * self->damp[k]; self->total_signal[k] += filt; self->buffer[k][j][self->in_count[k][j]] = inval + junction - self->lastSamples[k][j]; self->lastSamples[k][j] = filt; if(self->in_count[k][j] == 0) self->buffer[k][j][self->size[k][j]] = self->buffer[k][j][0]; self->in_count[k][j]++; if (self->in_count[k][j] >= self->size[k][j]) self->in_count[k][j] = 0; } self->buffer_streams[i+k*self->bufsize] = self->total_signal[k] * 0.25; } } } static void STReverb_process_aa(STReverb *self) { MYFLT val, x, x1, xind, frac, junction, inval, filt, amp1, amp2, b, f, sum_ref, inpos, feed, freq, step, invp; MYFLT ref_amp_l[NUM_REFS]; MYFLT ref_amp_r[NUM_REFS]; MYFLT ref_buf[2]; int i, j, k, k2, ind, half; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *pos = Stream_getData((Stream *)self->inpos_stream); if (self->modebuffer[1] == 0) feed = PyFloat_AS_DOUBLE(self->revtime); else feed = Stream_getData((Stream *)self->revtime_stream)[0]; MYFLT *fr = Stream_getData((Stream *)self->cutoff_stream); if (feed < 0.01) feed = 0.01; feed = MYPOW(100.0, -self->avg_time/feed); for (i=0; ibufsize; i++) { inpos = pos[i]; freq = fr[i]; if (inpos < 0.0) inpos = 0.0; else if (inpos > 1.0) inpos = 1.0; if (freq < 20.0) freq = 20.0; else if (freq > self->nyquist) freq = self->nyquist; if (freq != self->lastFreq || inpos != self->lastInpos) { self->lastFreq = freq; self->lastInpos = inpos; f = ((1.0 - inpos) * 0.3 + 0.7) * freq; b = 2.0 - MYCOS(TWOPI * f / self->sr); self->damp[0] = (b - MYSQRT(b * b - 1.0)); f = (inpos * 0.3 + 0.7) * freq; b = 2.0 - MYCOS(TWOPI * f / self->sr); self->damp[1] = (b - MYSQRT(b * b - 1.0)); } /* position of the source and first reflexions */ amp1 = 1.0 - inpos; amp2 = inpos; half = (NUM_REFS - 1) / 2; if (inpos <= 0.5) { step = (0.5 - inpos) / half; ref_amp_l[half] = ref_amp_r[half] = 0.5; for (k=0; kinput_buffer[0][i] = in[i] * amp1; self->input_buffer[1][i] = in[i] * amp2; ref_buf[0] = ref_buf[1] = 0.0; for (k=0; kref_buffer[k][self->ref_in_count[k]]; self->ref_buffer[k][self->ref_in_count[k]] = in[i]; self->ref_in_count[k]++; if (self->ref_in_count[k] == self->ref_size[k]) self->ref_in_count[k] = 0; ref_buf[0] += sum_ref * ref_amp_l[k]; ref_buf[1] += sum_ref * ref_amp_r[k]; } for (k=0; k<2; k++) { inval = self->input_buffer[k][i] * 0.8 + self->input_buffer[1-k][i] * 0.2 + ref_buf[k] * 0.1; junction = self->total_signal[k] * .25; self->total_signal[k] = ref_buf[k] * self->firstRefGain; for (j=0; j<8; j++) { self->rnd_time[k][j] += self->rnd_timeInc[k][j]; if (self->rnd_time[k][j] < 0.0) self->rnd_time[k][j] += 1.0; else if (self->rnd_time[k][j] >= 1.0) { self->rnd_time[k][j] -= 1.0; self->rnd_oldValue[k][j] = self->rnd_value[k][j]; self->rnd_value[k][j] = self->rnd_range[k][j] * (rand()/((MYFLT)(RAND_MAX)+1)) - self->rnd_halfRange[k][j]; self->rnd_diff[k][j] = self->rnd_value[k][j] - self->rnd_oldValue[k][j]; } self->rnd[k][j] = self->rnd_oldValue[k][j] + self->rnd_diff[k][j] * self->rnd_time[k][j]; xind = self->in_count[k][j] - (self->delays[k][j] + self->rnd[k][j]); if (xind < 0) xind += self->size[k][j]; ind = (int)xind; frac = xind - ind; x = self->buffer[k][j][ind]; x1 = self->buffer[k][j][ind+1]; val = x + (x1 - x) * frac; val *= feed; filt = val + (self->lastSamples[k][j] - val) * self->damp[k]; self->total_signal[k] += filt; self->buffer[k][j][self->in_count[k][j]] = inval + junction - self->lastSamples[k][j]; self->lastSamples[k][j] = filt; if(self->in_count[k][j] == 0) self->buffer[k][j][self->size[k][j]] = self->buffer[k][j][0]; self->in_count[k][j]++; if (self->in_count[k][j] >= self->size[k][j]) self->in_count[k][j] = 0; } self->buffer_streams[i+k*self->bufsize] = self->total_signal[k] * 0.25; } } } static void STReverb_mix_i(STReverb *self) { int i, k; MYFLT val; MYFLT mix = PyFloat_AS_DOUBLE(self->mix); if (mix < 0.0) mix = 0.0; else if (mix > 1.0) mix = 1.0; for (i=0; ibufsize; i++) { for (k=0; k<2; k++) { val = self->input_buffer[k][i] + (self->buffer_streams[i+k*self->bufsize] - self->input_buffer[k][i]) * mix; self->buffer_streams[i+k*self->bufsize] = val; } } } static void STReverb_mix_a(STReverb *self) { int i, k; MYFLT mix, val; MYFLT *mi = Stream_getData((Stream *)self->mix_stream); for (i=0; ibufsize; i++) { mix = mi[i]; if (mix < 0.0) mix = 0.0; else if (mix > 1.0) mix = 1.0; for (k=0; k<2; k++) { val = self->input_buffer[k][i] + (self->buffer_streams[i+k*self->bufsize] - self->input_buffer[k][i]) * mix; self->buffer_streams[i+k*self->bufsize] = val; } } } static void STReverb_setProcMode(STReverb *self) { int procmode, mixmode; procmode = self->modebuffer[0] + self->modebuffer[2] * 10; mixmode = self->modebuffer[3]; switch (procmode) { case 0: self->proc_func_ptr = STReverb_process_ii; break; case 1: self->proc_func_ptr = STReverb_process_ai; break; case 10: self->proc_func_ptr = STReverb_process_ia; break; case 11: self->proc_func_ptr = STReverb_process_aa; break; } switch (mixmode) { case 0: self->mix_func_ptr = STReverb_mix_i; break; case 1: self->mix_func_ptr = STReverb_mix_a; break; } } MYFLT * STReverb_getSamplesBuffer(STReverb *self) { return (MYFLT *)self->buffer_streams; } static void STReverb_compute_next_data_frame(STReverb *self) { (*self->proc_func_ptr)(self); (*self->mix_func_ptr)(self); } static int STReverb_traverse(STReverb *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->inpos); Py_VISIT(self->inpos_stream); Py_VISIT(self->revtime); Py_VISIT(self->revtime_stream); Py_VISIT(self->cutoff); Py_VISIT(self->cutoff_stream); Py_VISIT(self->mix); Py_VISIT(self->mix_stream); return 0; } static int STReverb_clear(STReverb *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->inpos); Py_CLEAR(self->inpos_stream); Py_CLEAR(self->revtime); Py_CLEAR(self->revtime_stream); Py_CLEAR(self->cutoff); Py_CLEAR(self->cutoff_stream); Py_CLEAR(self->mix); Py_CLEAR(self->mix_stream); return 0; } static void STReverb_dealloc(STReverb* self) { int i, k; pyo_DEALLOC for (k=0; k<2; k++) { free(self->input_buffer[k]); for (i=0; i<8; i++) { free(self->buffer[k][i]); } } for (i=0; iref_buffer[i]); } free(self->buffer_streams); STReverb_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * STReverb_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, j, k, din; long maxsize; MYFLT roomSize = 1.0; MYFLT firstRefTmp = -3.0; PyObject *inputtmp, *input_streamtmp, *inpostmp=NULL, *revtimetmp=NULL, *cutofftmp=NULL, *mixtmp=NULL; STReverb *self; self = (STReverb *)type->tp_alloc(type, 0); self->inpos = PyFloat_FromDouble(0.5); self->revtime = PyFloat_FromDouble(0.5); self->cutoff = PyFloat_FromDouble(5000.0); self->mix = PyFloat_FromDouble(0.5); self->total_signal[0] = self->total_signal[1] = self->lastFreq = self->damp[0] = self->damp[1] = 0.0; self->lastInpos = -1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON self->nyquist = self->sr * 0.49; self->srfac = self->sr / 44100.0; Stream_setFunctionPtr(self->stream, STReverb_compute_next_data_frame); self->mode_func_ptr = STReverb_setProcMode; static char *kwlist[] = {"input", "inpos", "revtime", "cutoff", "mix", "roomSize", "firstRefGain", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOOOFF, kwlist, &inputtmp, &inpostmp, &revtimetmp, &cutofftmp, &mixtmp, &roomSize, &firstRefTmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (inpostmp) { PyObject_CallMethod((PyObject *)self, "setInpos", "O", inpostmp); } if (revtimetmp) { PyObject_CallMethod((PyObject *)self, "setRevtime", "O", revtimetmp); } if (cutofftmp) { PyObject_CallMethod((PyObject *)self, "setCutoff", "O", cutofftmp); } if (mixtmp) { PyObject_CallMethod((PyObject *)self, "setMix", "O", mixtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->firstRefGain = MYPOW(10.0, firstRefTmp * 0.05); if (roomSize < 0.25) roomSize = 0.25; else if (roomSize > 4.0) roomSize = 4.0; self->avg_time = 0.0; for (k=0; k<2; k++) { din = k * 3; for (i=0; i<8; i++) { self->in_count[k][i] = 0; self->lastSamples[k][i] = 0.0; self->rnd[k][i] = self->rnd_value[k][i] = self->rnd_oldValue[k][i] = self->rnd_diff[k][i] = 0.0; self->rnd_time[k][i] = 1.0; self->rnd_timeInc[k][i] = reverbParams[i][2] * randomScaling / self->sr; self->rnd_range[k][i] = reverbParams[i][1] * randomScaling * self->sr; self->rnd_halfRange[k][i] = self->rnd_range[k][i] * 0.5; self->delays[k][i] = reverbParams[i][din] * self->srfac * roomSize; self->avg_time += self->delays[k][i] / self->sr; self->size[k][i] = reverbParams[i][din] * self->srfac * roomSize + (int)(reverbParams[i][1] * self->sr + 0.5); maxsize = reverbParams[i][din] * self->srfac * 4.0 + (int)(reverbParams[i][1] * self->sr + 0.5); self->buffer[k][i] = (MYFLT *)realloc(self->buffer[k][i], (maxsize+1) * sizeof(MYFLT)); for (j=0; j<(maxsize+1); j++) { self->buffer[k][i][j] = 0.; } } } self->avg_time /= 16.0; for (k=0; kref_in_count[k] = 0; self->ref_size[k] = (int)(first_ref_delays[k] * self->srfac * roomSize + 0.5); maxsize = (int)(first_ref_delays[k] * self->srfac * 4.0 + 0.5); self->ref_buffer[k] = (MYFLT *)realloc(self->ref_buffer[k], (maxsize+1) * sizeof(MYFLT)); for (i=0; i<(maxsize+1); i++) { self->ref_buffer[k][i] = 0.0; } } for (k=0; k<2; k++) { self->input_buffer[k] = (MYFLT *)realloc(self->input_buffer[k], self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->input_buffer[k][i] = 0.0; } } self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, 2 * self->bufsize * sizeof(MYFLT)); for (i=0; i<(2 * self->bufsize); i++) { self->buffer_streams[i] = 0.0; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * STReverb_getServer(STReverb* self) { GET_SERVER }; static PyObject * STReverb_getStream(STReverb* self) { GET_STREAM }; static PyObject * STReverb_play(STReverb *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * STReverb_stop(STReverb *self) { STOP }; static PyObject * STReverb_setInpos(STReverb *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->inpos); if (isNumber == 1) { self->inpos = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->inpos = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->inpos, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->inpos_stream); self->inpos_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * STReverb_setRevtime(STReverb *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->revtime); if (isNumber == 1) { self->revtime = PyNumber_Float(tmp); self->modebuffer[1] = 0; } else { self->revtime = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->revtime, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->revtime_stream); self->revtime_stream = (Stream *)streamtmp; self->modebuffer[1] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * STReverb_setCutoff(STReverb *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->cutoff); if (isNumber == 1) { self->cutoff = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->cutoff = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->cutoff, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->cutoff_stream); self->cutoff_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * STReverb_setMix(STReverb *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->mix); if (isNumber == 1) { self->mix = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->mix = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->mix, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->mix_stream); self->mix_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * STReverb_setRoomSize(STReverb *self, PyObject *arg) { int i, j, k, din; long maxsize; MYFLT roomSize; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { roomSize = PyFloat_AsDouble(arg); if (roomSize < 0.25) roomSize = 0.25; else if (roomSize > 4.0) roomSize = 4.0; self->avg_time = 0.0; for (k=0; k<2; k++) { din = k * 3; for (i=0; i<8; i++) { self->in_count[k][i] = 0; self->lastSamples[k][i] = 0.0; self->rnd[k][i] = self->rnd_value[k][i] = self->rnd_oldValue[k][i] = self->rnd_diff[k][i] = 0.0; self->rnd_time[k][i] = 1.0; self->delays[k][i] = reverbParams[i][din] * self->srfac * roomSize; self->avg_time += self->delays[k][i] / self->sr; self->size[k][i] = reverbParams[i][din] * self->srfac * roomSize + (int)(reverbParams[i][1] * self->sr + 0.5); maxsize = reverbParams[i][din] * self->srfac * 2 + (int)(reverbParams[i][1] * self->sr + 0.5); for (j=0; j<(maxsize+1); j++) { self->buffer[k][i][j] = 0.; } } } self->avg_time /= 16.0; for (k=0; kref_in_count[k] = 0; self->ref_size[k] = (int)(first_ref_delays[k] * self->srfac * roomSize + 0.5); maxsize = (int)(first_ref_delays[k] * self->srfac * 2 + 0.5); for (i=0; i<(maxsize+1); i++) { self->ref_buffer[k][i] = 0.0; } } } Py_INCREF(Py_None); return Py_None; } static PyObject * STReverb_setFirstRefGain(STReverb *self, PyObject *arg) { MYFLT tmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { tmp = PyFloat_AsDouble(arg); self->firstRefGain = MYPOW(10.0, tmp * 0.05); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef STReverb_members[] = { {"server", T_OBJECT_EX, offsetof(STReverb, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(STReverb, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(STReverb, input), 0, "Input sound object."}, {"inpos", T_OBJECT_EX, offsetof(STReverb, inpos), 0, "Position left-right of the source."}, {"revtime", T_OBJECT_EX, offsetof(STReverb, revtime), 0, "Reverb duration value."}, {"cutoff", T_OBJECT_EX, offsetof(STReverb, cutoff), 0, "STReverb lowpass filter cutoff."}, {"mix", T_OBJECT_EX, offsetof(STReverb, mix), 0, "Balance between dry and wet signals."}, {NULL} /* Sentinel */ }; static PyMethodDef STReverb_methods[] = { {"getServer", (PyCFunction)STReverb_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)STReverb_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)STReverb_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)STReverb_stop, METH_NOARGS, "Stops computing."}, {"setInpos", (PyCFunction)STReverb_setInpos, METH_O, "Sets position of the source between 0 -> 1."}, {"setRevtime", (PyCFunction)STReverb_setRevtime, METH_O, "Sets reverb duration in seconds."}, {"setCutoff", (PyCFunction)STReverb_setCutoff, METH_O, "Sets lowpass filter cutoff."}, {"setMix", (PyCFunction)STReverb_setMix, METH_O, "Sets balance between dry and wet signals."}, {"setFirstRefGain", (PyCFunction)STReverb_setFirstRefGain, METH_O, "Sets gain of the first reflexions."}, {"setRoomSize", (PyCFunction)STReverb_setRoomSize, METH_O, "Sets room size scaler."}, {NULL} /* Sentinel */ }; PyTypeObject STReverbType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.STReverb_base", /*tp_name*/ sizeof(STReverb), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)STReverb_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "STReverb objects. Waveguide-based reverberation network.", /* tp_doc */ (traverseproc)STReverb_traverse, /* tp_traverse */ (inquiry)STReverb_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ STReverb_methods, /* tp_methods */ STReverb_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ STReverb_new, /* tp_new */ }; /************************************************************************************************/ /* STReverb streamer object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD STReverb *mainSplitter; int modebuffer[2]; int chnl; // STRev order } STRev; static void STRev_postprocessing_ii(STRev *self) { POST_PROCESSING_II }; static void STRev_postprocessing_ai(STRev *self) { POST_PROCESSING_AI }; static void STRev_postprocessing_ia(STRev *self) { POST_PROCESSING_IA }; static void STRev_postprocessing_aa(STRev *self) { POST_PROCESSING_AA }; static void STRev_postprocessing_ireva(STRev *self) { POST_PROCESSING_IREVA }; static void STRev_postprocessing_areva(STRev *self) { POST_PROCESSING_AREVA }; static void STRev_postprocessing_revai(STRev *self) { POST_PROCESSING_REVAI }; static void STRev_postprocessing_revaa(STRev *self) { POST_PROCESSING_REVAA }; static void STRev_postprocessing_revareva(STRev *self) { POST_PROCESSING_REVAREVA }; static void STRev_setProcMode(STRev *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = STRev_postprocessing_ii; break; case 1: self->muladd_func_ptr = STRev_postprocessing_ai; break; case 2: self->muladd_func_ptr = STRev_postprocessing_revai; break; case 10: self->muladd_func_ptr = STRev_postprocessing_ia; break; case 11: self->muladd_func_ptr = STRev_postprocessing_aa; break; case 12: self->muladd_func_ptr = STRev_postprocessing_revaa; break; case 20: self->muladd_func_ptr = STRev_postprocessing_ireva; break; case 21: self->muladd_func_ptr = STRev_postprocessing_areva; break; case 22: self->muladd_func_ptr = STRev_postprocessing_revareva; break; } } static void STRev_compute_next_data_frame(STRev *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = STReverb_getSamplesBuffer((STReverb *)self->mainSplitter); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int STRev_traverse(STRev *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainSplitter); return 0; } static int STRev_clear(STRev *self) { pyo_CLEAR Py_CLEAR(self->mainSplitter); return 0; } static void STRev_dealloc(STRev* self) { pyo_DEALLOC STRev_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * STRev_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; STRev *self; self = (STRev *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, STRev_compute_next_data_frame); self->mode_func_ptr = STRev_setProcMode; static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainSplitter); Py_INCREF(maintmp); self->mainSplitter = (STReverb *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * STRev_getServer(STRev* self) { GET_SERVER }; static PyObject * STRev_getStream(STRev* self) { GET_STREAM }; static PyObject * STRev_setMul(STRev *self, PyObject *arg) { SET_MUL }; static PyObject * STRev_setAdd(STRev *self, PyObject *arg) { SET_ADD }; static PyObject * STRev_setSub(STRev *self, PyObject *arg) { SET_SUB }; static PyObject * STRev_setDiv(STRev *self, PyObject *arg) { SET_DIV }; static PyObject * STRev_play(STRev *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * STRev_out(STRev *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * STRev_stop(STRev *self) { STOP }; static PyObject * STRev_multiply(STRev *self, PyObject *arg) { MULTIPLY }; static PyObject * STRev_inplace_multiply(STRev *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * STRev_add(STRev *self, PyObject *arg) { ADD }; static PyObject * STRev_inplace_add(STRev *self, PyObject *arg) { INPLACE_ADD }; static PyObject * STRev_sub(STRev *self, PyObject *arg) { SUB }; static PyObject * STRev_inplace_sub(STRev *self, PyObject *arg) { INPLACE_SUB }; static PyObject * STRev_div(STRev *self, PyObject *arg) { DIV }; static PyObject * STRev_inplace_div(STRev *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef STRev_members[] = { {"server", T_OBJECT_EX, offsetof(STRev, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(STRev, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(STRev, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(STRev, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef STRev_methods[] = { {"getServer", (PyCFunction)STRev_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)STRev_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)STRev_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)STRev_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)STRev_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)STRev_setMul, METH_O, "Sets STRev mul factor."}, {"setAdd", (PyCFunction)STRev_setAdd, METH_O, "Sets STRev add factor."}, {"setSub", (PyCFunction)STRev_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)STRev_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods STRev_as_number = { (binaryfunc)STRev_add, /*nb_add*/ (binaryfunc)STRev_sub, /*nb_subtract*/ (binaryfunc)STRev_multiply, /*nb_multiply*/ (binaryfunc)STRev_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)STRev_inplace_add, /*inplace_add*/ (binaryfunc)STRev_inplace_sub, /*inplace_subtract*/ (binaryfunc)STRev_inplace_multiply, /*inplace_multiply*/ (binaryfunc)STRev_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject STRevType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.STRev_base", /*tp_name*/ sizeof(STRev), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)STRev_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &STRev_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "STRev objects. Reads one channel from a STReverb object.", /* tp_doc */ (traverseproc)STRev_traverse, /* tp_traverse */ (inquiry)STRev_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ STRev_methods, /* tp_methods */ STRev_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ STRev_new, /* tp_new */ };pyo/src/objects/oscilmodule.c0000644000175000017500000153175512652732202015602 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "tablemodule.h" #include "interpolation.h" static MYFLT SINE_ARRAY[513] = {0.0, 0.012271538285719925, 0.024541228522912288, 0.036807222941358832, 0.049067674327418015, 0.061320736302208578, 0.073564563599667426, 0.085797312344439894, 0.098017140329560604, 0.11022220729388306, 0.1224106751992162, 0.13458070850712617, 0.14673047445536175, 0.15885814333386145, 0.17096188876030122, 0.18303988795514095, 0.19509032201612825, 0.20711137619221856, 0.2191012401568698, 0.23105810828067111, 0.24298017990326387, 0.25486565960451457, 0.26671275747489837, 0.27851968938505306, 0.29028467725446233, 0.30200594931922808, 0.31368174039889152, 0.32531029216226293, 0.33688985339222005, 0.34841868024943456, 0.35989503653498811, 0.37131719395183754, 0.38268343236508978, 0.3939920400610481, 0.40524131400498986, 0.41642956009763715, 0.42755509343028208, 0.43861623853852766, 0.44961132965460654, 0.46053871095824001, 0.47139673682599764, 0.48218377207912272, 0.49289819222978404, 0.50353838372571758, 0.51410274419322166, 0.52458968267846895, 0.53499761988709715, 0.54532498842204646, 0.55557023301960218, 0.56573181078361312, 0.57580819141784534, 0.58579785745643886, 0.59569930449243336, 0.60551104140432555, 0.61523159058062682, 0.62485948814238634, 0.63439328416364549, 0.64383154288979139, 0.65317284295377676, 0.66241577759017178, 0.67155895484701833, 0.68060099779545302, 0.68954054473706683, 0.69837624940897292, 0.70710678118654746, 0.71573082528381859, 0.72424708295146689, 0.7326542716724127, 0.74095112535495899, 0.74913639452345926, 0.75720884650648446, 0.76516726562245885, 0.77301045336273688, 0.78073722857209438, 0.78834642762660623, 0.79583690460888346, 0.80320753148064483, 0.81045719825259477, 0.81758481315158371, 0.82458930278502529, 0.83146961230254512, 0.83822470555483797, 0.84485356524970701, 0.8513551931052652, 0.85772861000027212, 0.8639728561215867, 0.87008699110871135, 0.87607009419540649, 0.88192126434835494, 0.88763962040285393, 0.89322430119551532, 0.89867446569395382, 0.90398929312344334, 0.90916798309052238, 0.91420975570353069, 0.91911385169005777, 0.92387953251128674, 0.92850608047321548, 0.93299279883473885, 0.93733901191257496, 0.94154406518302081, 0.94560732538052128, 0.94952818059303667, 0.95330604035419375, 0.95694033573220894, 0.96043051941556579, 0.96377606579543984, 0.96697647104485207, 0.97003125319454397, 0.97293995220556007, 0.97570213003852857, 0.97831737071962765, 0.98078528040323043, 0.98310548743121629, 0.98527764238894122, 0.98730141815785843, 0.98917650996478101, 0.99090263542778001, 0.99247953459870997, 0.99390697000235606, 0.99518472667219682, 0.996312612182778, 0.99729045667869021, 0.99811811290014918, 0.99879545620517241, 0.99932238458834954, 0.99969881869620425, 0.9999247018391445, 1.0, 0.9999247018391445, 0.99969881869620425, 0.99932238458834954, 0.99879545620517241, 0.99811811290014918, 0.99729045667869021, 0.996312612182778, 0.99518472667219693, 0.99390697000235606, 0.99247953459870997, 0.99090263542778001, 0.98917650996478101, 0.98730141815785843, 0.98527764238894122, 0.98310548743121629, 0.98078528040323043, 0.97831737071962765, 0.97570213003852857, 0.97293995220556018, 0.97003125319454397, 0.96697647104485207, 0.96377606579543984, 0.9604305194155659, 0.95694033573220894, 0.95330604035419386, 0.94952818059303667, 0.94560732538052139, 0.94154406518302081, 0.93733901191257496, 0.93299279883473885, 0.92850608047321559, 0.92387953251128674, 0.91911385169005777, 0.91420975570353069, 0.90916798309052249, 0.90398929312344345, 0.89867446569395393, 0.89322430119551521, 0.88763962040285393, 0.88192126434835505, 0.8760700941954066, 0.87008699110871146, 0.86397285612158681, 0.85772861000027212, 0.8513551931052652, 0.84485356524970723, 0.83822470555483819, 0.83146961230254546, 0.82458930278502529, 0.81758481315158371, 0.81045719825259477, 0.80320753148064494, 0.79583690460888357, 0.78834642762660634, 0.7807372285720946, 0.7730104533627371, 0.76516726562245907, 0.75720884650648479, 0.74913639452345926, 0.74095112535495899, 0.73265427167241282, 0.724247082951467, 0.71573082528381871, 0.70710678118654757, 0.69837624940897292, 0.68954054473706705, 0.68060099779545324, 0.67155895484701855, 0.66241577759017201, 0.65317284295377664, 0.64383154288979139, 0.63439328416364549, 0.62485948814238634, 0.61523159058062693, 0.60551104140432555, 0.59569930449243347, 0.58579785745643898, 0.57580819141784545, 0.56573181078361345, 0.55557023301960218, 0.54532498842204635, 0.53499761988709715, 0.52458968267846895, 0.51410274419322177, 0.50353838372571758, 0.49289819222978415, 0.48218377207912289, 0.47139673682599781, 0.46053871095824023, 0.44961132965460687, 0.43861623853852755, 0.42755509343028203, 0.41642956009763715, 0.40524131400498986, 0.39399204006104815, 0.38268343236508984, 0.37131719395183765, 0.35989503653498833, 0.34841868024943479, 0.33688985339222027, 0.3253102921622632, 0.31368174039889141, 0.30200594931922803, 0.29028467725446233, 0.27851968938505312, 0.26671275747489848, 0.25486565960451468, 0.24298017990326404, 0.2310581082806713, 0.21910124015687002, 0.20711137619221884, 0.19509032201612858, 0.1830398879551409, 0.17096188876030119, 0.15885814333386145, 0.1467304744553618, 0.13458070850712628, 0.12241067519921635, 0.11022220729388325, 0.09801714032956084, 0.085797312344440158, 0.073564563599667745, 0.061320736302208495, 0.049067674327417973, 0.036807222941358832, 0.024541228522912326, 0.012271538285720007, 1.2246467991473532e-16, -0.012271538285719761, -0.024541228522912083, -0.036807222941358582, -0.049067674327417724, -0.061320736302208245, -0.073564563599667496, -0.085797312344439922, -0.09801714032956059, -0.110222207293883, -0.1224106751992161, -0.13458070850712606, -0.14673047445536158, -0.15885814333386122, -0.17096188876030097, -0.18303988795514067, -0.19509032201612836, -0.20711137619221862, -0.21910124015686983, -0.23105810828067111, -0.24298017990326382, -0.25486565960451446, -0.26671275747489825, -0.27851968938505289, -0.29028467725446216, -0.30200594931922781, -0.31368174039889118, -0.32531029216226304, -0.33688985339222011, -0.34841868024943456, -0.35989503653498811, -0.37131719395183749, -0.38268343236508967, -0.39399204006104793, -0.40524131400498969, -0.41642956009763693, -0.42755509343028181, -0.43861623853852733, -0.44961132965460665, -0.46053871095824006, -0.47139673682599764, -0.48218377207912272, -0.49289819222978393, -0.50353838372571746, -0.51410274419322155, -0.52458968267846873, -0.53499761988709693, -0.54532498842204613, -0.55557023301960196, -0.56573181078361323, -0.57580819141784534, -0.58579785745643886, -0.59569930449243325, -0.60551104140432543, -0.61523159058062671, -0.62485948814238623, -0.63439328416364527, -0.64383154288979128, -0.65317284295377653, -0.66241577759017178, -0.67155895484701844, -0.68060099779545302, -0.68954054473706683, -0.6983762494089728, -0.70710678118654746, -0.71573082528381848, -0.72424708295146667, -0.73265427167241259, -0.74095112535495877, -0.74913639452345904, -0.75720884650648423, -0.76516726562245885, -0.77301045336273666, -0.78073722857209438, -0.78834642762660589, -0.79583690460888334, -0.80320753148064505, -0.81045719825259466, -0.81758481315158371, -0.82458930278502507, -0.83146961230254524, -0.83822470555483775, -0.84485356524970712, -0.85135519310526486, -0.85772861000027201, -0.86397285612158647, -0.87008699110871135, -0.87607009419540671, -0.88192126434835494, -0.88763962040285405, -0.89322430119551521, -0.89867446569395382, -0.90398929312344312, -0.90916798309052238, -0.91420975570353047, -0.91911385169005766, -0.92387953251128652, -0.92850608047321548, -0.93299279883473896, -0.93733901191257485, -0.94154406518302081, -0.94560732538052117, -0.94952818059303667, -0.95330604035419375, -0.95694033573220882, -0.96043051941556568, -0.96377606579543984, -0.96697647104485218, -0.97003125319454397, -0.97293995220556018, -0.97570213003852846, -0.97831737071962765, -0.98078528040323032, -0.98310548743121629, -0.98527764238894111, -0.98730141815785832, -0.9891765099647809, -0.99090263542778001, -0.99247953459871008, -0.99390697000235606, -0.99518472667219693, -0.996312612182778, -0.99729045667869021, -0.99811811290014918, -0.99879545620517241, -0.99932238458834943, -0.99969881869620425, -0.9999247018391445, -1.0, -0.9999247018391445, -0.99969881869620425, -0.99932238458834954, -0.99879545620517241, -0.99811811290014918, -0.99729045667869021, -0.996312612182778, -0.99518472667219693, -0.99390697000235606, -0.99247953459871008, -0.99090263542778001, -0.9891765099647809, -0.98730141815785843, -0.98527764238894122, -0.9831054874312164, -0.98078528040323043, -0.97831737071962777, -0.97570213003852857, -0.97293995220556029, -0.97003125319454397, -0.96697647104485229, -0.96377606579543995, -0.96043051941556579, -0.95694033573220894, -0.95330604035419375, -0.94952818059303679, -0.94560732538052128, -0.94154406518302092, -0.93733901191257496, -0.93299279883473907, -0.92850608047321559, -0.92387953251128663, -0.91911385169005788, -0.91420975570353058, -0.90916798309052249, -0.90398929312344334, -0.89867446569395404, -0.89322430119551532, -0.88763962040285416, -0.88192126434835505, -0.87607009419540693, -0.87008699110871146, -0.8639728561215867, -0.85772861000027223, -0.85135519310526508, -0.84485356524970734, -0.83822470555483797, -0.83146961230254557, -0.82458930278502529, -0.81758481315158404, -0.81045719825259488, -0.80320753148064528, -0.79583690460888368, -0.78834642762660612, -0.78073722857209471, -0.77301045336273688, -0.76516726562245918, -0.75720884650648457, -0.7491363945234597, -0.74095112535495922, -0.73265427167241315, -0.72424708295146711, -0.71573082528381904, -0.70710678118654768, -0.69837624940897269, -0.68954054473706716, -0.68060099779545302, -0.67155895484701866, -0.66241577759017178, -0.65317284295377709, -0.6438315428897915, -0.63439328416364593, -0.62485948814238645, -0.61523159058062737, -0.60551104140432566, -0.59569930449243325, -0.58579785745643909, -0.57580819141784523, -0.56573181078361356, -0.55557023301960218, -0.5453249884220468, -0.53499761988709726, -0.52458968267846939, -0.51410274419322188, -0.50353838372571813, -0.49289819222978426, -0.48218377207912261, -0.47139673682599792, -0.46053871095823995, -0.44961132965460698, -0.43861623853852766, -0.42755509343028253, -0.41642956009763726, -0.40524131400499042, -0.39399204006104827, -0.38268343236509039, -0.37131719395183777, -0.359895036534988, -0.3484186802494349, -0.33688985339222, -0.32531029216226331, -0.31368174039889152, -0.30200594931922853, -0.29028467725446244, -0.27851968938505367, -0.26671275747489859, -0.25486565960451435, -0.24298017990326418, -0.23105810828067103, -0.21910124015687016, -0.20711137619221853, -0.19509032201612872, -0.18303988795514103, -0.17096188876030177, -0.15885814333386158, -0.14673047445536239, -0.13458070850712642, -0.12241067519921603, -0.11022220729388338, -0.09801714032956052, -0.085797312344440282, -0.073564563599667426, -0.06132073630220905, -0.049067674327418091, -0.036807222941359394, -0.024541228522912451, -0.012271538285720572, 0.0}; static MYFLT COSINE_ARRAY[513] = {1.0, 0.9999247018391445, 0.9996988186962042, 0.9993223845883495, 0.9987954562051724, 0.9981181129001492, 0.9972904566786902, 0.996312612182778, 0.9951847266721969, 0.9939069700023561, 0.99247953459871, 0.99090263542778, 0.989176509964781, 0.9873014181578584, 0.9852776423889412, 0.9831054874312163, 0.9807852804032304, 0.9783173707196277, 0.9757021300385286, 0.9729399522055602, 0.970031253194544, 0.9669764710448521, 0.9637760657954398, 0.9604305194155658, 0.9569403357322088, 0.9533060403541939, 0.9495281805930367, 0.9456073253805213, 0.9415440651830208, 0.937339011912575, 0.932992798834739, 0.9285060804732156, 0.9238795325112867, 0.9191138516900578, 0.9142097557035307, 0.9091679830905224, 0.9039892931234433, 0.8986744656939538, 0.8932243011955153, 0.8876396204028539, 0.881921264348355, 0.8760700941954066, 0.8700869911087115, 0.8639728561215868, 0.8577286100002721, 0.8513551931052652, 0.8448535652497071, 0.8382247055548381, 0.8314696123025452, 0.8245893027850253, 0.8175848131515837, 0.8104571982525948, 0.8032075314806449, 0.7958369046088836, 0.7883464276266063, 0.7807372285720945, 0.773010453362737, 0.765167265622459, 0.7572088465064846, 0.7491363945234594, 0.7409511253549591, 0.7326542716724128, 0.724247082951467, 0.7157308252838186, 0.7071067811865476, 0.6983762494089729, 0.6895405447370669, 0.6806009977954531, 0.6715589548470183, 0.6624157775901718, 0.6531728429537768, 0.6438315428897915, 0.6343932841636455, 0.6248594881423865, 0.6152315905806268, 0.6055110414043255, 0.5956993044924335, 0.5857978574564389, 0.5758081914178453, 0.5657318107836132, 0.5555702330196023, 0.5453249884220465, 0.5349976198870973, 0.5245896826784688, 0.5141027441932217, 0.5035383837257176, 0.4928981922297841, 0.48218377207912283, 0.4713967368259978, 0.46053871095824, 0.4496113296546066, 0.4386162385385277, 0.4275550934302822, 0.4164295600976373, 0.40524131400498986, 0.3939920400610481, 0.38268343236508984, 0.3713171939518376, 0.3598950365349883, 0.3484186802494345, 0.33688985339222005, 0.325310292162263, 0.3136817403988916, 0.3020059493192282, 0.29028467725446233, 0.27851968938505306, 0.2667127574748984, 0.2548656596045146, 0.24298017990326398, 0.23105810828067128, 0.21910124015686977, 0.20711137619221856, 0.19509032201612833, 0.18303988795514106, 0.17096188876030136, 0.1588581433338614, 0.14673047445536175, 0.13458070850712622, 0.12241067519921628, 0.11022220729388318, 0.09801714032956077, 0.08579731234443988, 0.07356456359966745, 0.06132073630220865, 0.049067674327418126, 0.03680722294135899, 0.024541228522912264, 0.012271538285719944, 6.123031769111886e-17, -0.012271538285719823, -0.024541228522912142, -0.036807222941358866, -0.04906767432741801, -0.06132073630220853, -0.07356456359966733, -0.08579731234443976, -0.09801714032956065, -0.11022220729388306, -0.12241067519921615, -0.1345807085071261, -0.14673047445536164, -0.15885814333386128, -0.17096188876030124, -0.18303988795514092, -0.1950903220161282, -0.20711137619221845, -0.21910124015686966, -0.23105810828067114, -0.24298017990326387, -0.2548656596045145, -0.2667127574748983, -0.27851968938505295, -0.29028467725446216, -0.3020059493192281, -0.3136817403988914, -0.32531029216226287, -0.33688985339221994, -0.3484186802494344, -0.35989503653498817, -0.3713171939518375, -0.3826834323650897, -0.393992040061048, -0.40524131400498975, -0.416429560097637, -0.42755509343028186, -0.4386162385385274, -0.4496113296546067, -0.46053871095824006, -0.4713967368259977, -0.4821837720791227, -0.492898192229784, -0.5035383837257175, -0.5141027441932217, -0.5245896826784687, -0.534997619887097, -0.5453249884220462, -0.555570233019602, -0.5657318107836132, -0.5758081914178453, -0.5857978574564389, -0.5956993044924334, -0.6055110414043254, -0.6152315905806267, -0.6248594881423862, -0.6343932841636454, -0.6438315428897913, -0.6531728429537765, -0.6624157775901719, -0.6715589548470184, -0.680600997795453, -0.6895405447370669, -0.6983762494089728, -0.7071067811865475, -0.7157308252838186, -0.7242470829514668, -0.7326542716724127, -0.7409511253549589, -0.7491363945234591, -0.7572088465064846, -0.765167265622459, -0.773010453362737, -0.7807372285720945, -0.7883464276266062, -0.7958369046088835, -0.8032075314806448, -0.8104571982525947, -0.8175848131515836, -0.8245893027850251, -0.8314696123025453, -0.8382247055548381, -0.8448535652497071, -0.8513551931052652, -0.857728610000272, -0.8639728561215867, -0.8700869911087113, -0.8760700941954065, -0.8819212643483549, -0.8876396204028538, -0.8932243011955152, -0.8986744656939539, -0.9039892931234433, -0.9091679830905224, -0.9142097557035307, -0.9191138516900578, -0.9238795325112867, -0.9285060804732155, -0.9329927988347388, -0.9373390119125748, -0.9415440651830207, -0.9456073253805212, -0.9495281805930367, -0.9533060403541939, -0.9569403357322088, -0.9604305194155658, -0.9637760657954398, -0.9669764710448521, -0.970031253194544, -0.9729399522055601, -0.9757021300385285, -0.9783173707196275, -0.9807852804032304, -0.9831054874312163, -0.9852776423889412, -0.9873014181578584, -0.989176509964781, -0.99090263542778, -0.99247953459871, -0.9939069700023561, -0.9951847266721968, -0.996312612182778, -0.9972904566786902, -0.9981181129001492, -0.9987954562051724, -0.9993223845883495, -0.9996988186962042, -0.9999247018391445, -1.0, -0.9999247018391445, -0.9996988186962042, -0.9993223845883495, -0.9987954562051724, -0.9981181129001492, -0.9972904566786902, -0.996312612182778, -0.9951847266721969, -0.9939069700023561, -0.99247953459871, -0.99090263542778, -0.989176509964781, -0.9873014181578584, -0.9852776423889413, -0.9831054874312164, -0.9807852804032304, -0.9783173707196277, -0.9757021300385286, -0.9729399522055602, -0.970031253194544, -0.9669764710448522, -0.96377606579544, -0.9604305194155659, -0.9569403357322089, -0.953306040354194, -0.9495281805930368, -0.9456073253805213, -0.9415440651830208, -0.937339011912575, -0.932992798834739, -0.9285060804732156, -0.9238795325112868, -0.9191138516900578, -0.9142097557035307, -0.9091679830905225, -0.9039892931234434, -0.898674465693954, -0.8932243011955153, -0.8876396204028539, -0.881921264348355, -0.8760700941954066, -0.8700869911087115, -0.8639728561215868, -0.8577286100002721, -0.8513551931052653, -0.8448535652497072, -0.8382247055548382, -0.8314696123025455, -0.8245893027850253, -0.8175848131515837, -0.8104571982525948, -0.8032075314806449, -0.7958369046088836, -0.7883464276266063, -0.7807372285720946, -0.7730104533627371, -0.7651672656224591, -0.7572088465064848, -0.7491363945234593, -0.7409511253549591, -0.7326542716724128, -0.724247082951467, -0.7157308252838187, -0.7071067811865477, -0.698376249408973, -0.689540544737067, -0.6806009977954532, -0.6715589548470187, -0.662415777590172, -0.6531728429537771, -0.6438315428897915, -0.6343932841636459, -0.6248594881423865, -0.6152315905806273, -0.6055110414043257, -0.5956993044924331, -0.5857978574564391, -0.5758081914178452, -0.5657318107836135, -0.5555702330196022, -0.5453249884220468, -0.5349976198870973, -0.5245896826784694, -0.5141027441932218, -0.503538383725718, -0.4928981922297842, -0.48218377207912255, -0.47139673682599786, -0.4605387109582399, -0.44961132965460693, -0.4386162385385276, -0.4275550934302825, -0.4164295600976372, -0.40524131400499036, -0.3939920400610482, -0.38268343236509034, -0.37131719395183777, -0.35989503653498794, -0.34841868024943484, -0.33688985339221994, -0.3253102921622633, -0.31368174039889146, -0.30200594931922853, -0.29028467725446244, -0.2785196893850536, -0.26671275747489853, -0.25486565960451435, -0.24298017990326412, -0.23105810828067094, -0.2191012401568701, -0.20711137619221848, -0.19509032201612866, -0.18303988795514095, -0.1709618887603017, -0.15885814333386153, -0.1467304744553623, -0.13458070850712636, -0.12241067519921596, -0.11022220729388331, -0.09801714032956045, -0.08579731234444023, -0.07356456359966736, -0.061320736302208995, -0.04906767432741803, -0.03680722294135933, -0.02454122852291239, -0.012271538285720512, -1.836909530733566e-16, 0.012271538285720144, 0.02454122852291202, 0.036807222941358964, 0.04906767432741766, 0.06132073630220863, 0.07356456359966698, 0.08579731234443985, 0.09801714032956009, 0.11022220729388293, 0.1224106751992156, 0.13458070850712597, 0.14673047445536194, 0.15885814333386117, 0.17096188876030133, 0.1830398879551406, 0.1950903220161283, 0.20711137619221812, 0.21910124015686974, 0.23105810828067058, 0.24298017990326376, 0.25486565960451396, 0.2667127574748982, 0.2785196893850533, 0.29028467725446205, 0.30200594931922814, 0.31368174039889113, 0.3253102921622629, 0.3368898533922196, 0.3484186802494345, 0.3598950365349876, 0.3713171939518374, 0.38268343236509, 0.3939920400610479, 0.40524131400499, 0.4164295600976369, 0.42755509343028214, 0.43861623853852727, 0.4496113296546066, 0.46053871095823956, 0.4713967368259976, 0.4821837720791222, 0.49289819222978387, 0.5035383837257178, 0.5141027441932216, 0.5245896826784691, 0.5349976198870969, 0.5453249884220465, 0.5555702330196018, 0.5657318107836131, 0.5758081914178449, 0.5857978574564388, 0.5956993044924329, 0.6055110414043253, 0.615231590580627, 0.6248594881423861, 0.6343932841636456, 0.6438315428897912, 0.6531728429537768, 0.6624157775901715, 0.6715589548470183, 0.6806009977954527, 0.6895405447370668, 0.6983762494089724, 0.7071067811865474, 0.7157308252838188, 0.7242470829514667, 0.7326542716724129, 0.7409511253549589, 0.7491363945234594, 0.7572088465064842, 0.7651672656224588, 0.7730104533627367, 0.7807372285720944, 0.7883464276266059, 0.7958369046088833, 0.803207531480645, 0.8104571982525947, 0.8175848131515837, 0.8245893027850251, 0.8314696123025452, 0.8382247055548377, 0.844853565249707, 0.8513551931052649, 0.857728610000272, 0.8639728561215864, 0.8700869911087113, 0.8760700941954067, 0.8819212643483548, 0.8876396204028539, 0.8932243011955151, 0.8986744656939538, 0.9039892931234431, 0.9091679830905224, 0.9142097557035305, 0.9191138516900577, 0.9238795325112865, 0.9285060804732155, 0.932992798834739, 0.9373390119125748, 0.9415440651830208, 0.9456073253805212, 0.9495281805930367, 0.9533060403541936, 0.9569403357322088, 0.9604305194155657, 0.9637760657954398, 0.9669764710448522, 0.970031253194544, 0.9729399522055602, 0.9757021300385285, 0.9783173707196277, 0.9807852804032303, 0.9831054874312163, 0.9852776423889411, 0.9873014181578583, 0.9891765099647809, 0.99090263542778, 0.99247953459871, 0.9939069700023561, 0.9951847266721969, 0.996312612182778, 0.9972904566786902, 0.9981181129001492, 0.9987954562051724, 0.9993223845883494, 0.9996988186962042, 0.9999247018391445, 1.0}; static MYFLT ONE_OVER_512 = 1.0 / 512.0; static const MYFLT ROSSLER_SCALE = 0.05757; static const MYFLT ROSSLER_ALT_SCALE = 0.06028; static const MYFLT LORENZ_SCALE = 0.05107; static const MYFLT LORENZ_ALT_SCALE = 0.03679; static MYFLT _clip(MYFLT x) { if (x < 0.0) return 0.0; else if (x >= 1.0) return 1.0; else return x; } static MYFLT Sine_clip(MYFLT x) { if (x < 0) { x += ((int)(-x * ONE_OVER_512) + 1) * 512; } else if (x >= 512) { x -= (int)(x * ONE_OVER_512) * 512; } return x; } /* Sine object */ typedef struct { pyo_audio_HEAD PyObject *freq; Stream *freq_stream; PyObject *phase; Stream *phase_stream; int modebuffer[4]; MYFLT pointerPos; } Sine; static void Sine_readframes_ii(Sine *self) { MYFLT inc, fr, ph, pos, fpart; int i, ipart; fr = PyFloat_AS_DOUBLE(self->freq); ph = PyFloat_AS_DOUBLE(self->phase) * 512; inc = fr * 512 / self->sr; for (i=0; ibufsize; i++) { self->pointerPos = Sine_clip(self->pointerPos); pos = self->pointerPos + ph; if (pos >= 512) pos -= 512; ipart = (int)pos; fpart = pos - ipart; self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos += inc; } } static void Sine_readframes_ai(Sine *self) { MYFLT inc, ph, pos, fpart, fac; int i, ipart; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); ph = PyFloat_AS_DOUBLE(self->phase) * 512; fac = 512 / self->sr; for (i=0; ibufsize; i++) { inc = fr[i] * fac; self->pointerPos = Sine_clip(self->pointerPos); pos = self->pointerPos + ph; if (pos >= 512) pos -= 512; ipart = (int)pos; fpart = pos - ipart; self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos += inc; } } static void Sine_readframes_ia(Sine *self) { MYFLT inc, fr, pos, fpart; int i, ipart; fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *ph = Stream_getData((Stream *)self->phase_stream); inc = fr * 512 / self->sr; for (i=0; ibufsize; i++) { self->pointerPos = Sine_clip(self->pointerPos); pos = self->pointerPos + ph[i] * 512; if (pos >= 512) pos -= 512; ipart = (int)pos; fpart = pos - ipart; self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos += inc; } } static void Sine_readframes_aa(Sine *self) { MYFLT inc, pos, fpart, fac; int i, ipart; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *ph = Stream_getData((Stream *)self->phase_stream); fac = 512 / self->sr; for (i=0; ibufsize; i++) { inc = fr[i] * fac; self->pointerPos = Sine_clip(self->pointerPos); pos = self->pointerPos + ph[i] * 512; if (pos >= 512) pos -= 512; ipart = (int)pos; fpart = pos - ipart; self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos += inc; } } static void Sine_postprocessing_ii(Sine *self) { POST_PROCESSING_II }; static void Sine_postprocessing_ai(Sine *self) { POST_PROCESSING_AI }; static void Sine_postprocessing_ia(Sine *self) { POST_PROCESSING_IA }; static void Sine_postprocessing_aa(Sine *self) { POST_PROCESSING_AA }; static void Sine_postprocessing_ireva(Sine *self) { POST_PROCESSING_IREVA }; static void Sine_postprocessing_areva(Sine *self) { POST_PROCESSING_AREVA }; static void Sine_postprocessing_revai(Sine *self) { POST_PROCESSING_REVAI }; static void Sine_postprocessing_revaa(Sine *self) { POST_PROCESSING_REVAA }; static void Sine_postprocessing_revareva(Sine *self) { POST_PROCESSING_REVAREVA }; static void Sine_setProcMode(Sine *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Sine_readframes_ii; break; case 1: self->proc_func_ptr = Sine_readframes_ai; break; case 10: self->proc_func_ptr = Sine_readframes_ia; break; case 11: self->proc_func_ptr = Sine_readframes_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Sine_postprocessing_ii; break; case 1: self->muladd_func_ptr = Sine_postprocessing_ai; break; case 2: self->muladd_func_ptr = Sine_postprocessing_revai; break; case 10: self->muladd_func_ptr = Sine_postprocessing_ia; break; case 11: self->muladd_func_ptr = Sine_postprocessing_aa; break; case 12: self->muladd_func_ptr = Sine_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Sine_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Sine_postprocessing_areva; break; case 22: self->muladd_func_ptr = Sine_postprocessing_revareva; break; } } static void Sine_compute_next_data_frame(Sine *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Sine_traverse(Sine *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->phase); Py_VISIT(self->phase_stream); return 0; } static int Sine_clear(Sine *self) { pyo_CLEAR Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->phase); Py_CLEAR(self->phase_stream); return 0; } static void Sine_dealloc(Sine* self) { pyo_DEALLOC Sine_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Sine_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *freqtmp=NULL, *phasetmp=NULL, *multmp=NULL, *addtmp=NULL; Sine *self; self = (Sine *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->phase = PyFloat_FromDouble(0.0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->pointerPos = 0.; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Sine_compute_next_data_frame); self->mode_func_ptr = Sine_setProcMode; static char *kwlist[] = {"freq", "phase", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &phasetmp, &multmp, &addtmp)) Py_RETURN_NONE; if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (phasetmp) { PyObject_CallMethod((PyObject *)self, "setPhase", "O", phasetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Sine_getServer(Sine* self) { GET_SERVER }; static PyObject * Sine_getStream(Sine* self) { GET_STREAM }; static PyObject * Sine_setMul(Sine *self, PyObject *arg) { SET_MUL }; static PyObject * Sine_setAdd(Sine *self, PyObject *arg) { SET_ADD }; static PyObject * Sine_setSub(Sine *self, PyObject *arg) { SET_SUB }; static PyObject * Sine_setDiv(Sine *self, PyObject *arg) { SET_DIV }; static PyObject * Sine_play(Sine *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Sine_out(Sine *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Sine_stop(Sine *self) { STOP }; static PyObject * Sine_multiply(Sine *self, PyObject *arg) { MULTIPLY }; static PyObject * Sine_inplace_multiply(Sine *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Sine_add(Sine *self, PyObject *arg) { ADD }; static PyObject * Sine_inplace_add(Sine *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Sine_sub(Sine *self, PyObject *arg) { SUB }; static PyObject * Sine_inplace_sub(Sine *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Sine_div(Sine *self, PyObject *arg) { DIV }; static PyObject * Sine_inplace_div(Sine *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Sine_setFreq(Sine *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Sine_setPhase(Sine *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->phase); if (isNumber == 1) { self->phase = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->phase = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->phase, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->phase_stream); self->phase_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Sine_reset(Sine *self) { self->pointerPos = 0.0; Py_INCREF(Py_None); return Py_None; } static PyMemberDef Sine_members[] = { {"server", T_OBJECT_EX, offsetof(Sine, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Sine, stream), 0, "Stream object."}, {"freq", T_OBJECT_EX, offsetof(Sine, freq), 0, "Frequency in cycle per second."}, {"phase", T_OBJECT_EX, offsetof(Sine, phase), 0, "Phase of signal (0 -> 1)"}, {"mul", T_OBJECT_EX, offsetof(Sine, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Sine, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Sine_methods[] = { {"getServer", (PyCFunction)Sine_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Sine_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Sine_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Sine_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Sine_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Sine_setFreq, METH_O, "Sets oscillator frequency in cycle per second."}, {"setPhase", (PyCFunction)Sine_setPhase, METH_O, "Sets oscillator phase between 0 and 1."}, {"reset", (PyCFunction)Sine_reset, METH_NOARGS, "Resets pointer position to 0."}, {"setMul", (PyCFunction)Sine_setMul, METH_O, "Sets Sine mul factor."}, {"setAdd", (PyCFunction)Sine_setAdd, METH_O, "Sets Sine add factor."}, {"setSub", (PyCFunction)Sine_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Sine_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Sine_as_number = { (binaryfunc)Sine_add, /*nb_add*/ (binaryfunc)Sine_sub, /*nb_subtract*/ (binaryfunc)Sine_multiply, /*nb_multiply*/ (binaryfunc)Sine_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Sine_inplace_add, /*inplace_add*/ (binaryfunc)Sine_inplace_sub, /*inplace_subtract*/ (binaryfunc)Sine_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Sine_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SineType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Sine_base", /*tp_name*/ sizeof(Sine), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Sine_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Sine_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Sine objects. Generates a sinewave.", /* tp_doc */ (traverseproc)Sine_traverse, /* tp_traverse */ (inquiry)Sine_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Sine_methods, /* tp_methods */ Sine_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Sine_new, /* tp_new */ }; /*******************/ /* SineLoop object */ /*******************/ typedef struct { pyo_audio_HEAD PyObject *freq; Stream *freq_stream; PyObject *feedback; Stream *feedback_stream; int modebuffer[4]; MYFLT pointerPos; MYFLT lastValue; } SineLoop; static void SineLoop_readframes_ii(SineLoop *self) { MYFLT inc, fr, feed, pos, fpart; int i, ipart; fr = PyFloat_AS_DOUBLE(self->freq); feed = _clip(PyFloat_AS_DOUBLE(self->feedback)) * 512; inc = fr * 512 / self->sr; for (i=0; ibufsize; i++) { self->pointerPos = Sine_clip(self->pointerPos); pos = Sine_clip(self->pointerPos + self->lastValue * feed); ipart = (int)pos; fpart = pos - ipart; self->data[i] = self->lastValue = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos += inc; } } static void SineLoop_readframes_ai(SineLoop *self) { MYFLT inc, feed, pos, fpart, fac; int i, ipart; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); feed = _clip(PyFloat_AS_DOUBLE(self->feedback)) * 512; fac = 512 / self->sr; for (i=0; ibufsize; i++) { inc = fr[i] * fac; self->pointerPos = Sine_clip(self->pointerPos); pos = Sine_clip(self->pointerPos + self->lastValue * feed); ipart = (int)pos; fpart = pos - ipart; self->data[i] = self->lastValue = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos += inc; } } static void SineLoop_readframes_ia(SineLoop *self) { MYFLT inc, fr, feed, pos, fpart; int i, ipart; fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *fd = Stream_getData((Stream *)self->feedback_stream); inc = fr * 512 / self->sr; for (i=0; ibufsize; i++) { feed = _clip(fd[i]) * 512; self->pointerPos = Sine_clip(self->pointerPos); pos = Sine_clip(self->pointerPos + self->lastValue * feed); ipart = (int)pos; fpart = pos - ipart; self->data[i] = self->lastValue = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos += inc; } } static void SineLoop_readframes_aa(SineLoop *self) { MYFLT inc, feed, pos, fpart, fac; int i, ipart; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *fd = Stream_getData((Stream *)self->feedback_stream); fac = 512 / self->sr; for (i=0; ibufsize; i++) { inc = fr[i] * fac; feed = _clip(fd[i]) * 512; self->pointerPos = Sine_clip(self->pointerPos); pos = Sine_clip(self->pointerPos + self->lastValue * feed); ipart = (int)pos; fpart = pos - ipart; self->data[i] = self->lastValue = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos += inc; } } static void SineLoop_postprocessing_ii(SineLoop *self) { POST_PROCESSING_II }; static void SineLoop_postprocessing_ai(SineLoop *self) { POST_PROCESSING_AI }; static void SineLoop_postprocessing_ia(SineLoop *self) { POST_PROCESSING_IA }; static void SineLoop_postprocessing_aa(SineLoop *self) { POST_PROCESSING_AA }; static void SineLoop_postprocessing_ireva(SineLoop *self) { POST_PROCESSING_IREVA }; static void SineLoop_postprocessing_areva(SineLoop *self) { POST_PROCESSING_AREVA }; static void SineLoop_postprocessing_revai(SineLoop *self) { POST_PROCESSING_REVAI }; static void SineLoop_postprocessing_revaa(SineLoop *self) { POST_PROCESSING_REVAA }; static void SineLoop_postprocessing_revareva(SineLoop *self) { POST_PROCESSING_REVAREVA }; static void SineLoop_setProcMode(SineLoop *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = SineLoop_readframes_ii; break; case 1: self->proc_func_ptr = SineLoop_readframes_ai; break; case 10: self->proc_func_ptr = SineLoop_readframes_ia; break; case 11: self->proc_func_ptr = SineLoop_readframes_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = SineLoop_postprocessing_ii; break; case 1: self->muladd_func_ptr = SineLoop_postprocessing_ai; break; case 2: self->muladd_func_ptr = SineLoop_postprocessing_revai; break; case 10: self->muladd_func_ptr = SineLoop_postprocessing_ia; break; case 11: self->muladd_func_ptr = SineLoop_postprocessing_aa; break; case 12: self->muladd_func_ptr = SineLoop_postprocessing_revaa; break; case 20: self->muladd_func_ptr = SineLoop_postprocessing_ireva; break; case 21: self->muladd_func_ptr = SineLoop_postprocessing_areva; break; case 22: self->muladd_func_ptr = SineLoop_postprocessing_revareva; break; } } static void SineLoop_compute_next_data_frame(SineLoop *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int SineLoop_traverse(SineLoop *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->feedback); Py_VISIT(self->feedback_stream); return 0; } static int SineLoop_clear(SineLoop *self) { pyo_CLEAR Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->feedback); Py_CLEAR(self->feedback_stream); return 0; } static void SineLoop_dealloc(SineLoop* self) { pyo_DEALLOC SineLoop_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SineLoop_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *freqtmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL; SineLoop *self; self = (SineLoop *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->feedback = PyFloat_FromDouble(0.0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->pointerPos = self->lastValue = 0.; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, SineLoop_compute_next_data_frame); self->mode_func_ptr = SineLoop_setProcMode; static char *kwlist[] = {"freq", "feedback", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &feedbacktmp, &multmp, &addtmp)) Py_RETURN_NONE; if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (feedbacktmp) { PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * SineLoop_getServer(SineLoop* self) { GET_SERVER }; static PyObject * SineLoop_getStream(SineLoop* self) { GET_STREAM }; static PyObject * SineLoop_setMul(SineLoop *self, PyObject *arg) { SET_MUL }; static PyObject * SineLoop_setAdd(SineLoop *self, PyObject *arg) { SET_ADD }; static PyObject * SineLoop_setSub(SineLoop *self, PyObject *arg) { SET_SUB }; static PyObject * SineLoop_setDiv(SineLoop *self, PyObject *arg) { SET_DIV }; static PyObject * SineLoop_play(SineLoop *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SineLoop_out(SineLoop *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * SineLoop_stop(SineLoop *self) { STOP }; static PyObject * SineLoop_multiply(SineLoop *self, PyObject *arg) { MULTIPLY }; static PyObject * SineLoop_inplace_multiply(SineLoop *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * SineLoop_add(SineLoop *self, PyObject *arg) { ADD }; static PyObject * SineLoop_inplace_add(SineLoop *self, PyObject *arg) { INPLACE_ADD }; static PyObject * SineLoop_sub(SineLoop *self, PyObject *arg) { SUB }; static PyObject * SineLoop_inplace_sub(SineLoop *self, PyObject *arg) { INPLACE_SUB }; static PyObject * SineLoop_div(SineLoop *self, PyObject *arg) { DIV }; static PyObject * SineLoop_inplace_div(SineLoop *self, PyObject *arg) { INPLACE_DIV }; static PyObject * SineLoop_setFreq(SineLoop *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SineLoop_setFeedback(SineLoop *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->feedback); if (isNumber == 1) { self->feedback = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->feedback = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->feedback_stream); self->feedback_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef SineLoop_members[] = { {"server", T_OBJECT_EX, offsetof(SineLoop, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SineLoop, stream), 0, "Stream object."}, {"freq", T_OBJECT_EX, offsetof(SineLoop, freq), 0, "Frequency in cycle per second."}, {"feedback", T_OBJECT_EX, offsetof(SineLoop, feedback), 0, "Phase of signal (0 -> 1)"}, {"mul", T_OBJECT_EX, offsetof(SineLoop, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(SineLoop, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef SineLoop_methods[] = { {"getServer", (PyCFunction)SineLoop_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SineLoop_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SineLoop_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)SineLoop_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)SineLoop_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)SineLoop_setFreq, METH_O, "Sets oscillator frequency in cycle per second."}, {"setFeedback", (PyCFunction)SineLoop_setFeedback, METH_O, "Sets oscillator feedback between 0 and 1."}, {"setMul", (PyCFunction)SineLoop_setMul, METH_O, "Sets SineLoop mul factor."}, {"setAdd", (PyCFunction)SineLoop_setAdd, METH_O, "Sets SineLoop add factor."}, {"setSub", (PyCFunction)SineLoop_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)SineLoop_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods SineLoop_as_number = { (binaryfunc)SineLoop_add, /*nb_add*/ (binaryfunc)SineLoop_sub, /*nb_subtract*/ (binaryfunc)SineLoop_multiply, /*nb_multiply*/ (binaryfunc)SineLoop_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)SineLoop_inplace_add, /*inplace_add*/ (binaryfunc)SineLoop_inplace_sub, /*inplace_subtract*/ (binaryfunc)SineLoop_inplace_multiply, /*inplace_multiply*/ (binaryfunc)SineLoop_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SineLoopType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SineLoop_base", /*tp_name*/ sizeof(SineLoop), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SineLoop_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &SineLoop_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SineLoop objects. Generates a looped sinewave.", /* tp_doc */ (traverseproc)SineLoop_traverse, /* tp_traverse */ (inquiry)SineLoop_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SineLoop_methods, /* tp_methods */ SineLoop_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SineLoop_new, /* tp_new */ }; /***************/ /* Osc objects */ /***************/ static double Osc_clip(double x, int size) { if (x < 0) { x += ((int)(-x / size) + 1) * size; } else if (x >= size) { x -= (int)(x / size) * size; } return x; } typedef struct { pyo_audio_HEAD PyObject *table; PyObject *freq; Stream *freq_stream; PyObject *phase; Stream *phase_stream; int modebuffer[4]; double pointerPos; int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */ MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int); } Osc; static void Osc_readframes_ii(Osc *self) { MYFLT fr, ph, fpart; double inc, pos; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); fr = PyFloat_AS_DOUBLE(self->freq); ph = PyFloat_AS_DOUBLE(self->phase); inc = fr * size / self->sr; ph *= size; for (i=0; ibufsize; i++) { self->pointerPos += inc; self->pointerPos = Osc_clip(self->pointerPos, size); pos = self->pointerPos + ph; if (pos >= size) pos -= size; ipart = (int)pos; fpart = pos - ipart; self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); } } static void Osc_readframes_ai(Osc *self) { MYFLT ph, fpart, sizeOnSr; double inc, pos; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); ph = PyFloat_AS_DOUBLE(self->phase); ph *= size; sizeOnSr = size / self->sr; for (i=0; ibufsize; i++) { inc = fr[i] * sizeOnSr; self->pointerPos += inc; self->pointerPos = Osc_clip(self->pointerPos, size); pos = self->pointerPos + ph; if (pos >= size) pos -= size; ipart = (int)pos; fpart = pos - ipart; self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); } } static void Osc_readframes_ia(Osc *self) { MYFLT fr, pha, fpart; double inc, pos; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *ph = Stream_getData((Stream *)self->phase_stream); inc = fr * size / self->sr; for (i=0; ibufsize; i++) { pha = ph[i] * size; self->pointerPos += inc; self->pointerPos = Osc_clip(self->pointerPos, size); pos = self->pointerPos + pha; if (pos >= size) pos -= size; ipart = (int)pos; fpart = pos - ipart; self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); } } static void Osc_readframes_aa(Osc *self) { MYFLT pha, fpart, sizeOnSr; double inc, pos; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *ph = Stream_getData((Stream *)self->phase_stream); sizeOnSr = size / self->sr; for (i=0; ibufsize; i++) { inc = fr[i] * sizeOnSr; pha = ph[i] * size; self->pointerPos += inc; self->pointerPos = Osc_clip(self->pointerPos, size); pos = self->pointerPos + pha; if (pos >= size) pos -= size; ipart = (int)pos; fpart = pos - ipart; self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); } } static void Osc_postprocessing_ii(Osc *self) { POST_PROCESSING_II }; static void Osc_postprocessing_ai(Osc *self) { POST_PROCESSING_AI }; static void Osc_postprocessing_ia(Osc *self) { POST_PROCESSING_IA }; static void Osc_postprocessing_aa(Osc *self) { POST_PROCESSING_AA }; static void Osc_postprocessing_ireva(Osc *self) { POST_PROCESSING_IREVA }; static void Osc_postprocessing_areva(Osc *self) { POST_PROCESSING_AREVA }; static void Osc_postprocessing_revai(Osc *self) { POST_PROCESSING_REVAI }; static void Osc_postprocessing_revaa(Osc *self) { POST_PROCESSING_REVAA }; static void Osc_postprocessing_revareva(Osc *self) { POST_PROCESSING_REVAREVA }; static void Osc_setProcMode(Osc *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Osc_readframes_ii; break; case 1: self->proc_func_ptr = Osc_readframes_ai; break; case 10: self->proc_func_ptr = Osc_readframes_ia; break; case 11: self->proc_func_ptr = Osc_readframes_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Osc_postprocessing_ii; break; case 1: self->muladd_func_ptr = Osc_postprocessing_ai; break; case 2: self->muladd_func_ptr = Osc_postprocessing_revai; break; case 10: self->muladd_func_ptr = Osc_postprocessing_ia; break; case 11: self->muladd_func_ptr = Osc_postprocessing_aa; break; case 12: self->muladd_func_ptr = Osc_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Osc_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Osc_postprocessing_areva; break; case 22: self->muladd_func_ptr = Osc_postprocessing_revareva; break; } } static void Osc_compute_next_data_frame(Osc *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Osc_traverse(Osc *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->phase); Py_VISIT(self->phase_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); return 0; } static int Osc_clear(Osc *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->phase); Py_CLEAR(self->phase_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); return 0; } static void Osc_dealloc(Osc* self) { pyo_DEALLOC Osc_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Osc_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *tabletmp, *freqtmp=NULL, *phasetmp=NULL, *multmp=NULL, *addtmp=NULL; Osc *self; self = (Osc *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->phase = PyFloat_FromDouble(0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->pointerPos = 0.; self->interp = 2; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Osc_compute_next_data_frame); self->mode_func_ptr = Osc_setProcMode; static char *kwlist[] = {"table", "freq", "phase", "interp", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOiOO", kwlist, &tabletmp, &freqtmp, &phasetmp, &self->interp, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of Osc must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if (phasetmp) { PyObject_CallMethod((PyObject *)self, "setPhase", "O", phasetmp); } if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); SET_INTERP_POINTER return (PyObject *)self; } static PyObject * Osc_getServer(Osc* self) { GET_SERVER }; static PyObject * Osc_getStream(Osc* self) { GET_STREAM }; static PyObject * Osc_setMul(Osc *self, PyObject *arg) { SET_MUL }; static PyObject * Osc_setAdd(Osc *self, PyObject *arg) { SET_ADD }; static PyObject * Osc_setSub(Osc *self, PyObject *arg) { SET_SUB }; static PyObject * Osc_setDiv(Osc *self, PyObject *arg) { SET_DIV }; static PyObject * Osc_play(Osc *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Osc_out(Osc *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Osc_stop(Osc *self) { STOP }; static PyObject * Osc_multiply(Osc *self, PyObject *arg) { MULTIPLY }; static PyObject * Osc_inplace_multiply(Osc *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Osc_add(Osc *self, PyObject *arg) { ADD }; static PyObject * Osc_inplace_add(Osc *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Osc_sub(Osc *self, PyObject *arg) { SUB }; static PyObject * Osc_inplace_sub(Osc *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Osc_div(Osc *self, PyObject *arg) { DIV }; static PyObject * Osc_inplace_div(Osc *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Osc_getTable(Osc* self) { Py_INCREF(self->table); return self->table; }; static PyObject * Osc_setTable(Osc *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * Osc_setFreq(Osc *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Osc_setPhase(Osc *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->phase); if (isNumber == 1) { self->phase = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->phase = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->phase, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->phase_stream); self->phase_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Osc_setInterp(Osc *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->interp = PyInt_AsLong(PyNumber_Int(arg)); } SET_INTERP_POINTER Py_INCREF(Py_None); return Py_None; } static PyObject * Osc_reset(Osc *self) { self->pointerPos = 0.0; Py_INCREF(Py_None); return Py_None; } static PyMemberDef Osc_members[] = { {"server", T_OBJECT_EX, offsetof(Osc, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Osc, stream), 0, "Stream object."}, {"table", T_OBJECT_EX, offsetof(Osc, table), 0, "Waveform table."}, {"freq", T_OBJECT_EX, offsetof(Osc, freq), 0, "Frequency in cycle per second."}, {"phase", T_OBJECT_EX, offsetof(Osc, phase), 0, "Oscillator phase."}, {"mul", T_OBJECT_EX, offsetof(Osc, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Osc, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Osc_methods[] = { {"getTable", (PyCFunction)Osc_getTable, METH_NOARGS, "Returns waveform table object."}, {"getServer", (PyCFunction)Osc_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Osc_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Osc_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Osc_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Osc_stop, METH_NOARGS, "Stops computing."}, {"setTable", (PyCFunction)Osc_setTable, METH_O, "Sets oscillator table."}, {"setFreq", (PyCFunction)Osc_setFreq, METH_O, "Sets oscillator frequency in cycle per second."}, {"setPhase", (PyCFunction)Osc_setPhase, METH_O, "Sets oscillator phase."}, {"setInterp", (PyCFunction)Osc_setInterp, METH_O, "Sets oscillator interpolation mode."}, {"reset", (PyCFunction)Osc_reset, METH_NOARGS, "Resets pointer position to 0."}, {"setMul", (PyCFunction)Osc_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Osc_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Osc_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)Osc_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Osc_as_number = { (binaryfunc)Osc_add, /*nb_add*/ (binaryfunc)Osc_sub, /*nb_subtract*/ (binaryfunc)Osc_multiply, /*nb_multiply*/ (binaryfunc)Osc_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Osc_inplace_add, /*inplace_add*/ (binaryfunc)Osc_inplace_sub, /*inplace_subtract*/ (binaryfunc)Osc_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Osc_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject OscType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Osc_base", /*tp_name*/ sizeof(Osc), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Osc_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Osc_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Osc objects. Generates an oscillatory waveform.", /* tp_doc */ (traverseproc)Osc_traverse, /* tp_traverse */ (inquiry)Osc_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Osc_methods, /* tp_methods */ Osc_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Osc_new, /* tp_new */ }; /**************/ /* OscLoop object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *table; PyObject *freq; Stream *freq_stream; PyObject *feedback; Stream *feedback_stream; int modebuffer[4]; double pointerPos; MYFLT lastValue; } OscLoop; static void OscLoop_readframes_ii(OscLoop *self) { MYFLT fr, feed, pos, inc, fpart; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); fr = PyFloat_AS_DOUBLE(self->freq); feed = _clip(PyFloat_AS_DOUBLE(self->feedback)) * size; inc = fr * size / self->sr; for (i=0; ibufsize; i++) { self->pointerPos += inc; self->pointerPos = Osc_clip(self->pointerPos, size); pos = self->pointerPos + (self->lastValue * feed); if (pos >= size) pos -= size; else if (pos < 0) pos += size; ipart = (int)pos; fpart = pos - ipart; self->data[i] = self->lastValue = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart; } } static void OscLoop_readframes_ai(OscLoop *self) { MYFLT inc, feed, pos, fpart, sizeOnSr; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); feed = _clip(PyFloat_AS_DOUBLE(self->feedback)) * size; sizeOnSr = size / self->sr; for (i=0; ibufsize; i++) { inc = fr[i] * sizeOnSr; self->pointerPos += inc; self->pointerPos = Osc_clip(self->pointerPos, size); pos = self->pointerPos + (self->lastValue * feed); if (pos >= size) pos -= size; else if (pos < 0) pos += size; ipart = (int)pos; fpart = pos - ipart; self->data[i] = self->lastValue = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart; } } static void OscLoop_readframes_ia(OscLoop *self) { MYFLT fr, feed, pos, inc, fpart; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *fd = Stream_getData((Stream *)self->feedback_stream); inc = fr * size / self->sr; for (i=0; ibufsize; i++) { feed = _clip(fd[i]) * size; self->pointerPos += inc; self->pointerPos = Osc_clip(self->pointerPos, size); pos = self->pointerPos + (self->lastValue * feed); if (pos >= size) pos -= size; else if (pos < 0) pos += size; ipart = (int)pos; fpart = pos - ipart; self->data[i] = self->lastValue = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart; } } static void OscLoop_readframes_aa(OscLoop *self) { MYFLT inc, feed, pos, fpart, sizeOnSr; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *fd = Stream_getData((Stream *)self->feedback_stream); sizeOnSr = size / self->sr; for (i=0; ibufsize; i++) { inc = fr[i] * sizeOnSr; feed = _clip(fd[i]) * size; self->pointerPos += inc; self->pointerPos = Osc_clip(self->pointerPos, size); pos = self->pointerPos + (self->lastValue * feed); if (pos >= size) pos -= size; else if (pos < 0) pos += size; ipart = (int)pos; fpart = pos - ipart; self->data[i] = self->lastValue = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart; } } static void OscLoop_postprocessing_ii(OscLoop *self) { POST_PROCESSING_II }; static void OscLoop_postprocessing_ai(OscLoop *self) { POST_PROCESSING_AI }; static void OscLoop_postprocessing_ia(OscLoop *self) { POST_PROCESSING_IA }; static void OscLoop_postprocessing_aa(OscLoop *self) { POST_PROCESSING_AA }; static void OscLoop_postprocessing_ireva(OscLoop *self) { POST_PROCESSING_IREVA }; static void OscLoop_postprocessing_areva(OscLoop *self) { POST_PROCESSING_AREVA }; static void OscLoop_postprocessing_revai(OscLoop *self) { POST_PROCESSING_REVAI }; static void OscLoop_postprocessing_revaa(OscLoop *self) { POST_PROCESSING_REVAA }; static void OscLoop_postprocessing_revareva(OscLoop *self) { POST_PROCESSING_REVAREVA }; static void OscLoop_setProcMode(OscLoop *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = OscLoop_readframes_ii; break; case 1: self->proc_func_ptr = OscLoop_readframes_ai; break; case 10: self->proc_func_ptr = OscLoop_readframes_ia; break; case 11: self->proc_func_ptr = OscLoop_readframes_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = OscLoop_postprocessing_ii; break; case 1: self->muladd_func_ptr = OscLoop_postprocessing_ai; break; case 2: self->muladd_func_ptr = OscLoop_postprocessing_revai; break; case 10: self->muladd_func_ptr = OscLoop_postprocessing_ia; break; case 11: self->muladd_func_ptr = OscLoop_postprocessing_aa; break; case 12: self->muladd_func_ptr = OscLoop_postprocessing_revaa; break; case 20: self->muladd_func_ptr = OscLoop_postprocessing_ireva; break; case 21: self->muladd_func_ptr = OscLoop_postprocessing_areva; break; case 22: self->muladd_func_ptr = OscLoop_postprocessing_revareva; break; } } static void OscLoop_compute_next_data_frame(OscLoop *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int OscLoop_traverse(OscLoop *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->feedback); Py_VISIT(self->feedback_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); return 0; } static int OscLoop_clear(OscLoop *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->feedback); Py_CLEAR(self->feedback_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); return 0; } static void OscLoop_dealloc(OscLoop* self) { pyo_DEALLOC OscLoop_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * OscLoop_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *tabletmp, *freqtmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL; OscLoop *self; self = (OscLoop *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->feedback = PyFloat_FromDouble(0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->pointerPos = self->lastValue = 0.; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, OscLoop_compute_next_data_frame); self->mode_func_ptr = OscLoop_setProcMode; static char *kwlist[] = {"table", "freq", "feedback", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &tabletmp, &freqtmp, &feedbacktmp, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of OscLoop must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if (feedbacktmp) { PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp); } if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * OscLoop_getServer(OscLoop* self) { GET_SERVER }; static PyObject * OscLoop_getStream(OscLoop* self) { GET_STREAM }; static PyObject * OscLoop_setMul(OscLoop *self, PyObject *arg) { SET_MUL }; static PyObject * OscLoop_setAdd(OscLoop *self, PyObject *arg) { SET_ADD }; static PyObject * OscLoop_setSub(OscLoop *self, PyObject *arg) { SET_SUB }; static PyObject * OscLoop_setDiv(OscLoop *self, PyObject *arg) { SET_DIV }; static PyObject * OscLoop_play(OscLoop *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * OscLoop_out(OscLoop *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * OscLoop_stop(OscLoop *self) { STOP }; static PyObject * OscLoop_multiply(OscLoop *self, PyObject *arg) { MULTIPLY }; static PyObject * OscLoop_inplace_multiply(OscLoop *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * OscLoop_add(OscLoop *self, PyObject *arg) { ADD }; static PyObject * OscLoop_inplace_add(OscLoop *self, PyObject *arg) { INPLACE_ADD }; static PyObject * OscLoop_sub(OscLoop *self, PyObject *arg) { SUB }; static PyObject * OscLoop_inplace_sub(OscLoop *self, PyObject *arg) { INPLACE_SUB }; static PyObject * OscLoop_div(OscLoop *self, PyObject *arg) { DIV }; static PyObject * OscLoop_inplace_div(OscLoop *self, PyObject *arg) { INPLACE_DIV }; static PyObject * OscLoop_getTable(OscLoop* self) { Py_INCREF(self->table); return self->table; }; static PyObject * OscLoop_setTable(OscLoop *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * OscLoop_setFreq(OscLoop *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * OscLoop_setFeedback(OscLoop *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->feedback); if (isNumber == 1) { self->feedback = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->feedback = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->feedback_stream); self->feedback_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef OscLoop_members[] = { {"server", T_OBJECT_EX, offsetof(OscLoop, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(OscLoop, stream), 0, "Stream object."}, {"table", T_OBJECT_EX, offsetof(OscLoop, table), 0, "Waveform table."}, {"freq", T_OBJECT_EX, offsetof(OscLoop, freq), 0, "Frequency in cycle per second."}, {"feedback", T_OBJECT_EX, offsetof(OscLoop, feedback), 0, "Oscillator feedback."}, {"mul", T_OBJECT_EX, offsetof(OscLoop, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(OscLoop, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef OscLoop_methods[] = { {"getTable", (PyCFunction)OscLoop_getTable, METH_NOARGS, "Returns waveform table object."}, {"getServer", (PyCFunction)OscLoop_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)OscLoop_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)OscLoop_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)OscLoop_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)OscLoop_stop, METH_NOARGS, "Stops computing."}, {"setTable", (PyCFunction)OscLoop_setTable, METH_O, "Sets oscillator table."}, {"setFreq", (PyCFunction)OscLoop_setFreq, METH_O, "Sets oscillator frequency in cycle per second."}, {"setFeedback", (PyCFunction)OscLoop_setFeedback, METH_O, "Sets oscillator feedback."}, {"setMul", (PyCFunction)OscLoop_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)OscLoop_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)OscLoop_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)OscLoop_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods OscLoop_as_number = { (binaryfunc)OscLoop_add, /*nb_add*/ (binaryfunc)OscLoop_sub, /*nb_subtract*/ (binaryfunc)OscLoop_multiply, /*nb_multiply*/ (binaryfunc)OscLoop_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)OscLoop_inplace_add, /*inplace_add*/ (binaryfunc)OscLoop_inplace_sub, /*inplace_subtract*/ (binaryfunc)OscLoop_inplace_multiply, /*inplace_multiply*/ (binaryfunc)OscLoop_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject OscLoopType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.OscLoop_base", /*tp_name*/ sizeof(OscLoop), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)OscLoop_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &OscLoop_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "OscLoop objects. Generates an oscillatory waveform.", /* tp_doc */ (traverseproc)OscLoop_traverse, /* tp_traverse */ (inquiry)OscLoop_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ OscLoop_methods, /* tp_methods */ OscLoop_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ OscLoop_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *table; PyObject *freq; Stream *freq_stream; PyObject *phase; Stream *phase_stream; PyObject *trig; Stream *trig_stream; int modebuffer[4]; double pointerPos; int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */ MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int); } OscTrig; static void OscTrig_readframes_ii(OscTrig *self) { MYFLT fr, ph, fpart; double inc, pos; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); fr = PyFloat_AS_DOUBLE(self->freq); ph = PyFloat_AS_DOUBLE(self->phase); MYFLT *tr = Stream_getData((Stream *)self->trig_stream); inc = fr * size / self->sr; ph *= size; for (i=0; ibufsize; i++) { if (tr[i] == 1) self->pointerPos = 0.0; else { self->pointerPos += inc; self->pointerPos = Osc_clip(self->pointerPos, size); } pos = self->pointerPos + ph; if (pos >= size) pos -= size; ipart = (int)pos; fpart = pos - ipart; self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); } } static void OscTrig_readframes_ai(OscTrig *self) { MYFLT ph, fpart, sizeOnSr; double inc, pos; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); ph = PyFloat_AS_DOUBLE(self->phase); MYFLT *tr = Stream_getData((Stream *)self->trig_stream); ph *= size; sizeOnSr = size / self->sr; for (i=0; ibufsize; i++) { inc = fr[i] * sizeOnSr; if (tr[i] == 1) self->pointerPos = 0.0; else { self->pointerPos += inc; self->pointerPos = Osc_clip(self->pointerPos, size); } pos = self->pointerPos + ph; if (pos >= size) pos -= size; ipart = (int)pos; fpart = pos - ipart; self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); } } static void OscTrig_readframes_ia(OscTrig *self) { MYFLT fr, pha, fpart; double inc, pos; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *ph = Stream_getData((Stream *)self->phase_stream); MYFLT *tr = Stream_getData((Stream *)self->trig_stream); inc = fr * size / self->sr; for (i=0; ibufsize; i++) { pha = ph[i] * size; if (tr[i] == 1) self->pointerPos = 0.0; else { self->pointerPos += inc; self->pointerPos = Osc_clip(self->pointerPos, size); } pos = self->pointerPos + pha; if (pos >= size) pos -= size; ipart = (int)pos; fpart = pos - ipart; self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); } } static void OscTrig_readframes_aa(OscTrig *self) { MYFLT pha, fpart, sizeOnSr; double inc, pos; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *ph = Stream_getData((Stream *)self->phase_stream); MYFLT *tr = Stream_getData((Stream *)self->trig_stream); sizeOnSr = size / self->sr; for (i=0; ibufsize; i++) { inc = fr[i] * sizeOnSr; pha = ph[i] * size; if (tr[i] == 1) self->pointerPos = 0.0; else { self->pointerPos += inc; self->pointerPos = Osc_clip(self->pointerPos, size); } pos = self->pointerPos + pha; if (pos >= size) pos -= size; ipart = (int)pos; fpart = pos - ipart; self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); } } static void OscTrig_postprocessing_ii(OscTrig *self) { POST_PROCESSING_II }; static void OscTrig_postprocessing_ai(OscTrig *self) { POST_PROCESSING_AI }; static void OscTrig_postprocessing_ia(OscTrig *self) { POST_PROCESSING_IA }; static void OscTrig_postprocessing_aa(OscTrig *self) { POST_PROCESSING_AA }; static void OscTrig_postprocessing_ireva(OscTrig *self) { POST_PROCESSING_IREVA }; static void OscTrig_postprocessing_areva(OscTrig *self) { POST_PROCESSING_AREVA }; static void OscTrig_postprocessing_revai(OscTrig *self) { POST_PROCESSING_REVAI }; static void OscTrig_postprocessing_revaa(OscTrig *self) { POST_PROCESSING_REVAA }; static void OscTrig_postprocessing_revareva(OscTrig *self) { POST_PROCESSING_REVAREVA }; static void OscTrig_setProcMode(OscTrig *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = OscTrig_readframes_ii; break; case 1: self->proc_func_ptr = OscTrig_readframes_ai; break; case 10: self->proc_func_ptr = OscTrig_readframes_ia; break; case 11: self->proc_func_ptr = OscTrig_readframes_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = OscTrig_postprocessing_ii; break; case 1: self->muladd_func_ptr = OscTrig_postprocessing_ai; break; case 2: self->muladd_func_ptr = OscTrig_postprocessing_revai; break; case 10: self->muladd_func_ptr = OscTrig_postprocessing_ia; break; case 11: self->muladd_func_ptr = OscTrig_postprocessing_aa; break; case 12: self->muladd_func_ptr = OscTrig_postprocessing_revaa; break; case 20: self->muladd_func_ptr = OscTrig_postprocessing_ireva; break; case 21: self->muladd_func_ptr = OscTrig_postprocessing_areva; break; case 22: self->muladd_func_ptr = OscTrig_postprocessing_revareva; break; } } static void OscTrig_compute_next_data_frame(OscTrig *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int OscTrig_traverse(OscTrig *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->phase); Py_VISIT(self->phase_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->trig); Py_VISIT(self->trig_stream); return 0; } static int OscTrig_clear(OscTrig *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->phase); Py_CLEAR(self->phase_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->trig); Py_CLEAR(self->trig_stream); return 0; } static void OscTrig_dealloc(OscTrig* self) { pyo_DEALLOC OscTrig_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * OscTrig_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *tabletmp, *trigtmp, *freqtmp=NULL, *phasetmp=NULL, *multmp=NULL, *addtmp=NULL; OscTrig *self; self = (OscTrig *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1000); self->phase = PyFloat_FromDouble(0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->pointerPos = 0.; self->interp = 2; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, OscTrig_compute_next_data_frame); self->mode_func_ptr = OscTrig_setProcMode; static char *kwlist[] = {"table", "trig", "freq", "phase", "interp", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOiOO", kwlist, &tabletmp, &trigtmp, &freqtmp, &phasetmp, &self->interp, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of OscTrig must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if (trigtmp) { PyObject_CallMethod((PyObject *)self, "setTrig", "O", trigtmp); } if (phasetmp) { PyObject_CallMethod((PyObject *)self, "setPhase", "O", phasetmp); } if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); SET_INTERP_POINTER return (PyObject *)self; } static PyObject * OscTrig_getServer(OscTrig* self) { GET_SERVER }; static PyObject * OscTrig_getStream(OscTrig* self) { GET_STREAM }; static PyObject * OscTrig_setMul(OscTrig *self, PyObject *arg) { SET_MUL }; static PyObject * OscTrig_setAdd(OscTrig *self, PyObject *arg) { SET_ADD }; static PyObject * OscTrig_setSub(OscTrig *self, PyObject *arg) { SET_SUB }; static PyObject * OscTrig_setDiv(OscTrig *self, PyObject *arg) { SET_DIV }; static PyObject * OscTrig_play(OscTrig *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * OscTrig_out(OscTrig *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * OscTrig_stop(OscTrig *self) { STOP }; static PyObject * OscTrig_multiply(OscTrig *self, PyObject *arg) { MULTIPLY }; static PyObject * OscTrig_inplace_multiply(OscTrig *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * OscTrig_add(OscTrig *self, PyObject *arg) { ADD }; static PyObject * OscTrig_inplace_add(OscTrig *self, PyObject *arg) { INPLACE_ADD }; static PyObject * OscTrig_sub(OscTrig *self, PyObject *arg) { SUB }; static PyObject * OscTrig_inplace_sub(OscTrig *self, PyObject *arg) { INPLACE_SUB }; static PyObject * OscTrig_div(OscTrig *self, PyObject *arg) { DIV }; static PyObject * OscTrig_inplace_div(OscTrig *self, PyObject *arg) { INPLACE_DIV }; static PyObject * OscTrig_getTable(OscTrig* self) { Py_INCREF(self->table); return self->table; }; static PyObject * OscTrig_setTable(OscTrig *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * OscTrig_setTrig(OscTrig *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_XDECREF(self->trig); if (isNumber == 1) { Py_INCREF(Py_None); return Py_None; } else { self->trig = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->trig, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->trig_stream); self->trig_stream = (Stream *)streamtmp; } Py_INCREF(Py_None); return Py_None; } static PyObject * OscTrig_setFreq(OscTrig *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * OscTrig_setPhase(OscTrig *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->phase); if (isNumber == 1) { self->phase = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->phase = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->phase, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->phase_stream); self->phase_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * OscTrig_setInterp(OscTrig *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->interp = PyInt_AsLong(PyNumber_Int(arg)); } SET_INTERP_POINTER Py_INCREF(Py_None); return Py_None; } static PyObject * OscTrig_reset(OscTrig *self) { self->pointerPos = 0.0; Py_INCREF(Py_None); return Py_None; } static PyMemberDef OscTrig_members[] = { {"server", T_OBJECT_EX, offsetof(OscTrig, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(OscTrig, stream), 0, "Stream object."}, {"table", T_OBJECT_EX, offsetof(OscTrig, table), 0, "Waveform table."}, {"trig", T_OBJECT_EX, offsetof(OscTrig, trig), 0, "Trigger signal."}, {"freq", T_OBJECT_EX, offsetof(OscTrig, freq), 0, "Frequency in cycle per second."}, {"phase", T_OBJECT_EX, offsetof(OscTrig, phase), 0, "OscTrigillator phase."}, {"mul", T_OBJECT_EX, offsetof(OscTrig, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(OscTrig, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef OscTrig_methods[] = { {"getTable", (PyCFunction)OscTrig_getTable, METH_NOARGS, "Returns waveform table object."}, {"getServer", (PyCFunction)OscTrig_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)OscTrig_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)OscTrig_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)OscTrig_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)OscTrig_stop, METH_NOARGS, "Stops computing."}, {"setTable", (PyCFunction)OscTrig_setTable, METH_O, "Sets oscillator table."}, {"setTrig", (PyCFunction)OscTrig_setTrig, METH_O, "Sets the reset trigger signal."}, {"setFreq", (PyCFunction)OscTrig_setFreq, METH_O, "Sets oscillator frequency in cycle per second."}, {"setPhase", (PyCFunction)OscTrig_setPhase, METH_O, "Sets oscillator phase."}, {"setInterp", (PyCFunction)OscTrig_setInterp, METH_O, "Sets oscillator interpolation mode."}, {"reset", (PyCFunction)OscTrig_reset, METH_NOARGS, "Resets pointer position to 0."}, {"setMul", (PyCFunction)OscTrig_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)OscTrig_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)OscTrig_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)OscTrig_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods OscTrig_as_number = { (binaryfunc)OscTrig_add, /*nb_add*/ (binaryfunc)OscTrig_sub, /*nb_subtract*/ (binaryfunc)OscTrig_multiply, /*nb_multiply*/ (binaryfunc)OscTrig_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)OscTrig_inplace_add, /*inplace_add*/ (binaryfunc)OscTrig_inplace_sub, /*inplace_subtract*/ (binaryfunc)OscTrig_inplace_multiply, /*inplace_multiply*/ (binaryfunc)OscTrig_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject OscTrigType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.OscTrig_base", /*tp_name*/ sizeof(OscTrig), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)OscTrig_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &OscTrig_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "OscTrig objects. Generates an oscillatory waveform with sample accurate reset signal.", /* tp_doc */ (traverseproc)OscTrig_traverse, /* tp_traverse */ (inquiry)OscTrig_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ OscTrig_methods, /* tp_methods */ OscTrig_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ OscTrig_new, /* tp_new */ }; /**************/ /* Phasor object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *freq; Stream *freq_stream; PyObject *phase; Stream *phase_stream; int modebuffer[4]; double pointerPos; } Phasor; static void Phasor_readframes_ii(Phasor *self) { MYFLT fr, ph; double inc, pos; int i; fr = PyFloat_AS_DOUBLE(self->freq); ph = _clip(PyFloat_AS_DOUBLE(self->phase)); inc = fr / self->sr; for (i=0; ibufsize; i++) { pos = self->pointerPos + ph; if (pos > 1) pos -= 1.0; self->data[i] = pos; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } } static void Phasor_readframes_ai(Phasor *self) { MYFLT ph, oneOnSr; double inc, pos; int i; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); ph = _clip(PyFloat_AS_DOUBLE(self->phase)); oneOnSr = 1.0 / self->sr; for (i=0; ibufsize; i++) { pos = self->pointerPos + ph; if (pos > 1) pos -= 1.0; self->data[i] = pos; inc = fr[i] * oneOnSr; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } } static void Phasor_readframes_ia(Phasor *self) { MYFLT fr, pha; double inc, pos; int i; fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *ph = Stream_getData((Stream *)self->phase_stream); inc = fr / self->sr; for (i=0; ibufsize; i++) { pha = _clip(ph[i]); pos = self->pointerPos + pha; if (pos > 1) pos -= 1.0; self->data[i] = pos; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } } static void Phasor_readframes_aa(Phasor *self) { MYFLT pha, oneOnSr; double inc, pos; int i; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *ph = Stream_getData((Stream *)self->phase_stream); oneOnSr = 1.0 / self->sr; for (i=0; ibufsize; i++) { pha = _clip(ph[i]); pos = self->pointerPos + pha; if (pos > 1) pos -= 1.0; self->data[i] = pos; inc = fr[i] * oneOnSr; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } } static void Phasor_postprocessing_ii(Phasor *self) { POST_PROCESSING_II }; static void Phasor_postprocessing_ai(Phasor *self) { POST_PROCESSING_AI }; static void Phasor_postprocessing_ia(Phasor *self) { POST_PROCESSING_IA }; static void Phasor_postprocessing_aa(Phasor *self) { POST_PROCESSING_AA }; static void Phasor_postprocessing_ireva(Phasor *self) { POST_PROCESSING_IREVA }; static void Phasor_postprocessing_areva(Phasor *self) { POST_PROCESSING_AREVA }; static void Phasor_postprocessing_revai(Phasor *self) { POST_PROCESSING_REVAI }; static void Phasor_postprocessing_revaa(Phasor *self) { POST_PROCESSING_REVAA }; static void Phasor_postprocessing_revareva(Phasor *self) { POST_PROCESSING_REVAREVA }; static void Phasor_setProcMode(Phasor *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Phasor_readframes_ii; break; case 1: self->proc_func_ptr = Phasor_readframes_ai; break; case 10: self->proc_func_ptr = Phasor_readframes_ia; break; case 11: self->proc_func_ptr = Phasor_readframes_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Phasor_postprocessing_ii; break; case 1: self->muladd_func_ptr = Phasor_postprocessing_ai; break; case 2: self->muladd_func_ptr = Phasor_postprocessing_revai; break; case 10: self->muladd_func_ptr = Phasor_postprocessing_ia; break; case 11: self->muladd_func_ptr = Phasor_postprocessing_aa; break; case 12: self->muladd_func_ptr = Phasor_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Phasor_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Phasor_postprocessing_areva; break; case 22: self->muladd_func_ptr = Phasor_postprocessing_revareva; break; } } static void Phasor_compute_next_data_frame(Phasor *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Phasor_traverse(Phasor *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->phase); Py_VISIT(self->phase_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); return 0; } static int Phasor_clear(Phasor *self) { pyo_CLEAR Py_CLEAR(self->phase); Py_CLEAR(self->phase_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); return 0; } static void Phasor_dealloc(Phasor* self) { pyo_DEALLOC Phasor_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Phasor_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *freqtmp=NULL, *phasetmp=NULL, *multmp=NULL, *addtmp=NULL; Phasor *self; self = (Phasor *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(100); self->phase = PyFloat_FromDouble(0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->pointerPos = 0.; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Phasor_compute_next_data_frame); self->mode_func_ptr = Phasor_setProcMode; static char *kwlist[] = {"freq", "phase", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &phasetmp, &multmp, &addtmp)) Py_RETURN_NONE; if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (phasetmp) { PyObject_CallMethod((PyObject *)self, "setPhase", "O", phasetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Phasor_getServer(Phasor* self) { GET_SERVER }; static PyObject * Phasor_getStream(Phasor* self) { GET_STREAM }; static PyObject * Phasor_setMul(Phasor *self, PyObject *arg) { SET_MUL }; static PyObject * Phasor_setAdd(Phasor *self, PyObject *arg) { SET_ADD }; static PyObject * Phasor_setSub(Phasor *self, PyObject *arg) { SET_SUB }; static PyObject * Phasor_setDiv(Phasor *self, PyObject *arg) { SET_DIV }; static PyObject * Phasor_play(Phasor *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Phasor_out(Phasor *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Phasor_stop(Phasor *self) { STOP }; static PyObject * Phasor_multiply(Phasor *self, PyObject *arg) { MULTIPLY }; static PyObject * Phasor_inplace_multiply(Phasor *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Phasor_add(Phasor *self, PyObject *arg) { ADD }; static PyObject * Phasor_inplace_add(Phasor *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Phasor_sub(Phasor *self, PyObject *arg) { SUB }; static PyObject * Phasor_inplace_sub(Phasor *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Phasor_div(Phasor *self, PyObject *arg) { DIV }; static PyObject * Phasor_inplace_div(Phasor *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Phasor_setFreq(Phasor *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Phasor_setPhase(Phasor *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->phase); if (isNumber == 1) { self->phase = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->phase = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->phase, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->phase_stream); self->phase_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Phasor_reset(Phasor *self) { self->pointerPos = 0.0; Py_INCREF(Py_None); return Py_None; } static PyMemberDef Phasor_members[] = { {"server", T_OBJECT_EX, offsetof(Phasor, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Phasor, stream), 0, "Stream object."}, {"freq", T_OBJECT_EX, offsetof(Phasor, freq), 0, "Frequency in cycle per second."}, {"phase", T_OBJECT_EX, offsetof(Phasor, phase), 0, "Phasorillator phase."}, {"mul", T_OBJECT_EX, offsetof(Phasor, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Phasor, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Phasor_methods[] = { {"getServer", (PyCFunction)Phasor_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Phasor_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Phasor_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Phasor_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Phasor_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Phasor_setFreq, METH_O, "Sets oscillator frequency in cycle per second."}, {"setPhase", (PyCFunction)Phasor_setPhase, METH_O, "Sets oscillator phase."}, {"reset", (PyCFunction)Phasor_reset, METH_NOARGS, "Resets pointer position to 0."}, {"setMul", (PyCFunction)Phasor_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Phasor_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Phasor_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)Phasor_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Phasor_as_number = { (binaryfunc)Phasor_add, /*nb_add*/ (binaryfunc)Phasor_sub, /*nb_subtract*/ (binaryfunc)Phasor_multiply, /*nb_multiply*/ (binaryfunc)Phasor_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Phasor_inplace_add, /*inplace_add*/ (binaryfunc)Phasor_inplace_sub, /*inplace_subtract*/ (binaryfunc)Phasor_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Phasor_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject PhasorType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Phasor_base", /*tp_name*/ sizeof(Phasor), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Phasor_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Phasor_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Phasor objects. Phase incrementor from 0 to 1.", /* tp_doc */ (traverseproc)Phasor_traverse, /* tp_traverse */ (inquiry)Phasor_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Phasor_methods, /* tp_methods */ Phasor_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Phasor_new, /* tp_new */ }; /**************/ /* Pointer object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *table; PyObject *index; Stream *index_stream; int modebuffer[2]; } Pointer; static void Pointer_readframes_a(Pointer *self) { MYFLT fpart; double ph; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *pha = Stream_getData((Stream *)self->index_stream); for (i=0; ibufsize; i++) { ph = Osc_clip(pha[i] * size, size); ipart = (int)ph; fpart = ph - ipart; self->data[i] = tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * fpart; } } static void Pointer_postprocessing_ii(Pointer *self) { POST_PROCESSING_II }; static void Pointer_postprocessing_ai(Pointer *self) { POST_PROCESSING_AI }; static void Pointer_postprocessing_ia(Pointer *self) { POST_PROCESSING_IA }; static void Pointer_postprocessing_aa(Pointer *self) { POST_PROCESSING_AA }; static void Pointer_postprocessing_ireva(Pointer *self) { POST_PROCESSING_IREVA }; static void Pointer_postprocessing_areva(Pointer *self) { POST_PROCESSING_AREVA }; static void Pointer_postprocessing_revai(Pointer *self) { POST_PROCESSING_REVAI }; static void Pointer_postprocessing_revaa(Pointer *self) { POST_PROCESSING_REVAA }; static void Pointer_postprocessing_revareva(Pointer *self) { POST_PROCESSING_REVAREVA }; static void Pointer_setProcMode(Pointer *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Pointer_readframes_a; switch (muladdmode) { case 0: self->muladd_func_ptr = Pointer_postprocessing_ii; break; case 1: self->muladd_func_ptr = Pointer_postprocessing_ai; break; case 2: self->muladd_func_ptr = Pointer_postprocessing_revai; break; case 10: self->muladd_func_ptr = Pointer_postprocessing_ia; break; case 11: self->muladd_func_ptr = Pointer_postprocessing_aa; break; case 12: self->muladd_func_ptr = Pointer_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Pointer_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Pointer_postprocessing_areva; break; case 22: self->muladd_func_ptr = Pointer_postprocessing_revareva; break; } } static void Pointer_compute_next_data_frame(Pointer *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Pointer_traverse(Pointer *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->index); Py_VISIT(self->index_stream); return 0; } static int Pointer_clear(Pointer *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->index); Py_CLEAR(self->index_stream); return 0; } static void Pointer_dealloc(Pointer* self) { pyo_DEALLOC Pointer_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *tabletmp, *indextmp, *multmp=NULL, *addtmp=NULL; Pointer *self; self = (Pointer *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Pointer_compute_next_data_frame); self->mode_func_ptr = Pointer_setProcMode; static char *kwlist[] = {"table", "index", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &tabletmp, &indextmp, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of Pointer must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if (indextmp) { PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp); } PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Pointer_getServer(Pointer* self) { GET_SERVER }; static PyObject * Pointer_getStream(Pointer* self) { GET_STREAM }; static PyObject * Pointer_setMul(Pointer *self, PyObject *arg) { SET_MUL }; static PyObject * Pointer_setAdd(Pointer *self, PyObject *arg) { SET_ADD }; static PyObject * Pointer_setSub(Pointer *self, PyObject *arg) { SET_SUB }; static PyObject * Pointer_setDiv(Pointer *self, PyObject *arg) { SET_DIV }; static PyObject * Pointer_play(Pointer *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Pointer_out(Pointer *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Pointer_stop(Pointer *self) { STOP }; static PyObject * Pointer_multiply(Pointer *self, PyObject *arg) { MULTIPLY }; static PyObject * Pointer_inplace_multiply(Pointer *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Pointer_add(Pointer *self, PyObject *arg) { ADD }; static PyObject * Pointer_inplace_add(Pointer *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Pointer_sub(Pointer *self, PyObject *arg) { SUB }; static PyObject * Pointer_inplace_sub(Pointer *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Pointer_div(Pointer *self, PyObject *arg) { DIV }; static PyObject * Pointer_inplace_div(Pointer *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Pointer_getTable(Pointer* self) { Py_INCREF(self->table); return self->table; }; static PyObject * Pointer_setTable(Pointer *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * Pointer_setIndex(Pointer *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL tmp = arg; if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) { PyErr_SetString(PyExc_TypeError, "\"index\" argument of Pointer must be a PyoObject.\n"); Py_RETURN_NONE; } Py_INCREF(tmp); Py_XDECREF(self->index); self->index = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->index_stream); self->index_stream = (Stream *)streamtmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef Pointer_members[] = { {"server", T_OBJECT_EX, offsetof(Pointer, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Pointer, stream), 0, "Stream object."}, {"table", T_OBJECT_EX, offsetof(Pointer, table), 0, "Waveform table."}, {"index", T_OBJECT_EX, offsetof(Pointer, index), 0, "Reader index."}, {"mul", T_OBJECT_EX, offsetof(Pointer, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Pointer, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Pointer_methods[] = { {"getTable", (PyCFunction)Pointer_getTable, METH_NOARGS, "Returns waveform table object."}, {"getServer", (PyCFunction)Pointer_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Pointer_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Pointer_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Pointer_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Pointer_stop, METH_NOARGS, "Stops computing."}, {"setTable", (PyCFunction)Pointer_setTable, METH_O, "Sets oscillator table."}, {"setIndex", (PyCFunction)Pointer_setIndex, METH_O, "Sets reader index."}, {"setMul", (PyCFunction)Pointer_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Pointer_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Pointer_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)Pointer_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Pointer_as_number = { (binaryfunc)Pointer_add, /*nb_add*/ (binaryfunc)Pointer_sub, /*nb_subtract*/ (binaryfunc)Pointer_multiply, /*nb_multiply*/ (binaryfunc)Pointer_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Pointer_inplace_add, /*inplace_add*/ (binaryfunc)Pointer_inplace_sub, /*inplace_subtract*/ (binaryfunc)Pointer_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Pointer_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject PointerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Pointer_base", /*tp_name*/ sizeof(Pointer), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Pointer_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Pointer_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Pointer objects. Read a waveform table with a pointer index.", /* tp_doc */ (traverseproc)Pointer_traverse, /* tp_traverse */ (inquiry)Pointer_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Pointer_methods, /* tp_methods */ Pointer_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Pointer_new, /* tp_new */ }; /**************/ /* Pointer2 object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *table; PyObject *index; Stream *index_stream; int modebuffer[2]; int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */ int autosmooth; /* 0 = off, > 0 = on */ MYFLT y1; MYFLT y2; MYFLT c; MYFLT lastPh; MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int); } Pointer2; static void Pointer2_readframes_a(Pointer2 *self) { MYFLT fpart, phdiff, b, fr; double ph; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); double tableSr = TableStream_getSamplingRate(self->table); MYFLT *pha = Stream_getData((Stream *)self->index_stream); if (!self->autosmooth) { for (i=0; ibufsize; i++) { ph = Osc_clip(pha[i] * size, size); ipart = (int)ph; fpart = ph - ipart; self->y1 = self->y2 = self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); } } else { for (i=0; ibufsize; i++) { ph = Osc_clip(pha[i] * size, size); ipart = (int)ph; fpart = ph - ipart; self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); phdiff = MYFABS(ph - self->lastPh); self->lastPh = ph; if (phdiff < 1) { fr = phdiff * tableSr * 0.45; b = 2.0 - MYCOS(TWOPI * fr / self->sr); self->c = (b - MYSQRT(b * b - 1.0)); self->y1 = self->data[i] + (self->y1 - self->data[i]) * self->c; self->data[i] = self->y2 = self->y1 + (self->y2 - self->y1) * self->c; } else self->y1 = self->y2 = self->data[i]; } } } static void Pointer2_postprocessing_ii(Pointer2 *self) { POST_PROCESSING_II }; static void Pointer2_postprocessing_ai(Pointer2 *self) { POST_PROCESSING_AI }; static void Pointer2_postprocessing_ia(Pointer2 *self) { POST_PROCESSING_IA }; static void Pointer2_postprocessing_aa(Pointer2 *self) { POST_PROCESSING_AA }; static void Pointer2_postprocessing_ireva(Pointer2 *self) { POST_PROCESSING_IREVA }; static void Pointer2_postprocessing_areva(Pointer2 *self) { POST_PROCESSING_AREVA }; static void Pointer2_postprocessing_revai(Pointer2 *self) { POST_PROCESSING_REVAI }; static void Pointer2_postprocessing_revaa(Pointer2 *self) { POST_PROCESSING_REVAA }; static void Pointer2_postprocessing_revareva(Pointer2 *self) { POST_PROCESSING_REVAREVA }; static void Pointer2_setProcMode(Pointer2 *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Pointer2_readframes_a; switch (muladdmode) { case 0: self->muladd_func_ptr = Pointer2_postprocessing_ii; break; case 1: self->muladd_func_ptr = Pointer2_postprocessing_ai; break; case 2: self->muladd_func_ptr = Pointer2_postprocessing_revai; break; case 10: self->muladd_func_ptr = Pointer2_postprocessing_ia; break; case 11: self->muladd_func_ptr = Pointer2_postprocessing_aa; break; case 12: self->muladd_func_ptr = Pointer2_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Pointer2_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Pointer2_postprocessing_areva; break; case 22: self->muladd_func_ptr = Pointer2_postprocessing_revareva; break; } } static void Pointer2_compute_next_data_frame(Pointer2 *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Pointer2_traverse(Pointer2 *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->index); Py_VISIT(self->index_stream); return 0; } static int Pointer2_clear(Pointer2 *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->index); Py_CLEAR(self->index_stream); return 0; } static void Pointer2_dealloc(Pointer2* self) { pyo_DEALLOC Pointer2_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Pointer2_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *tabletmp, *indextmp, *multmp=NULL, *addtmp=NULL; Pointer2 *self; self = (Pointer2 *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->interp = 4; self->autosmooth = 1; self->y1 = self->y2 = self->c = self->lastPh = 0.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Pointer2_compute_next_data_frame); self->mode_func_ptr = Pointer2_setProcMode; static char *kwlist[] = {"table", "index", "interp", "autosmooth", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|iiOO", kwlist, &tabletmp, &indextmp, &self->interp, &self->autosmooth, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of Pointer2 must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if (indextmp) { PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp); } PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); SET_INTERP_POINTER return (PyObject *)self; } static PyObject * Pointer2_getServer(Pointer2* self) { GET_SERVER }; static PyObject * Pointer2_getStream(Pointer2* self) { GET_STREAM }; static PyObject * Pointer2_setMul(Pointer2 *self, PyObject *arg) { SET_MUL }; static PyObject * Pointer2_setAdd(Pointer2 *self, PyObject *arg) { SET_ADD }; static PyObject * Pointer2_setSub(Pointer2 *self, PyObject *arg) { SET_SUB }; static PyObject * Pointer2_setDiv(Pointer2 *self, PyObject *arg) { SET_DIV }; static PyObject * Pointer2_play(Pointer2 *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Pointer2_out(Pointer2 *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Pointer2_stop(Pointer2 *self) { STOP }; static PyObject * Pointer2_multiply(Pointer2 *self, PyObject *arg) { MULTIPLY }; static PyObject * Pointer2_inplace_multiply(Pointer2 *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Pointer2_add(Pointer2 *self, PyObject *arg) { ADD }; static PyObject * Pointer2_inplace_add(Pointer2 *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Pointer2_sub(Pointer2 *self, PyObject *arg) { SUB }; static PyObject * Pointer2_inplace_sub(Pointer2 *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Pointer2_div(Pointer2 *self, PyObject *arg) { DIV }; static PyObject * Pointer2_inplace_div(Pointer2 *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Pointer2_getTable(Pointer2* self) { Py_INCREF(self->table); return self->table; }; static PyObject * Pointer2_setTable(Pointer2 *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * Pointer2_setIndex(Pointer2 *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL tmp = arg; if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) { PyErr_SetString(PyExc_TypeError, "\"index\" argument of Pointer2 must be a PyoObject.\n"); Py_RETURN_NONE; } Py_INCREF(tmp); Py_XDECREF(self->index); self->index = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->index_stream); self->index_stream = (Stream *)streamtmp; Py_INCREF(Py_None); return Py_None; } static PyObject * Pointer2_setInterp(Pointer2 *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->interp = PyInt_AsLong(PyNumber_Int(arg)); } SET_INTERP_POINTER Py_INCREF(Py_None); return Py_None; } static PyObject * Pointer2_setAutoSmooth(Pointer2 *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->autosmooth = PyInt_AsLong(PyNumber_Int(arg)); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Pointer2_members[] = { {"server", T_OBJECT_EX, offsetof(Pointer2, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Pointer2, stream), 0, "Stream object."}, {"table", T_OBJECT_EX, offsetof(Pointer2, table), 0, "Waveform table."}, {"index", T_OBJECT_EX, offsetof(Pointer2, index), 0, "Reader index."}, {"mul", T_OBJECT_EX, offsetof(Pointer2, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Pointer2, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Pointer2_methods[] = { {"getTable", (PyCFunction)Pointer2_getTable, METH_NOARGS, "Returns waveform table object."}, {"getServer", (PyCFunction)Pointer2_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Pointer2_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Pointer2_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Pointer2_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Pointer2_stop, METH_NOARGS, "Stops computing."}, {"setTable", (PyCFunction)Pointer2_setTable, METH_O, "Sets oscillator table."}, {"setIndex", (PyCFunction)Pointer2_setIndex, METH_O, "Sets reader index."}, {"setInterp", (PyCFunction)Pointer2_setInterp, METH_O, "Sets oscillator interpolation mode."}, {"setAutoSmooth", (PyCFunction)Pointer2_setAutoSmooth, METH_O, "Activates auto smoother filter."}, {"setMul", (PyCFunction)Pointer2_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Pointer2_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Pointer2_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)Pointer2_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Pointer2_as_number = { (binaryfunc)Pointer2_add, /*nb_add*/ (binaryfunc)Pointer2_sub, /*nb_subtract*/ (binaryfunc)Pointer2_multiply, /*nb_multiply*/ (binaryfunc)Pointer2_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Pointer2_inplace_add, /*inplace_add*/ (binaryfunc)Pointer2_inplace_sub, /*inplace_subtract*/ (binaryfunc)Pointer2_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Pointer2_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject Pointer2Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Pointer2_base", /*tp_name*/ sizeof(Pointer2), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Pointer2_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Pointer2_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Pointer2 objects. High quality table reader with a pointer index.", /* tp_doc */ (traverseproc)Pointer2_traverse, /* tp_traverse */ (inquiry)Pointer2_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Pointer2_methods, /* tp_methods */ Pointer2_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Pointer2_new, /* tp_new */ }; /**************/ /* TableIndex object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *table; PyObject *index; Stream *index_stream; int modebuffer[2]; } TableIndex; static void TableIndex_readframes_a(TableIndex *self) { int i, ind; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *phase = Stream_getData((Stream *)self->index_stream); for (i=0; ibufsize; i++) { ind = (int)phase[i]; if (ind < 0) ind = 0; else if (ind >= size) ind = size - 1; self->data[i] = tablelist[ind]; } } static void TableIndex_postprocessing_ii(TableIndex *self) { POST_PROCESSING_II }; static void TableIndex_postprocessing_ai(TableIndex *self) { POST_PROCESSING_AI }; static void TableIndex_postprocessing_ia(TableIndex *self) { POST_PROCESSING_IA }; static void TableIndex_postprocessing_aa(TableIndex *self) { POST_PROCESSING_AA }; static void TableIndex_postprocessing_ireva(TableIndex *self) { POST_PROCESSING_IREVA }; static void TableIndex_postprocessing_areva(TableIndex *self) { POST_PROCESSING_AREVA }; static void TableIndex_postprocessing_revai(TableIndex *self) { POST_PROCESSING_REVAI }; static void TableIndex_postprocessing_revaa(TableIndex *self) { POST_PROCESSING_REVAA }; static void TableIndex_postprocessing_revareva(TableIndex *self) { POST_PROCESSING_REVAREVA }; static void TableIndex_setProcMode(TableIndex *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = TableIndex_readframes_a; switch (muladdmode) { case 0: self->muladd_func_ptr = TableIndex_postprocessing_ii; break; case 1: self->muladd_func_ptr = TableIndex_postprocessing_ai; break; case 2: self->muladd_func_ptr = TableIndex_postprocessing_revai; break; case 10: self->muladd_func_ptr = TableIndex_postprocessing_ia; break; case 11: self->muladd_func_ptr = TableIndex_postprocessing_aa; break; case 12: self->muladd_func_ptr = TableIndex_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TableIndex_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TableIndex_postprocessing_areva; break; case 22: self->muladd_func_ptr = TableIndex_postprocessing_revareva; break; } } static void TableIndex_compute_next_data_frame(TableIndex *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int TableIndex_traverse(TableIndex *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->index); Py_VISIT(self->index_stream); return 0; } static int TableIndex_clear(TableIndex *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->index); Py_CLEAR(self->index_stream); return 0; } static void TableIndex_dealloc(TableIndex* self) { pyo_DEALLOC TableIndex_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TableIndex_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *tabletmp, *indextmp, *multmp=NULL, *addtmp=NULL; TableIndex *self; self = (TableIndex *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TableIndex_compute_next_data_frame); self->mode_func_ptr = TableIndex_setProcMode; static char *kwlist[] = {"table", "index", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &tabletmp, &indextmp, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableIndex must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if (indextmp) { PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp); } PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TableIndex_getServer(TableIndex* self) { GET_SERVER }; static PyObject * TableIndex_getStream(TableIndex* self) { GET_STREAM }; static PyObject * TableIndex_setMul(TableIndex *self, PyObject *arg) { SET_MUL }; static PyObject * TableIndex_setAdd(TableIndex *self, PyObject *arg) { SET_ADD }; static PyObject * TableIndex_setSub(TableIndex *self, PyObject *arg) { SET_SUB }; static PyObject * TableIndex_setDiv(TableIndex *self, PyObject *arg) { SET_DIV }; static PyObject * TableIndex_play(TableIndex *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TableIndex_out(TableIndex *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TableIndex_stop(TableIndex *self) { STOP }; static PyObject * TableIndex_multiply(TableIndex *self, PyObject *arg) { MULTIPLY }; static PyObject * TableIndex_inplace_multiply(TableIndex *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TableIndex_add(TableIndex *self, PyObject *arg) { ADD }; static PyObject * TableIndex_inplace_add(TableIndex *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TableIndex_sub(TableIndex *self, PyObject *arg) { SUB }; static PyObject * TableIndex_inplace_sub(TableIndex *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TableIndex_div(TableIndex *self, PyObject *arg) { DIV }; static PyObject * TableIndex_inplace_div(TableIndex *self, PyObject *arg) { INPLACE_DIV }; static PyObject * TableIndex_getTable(TableIndex* self) { Py_INCREF(self->table); return self->table; }; static PyObject * TableIndex_setTable(TableIndex *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * TableIndex_setIndex(TableIndex *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL tmp = arg; if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) { PyErr_SetString(PyExc_TypeError, "\"index\" argument of TableIndex must be a PyoObject.\n"); Py_RETURN_NONE; } Py_INCREF(tmp); Py_XDECREF(self->index); self->index = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->index_stream); self->index_stream = (Stream *)streamtmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef TableIndex_members[] = { {"server", T_OBJECT_EX, offsetof(TableIndex, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TableIndex, stream), 0, "Stream object."}, {"table", T_OBJECT_EX, offsetof(TableIndex, table), 0, "Waveform table."}, {"index", T_OBJECT_EX, offsetof(TableIndex, index), 0, "Reader index."}, {"mul", T_OBJECT_EX, offsetof(TableIndex, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TableIndex, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TableIndex_methods[] = { {"getTable", (PyCFunction)TableIndex_getTable, METH_NOARGS, "Returns waveform table object."}, {"getServer", (PyCFunction)TableIndex_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TableIndex_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TableIndex_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TableIndex_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TableIndex_stop, METH_NOARGS, "Stops computing."}, {"setTable", (PyCFunction)TableIndex_setTable, METH_O, "Sets oscillator table."}, {"setIndex", (PyCFunction)TableIndex_setIndex, METH_O, "Sets reader index."}, {"setMul", (PyCFunction)TableIndex_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TableIndex_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TableIndex_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)TableIndex_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TableIndex_as_number = { (binaryfunc)TableIndex_add, /*nb_add*/ (binaryfunc)TableIndex_sub, /*nb_subtract*/ (binaryfunc)TableIndex_multiply, /*nb_multiply*/ (binaryfunc)TableIndex_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TableIndex_inplace_add, /*inplace_add*/ (binaryfunc)TableIndex_inplace_sub, /*inplace_subtract*/ (binaryfunc)TableIndex_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TableIndex_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TableIndexType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TableIndex_base", /*tp_name*/ sizeof(TableIndex), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TableIndex_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TableIndex_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TableIndex objects. Read a table by indexing without interpolation.", /* tp_doc */ (traverseproc)TableIndex_traverse, /* tp_traverse */ (inquiry)TableIndex_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TableIndex_methods, /* tp_methods */ TableIndex_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TableIndex_new, /* tp_new */ }; /**************/ /* Lookup object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *table; PyObject *index; Stream *index_stream; int modebuffer[2]; } Lookup; static MYFLT Lookup_clip(MYFLT x) { if (x < -1.0) return -1.0; else if (x > 1.0) return 1.0; else return x; } static void Lookup_readframes_a(Lookup *self) { MYFLT ph, fpart; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *pha = Stream_getData((Stream *)self->index_stream); for (i=0; ibufsize; i++) { ph = (Lookup_clip(pha[i]) * 0.495 + 0.5) * size; ipart = (int)ph; fpart = ph - ipart; self->data[i] = tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * fpart; } } static void Lookup_postprocessing_ii(Lookup *self) { POST_PROCESSING_II }; static void Lookup_postprocessing_ai(Lookup *self) { POST_PROCESSING_AI }; static void Lookup_postprocessing_ia(Lookup *self) { POST_PROCESSING_IA }; static void Lookup_postprocessing_aa(Lookup *self) { POST_PROCESSING_AA }; static void Lookup_postprocessing_ireva(Lookup *self) { POST_PROCESSING_IREVA }; static void Lookup_postprocessing_areva(Lookup *self) { POST_PROCESSING_AREVA }; static void Lookup_postprocessing_revai(Lookup *self) { POST_PROCESSING_REVAI }; static void Lookup_postprocessing_revaa(Lookup *self) { POST_PROCESSING_REVAA }; static void Lookup_postprocessing_revareva(Lookup *self) { POST_PROCESSING_REVAREVA }; static void Lookup_setProcMode(Lookup *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Lookup_readframes_a; switch (muladdmode) { case 0: self->muladd_func_ptr = Lookup_postprocessing_ii; break; case 1: self->muladd_func_ptr = Lookup_postprocessing_ai; break; case 2: self->muladd_func_ptr = Lookup_postprocessing_revai; break; case 10: self->muladd_func_ptr = Lookup_postprocessing_ia; break; case 11: self->muladd_func_ptr = Lookup_postprocessing_aa; break; case 12: self->muladd_func_ptr = Lookup_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Lookup_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Lookup_postprocessing_areva; break; case 22: self->muladd_func_ptr = Lookup_postprocessing_revareva; break; } } static void Lookup_compute_next_data_frame(Lookup *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Lookup_traverse(Lookup *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->index); Py_VISIT(self->index_stream); return 0; } static int Lookup_clear(Lookup *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->index); Py_CLEAR(self->index_stream); return 0; } static void Lookup_dealloc(Lookup* self) { pyo_DEALLOC Lookup_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Lookup_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *tabletmp, *indextmp, *multmp=NULL, *addtmp=NULL; Lookup *self; self = (Lookup *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Lookup_compute_next_data_frame); self->mode_func_ptr = Lookup_setProcMode; static char *kwlist[] = {"table", "index", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &tabletmp, &indextmp, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of Lookup must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if (indextmp) { PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp); } PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Lookup_getServer(Lookup* self) { GET_SERVER }; static PyObject * Lookup_getStream(Lookup* self) { GET_STREAM }; static PyObject * Lookup_setMul(Lookup *self, PyObject *arg) { SET_MUL }; static PyObject * Lookup_setAdd(Lookup *self, PyObject *arg) { SET_ADD }; static PyObject * Lookup_setSub(Lookup *self, PyObject *arg) { SET_SUB }; static PyObject * Lookup_setDiv(Lookup *self, PyObject *arg) { SET_DIV }; static PyObject * Lookup_play(Lookup *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Lookup_out(Lookup *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Lookup_stop(Lookup *self) { STOP }; static PyObject * Lookup_multiply(Lookup *self, PyObject *arg) { MULTIPLY }; static PyObject * Lookup_inplace_multiply(Lookup *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Lookup_add(Lookup *self, PyObject *arg) { ADD }; static PyObject * Lookup_inplace_add(Lookup *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Lookup_sub(Lookup *self, PyObject *arg) { SUB }; static PyObject * Lookup_inplace_sub(Lookup *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Lookup_div(Lookup *self, PyObject *arg) { DIV }; static PyObject * Lookup_inplace_div(Lookup *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Lookup_getTable(Lookup* self) { Py_INCREF(self->table); return self->table; }; static PyObject * Lookup_setTable(Lookup *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * Lookup_setIndex(Lookup *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL tmp = arg; if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) { PyErr_SetString(PyExc_TypeError, "\"index\" argument of Lookup must be a PyoObject.\n"); Py_RETURN_NONE; } Py_INCREF(tmp); Py_XDECREF(self->index); self->index = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->index_stream); self->index_stream = (Stream *)streamtmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef Lookup_members[] = { {"server", T_OBJECT_EX, offsetof(Lookup, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Lookup, stream), 0, "Stream object."}, {"table", T_OBJECT_EX, offsetof(Lookup, table), 0, "Waveform table."}, {"index", T_OBJECT_EX, offsetof(Lookup, index), 0, "Reader index."}, {"mul", T_OBJECT_EX, offsetof(Lookup, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Lookup, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Lookup_methods[] = { {"getTable", (PyCFunction)Lookup_getTable, METH_NOARGS, "Returns waveform table object."}, {"getServer", (PyCFunction)Lookup_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Lookup_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Lookup_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Lookup_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Lookup_stop, METH_NOARGS, "Stops computing."}, {"setTable", (PyCFunction)Lookup_setTable, METH_O, "Sets oscillator table."}, {"setIndex", (PyCFunction)Lookup_setIndex, METH_O, "Sets reader index."}, {"setMul", (PyCFunction)Lookup_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Lookup_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Lookup_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)Lookup_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Lookup_as_number = { (binaryfunc)Lookup_add, /*nb_add*/ (binaryfunc)Lookup_sub, /*nb_subtract*/ (binaryfunc)Lookup_multiply, /*nb_multiply*/ (binaryfunc)Lookup_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Lookup_inplace_add, /*inplace_add*/ (binaryfunc)Lookup_inplace_sub, /*inplace_subtract*/ (binaryfunc)Lookup_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Lookup_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject LookupType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Lookup_base", /*tp_name*/ sizeof(Lookup), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Lookup_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Lookup_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Lookup objects. Modify a signal by reading a table with the signal as the index.", /* tp_doc */ (traverseproc)Lookup_traverse, /* tp_traverse */ (inquiry)Lookup_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Lookup_methods, /* tp_methods */ Lookup_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Lookup_new, /* tp_new */ }; /**************/ /* Pulsar object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *table; PyObject *env; PyObject *freq; Stream *freq_stream; PyObject *phase; Stream *phase_stream; PyObject *frac; Stream *frac_stream; int modebuffer[5]; MYFLT pointerPos; int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */ MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int); } Pulsar; static void Pulsar_readframes_iii(Pulsar *self) { MYFLT fr, ph, frac, invfrac, pos, scl_pos, t_pos, e_pos, fpart, tmp; double inc; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); MYFLT *envlist = TableStream_getData(self->env); int size = TableStream_getSize(self->table); int envsize = TableStream_getSize(self->env); fr = PyFloat_AS_DOUBLE(self->freq); ph = PyFloat_AS_DOUBLE(self->phase); frac = _clip(PyFloat_AS_DOUBLE(self->frac)); invfrac = 1.0 / frac; inc = fr / self->sr; for (i=0; ibufsize; i++) { self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos = 1.0 + self->pointerPos; else if (self->pointerPos >= 1.0) self->pointerPos -= 1.0; pos = self->pointerPos + ph; if (pos >= 1.0) pos -= 1.0; if (pos < frac) { scl_pos = pos * invfrac; t_pos = scl_pos * size; ipart = (int)t_pos; fpart = t_pos - ipart; tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); e_pos = scl_pos * envsize; ipart = (int)e_pos; fpart = e_pos - ipart; self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart); } else { self->data[i] = 0.0; } } } static void Pulsar_readframes_aii(Pulsar *self) { MYFLT ph, frac, invfrac, pos, scl_pos, t_pos, e_pos, fpart, tmp, oneOnSr; double inc; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); MYFLT *envlist = TableStream_getData(self->env); int size = TableStream_getSize(self->table); int envsize = TableStream_getSize(self->env); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); ph = PyFloat_AS_DOUBLE(self->phase); frac = _clip(PyFloat_AS_DOUBLE(self->frac)); invfrac = 1.0 / frac; oneOnSr = 1.0 / self->sr; for (i=0; ibufsize; i++) { inc = fr[i] * oneOnSr; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos = 1.0 + self->pointerPos; else if (self->pointerPos >= 1.0) self->pointerPos -= 1.0; pos = self->pointerPos + ph; if (pos >= 1.0) pos -= 1.0; if (pos < frac) { scl_pos = pos * invfrac; t_pos = scl_pos * size; ipart = (int)t_pos; fpart = t_pos - ipart; tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); e_pos = scl_pos * envsize; ipart = (int)e_pos; fpart = e_pos - ipart; self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart); } else { self->data[i] = 0.0; } } } static void Pulsar_readframes_iai(Pulsar *self) { MYFLT fr, frac, invfrac, pos, scl_pos, t_pos, e_pos, fpart, tmp; double inc; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); MYFLT *envlist = TableStream_getData(self->env); int size = TableStream_getSize(self->table); int envsize = TableStream_getSize(self->env); fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *ph = Stream_getData((Stream *)self->phase_stream); frac = _clip(PyFloat_AS_DOUBLE(self->frac)); invfrac = 1.0 / frac; inc = fr / self->sr; for (i=0; ibufsize; i++) { self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos = 1.0 + self->pointerPos; else if (self->pointerPos >= 1.0) self->pointerPos -= 1.0; pos = self->pointerPos + ph[i]; if (pos >= 1.0) pos -= 1.0; if (pos < frac) { scl_pos = pos * invfrac; t_pos = scl_pos * size; ipart = (int)t_pos; fpart = t_pos - ipart; tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); e_pos = scl_pos * envsize; ipart = (int)e_pos; fpart = e_pos - ipart; self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart); } else { self->data[i] = 0.0; } } } static void Pulsar_readframes_aai(Pulsar *self) { MYFLT frac, invfrac, pos, scl_pos, t_pos, e_pos, fpart, tmp, oneOnSr; double inc; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); MYFLT *envlist = TableStream_getData(self->env); int size = TableStream_getSize(self->table); int envsize = TableStream_getSize(self->env); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *ph = Stream_getData((Stream *)self->phase_stream); frac = _clip(PyFloat_AS_DOUBLE(self->frac)); invfrac = 1.0 / frac; oneOnSr = 1.0 / self->sr; for (i=0; ibufsize; i++) { inc = fr[i] * oneOnSr; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos = 1.0 + self->pointerPos; else if (self->pointerPos >= 1.0) self->pointerPos -= 1.0; pos = self->pointerPos + ph[i]; if (pos >= 1.0) pos -= 1.0; if (pos < frac) { scl_pos = pos * invfrac; t_pos = scl_pos * size; ipart = (int)t_pos; fpart = t_pos - ipart; tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); e_pos = scl_pos * envsize; ipart = (int)e_pos; fpart = e_pos - ipart; self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart); } else { self->data[i] = 0.0; } } } static void Pulsar_readframes_iia(Pulsar *self) { MYFLT fr, ph, pos, curfrac, scl_pos, t_pos, e_pos, fpart, tmp; double inc; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); MYFLT *envlist = TableStream_getData(self->env); int size = TableStream_getSize(self->table); int envsize = TableStream_getSize(self->env); fr = PyFloat_AS_DOUBLE(self->freq); ph = PyFloat_AS_DOUBLE(self->phase); MYFLT *frac = Stream_getData((Stream *)self->frac_stream); inc = fr / self->sr; for (i=0; ibufsize; i++) { curfrac = frac[i]; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos = 1.0 + self->pointerPos; else if (self->pointerPos >= 1.0) self->pointerPos -= 1.0; pos = self->pointerPos + ph; if (pos >= 1.0) pos -= 1.0; if (pos < curfrac) { scl_pos = pos / curfrac; t_pos = scl_pos * size; ipart = (int)t_pos; fpart = t_pos - ipart; tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); e_pos = scl_pos * envsize; ipart = (int)e_pos; fpart = e_pos - ipart; self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart); } else { self->data[i] = 0.0; } } } static void Pulsar_readframes_aia(Pulsar *self) { MYFLT ph, pos, curfrac, scl_pos, t_pos, e_pos, fpart, tmp, oneOnSr; double inc; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); MYFLT *envlist = TableStream_getData(self->env); int size = TableStream_getSize(self->table); int envsize = TableStream_getSize(self->env); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); ph = PyFloat_AS_DOUBLE(self->phase); MYFLT *frac = Stream_getData((Stream *)self->frac_stream); oneOnSr = 1.0 / self->sr; for (i=0; ibufsize; i++) { curfrac = frac[i]; inc = fr[i] * oneOnSr; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos = 1.0 + self->pointerPos; else if (self->pointerPos >= 1.0) self->pointerPos -= 1.0; pos = self->pointerPos + ph; if (pos >= 1.0) pos -= 1.0; if (pos < curfrac) { scl_pos = pos / curfrac; t_pos = scl_pos * size; ipart = (int)t_pos; fpart = t_pos - ipart; tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); e_pos = scl_pos * envsize; ipart = (int)e_pos; fpart = e_pos - ipart; self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart); } else { self->data[i] = 0.0; } } } static void Pulsar_readframes_iaa(Pulsar *self) { MYFLT fr, pos, curfrac, scl_pos, t_pos, e_pos, fpart, tmp; double inc; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); MYFLT *envlist = TableStream_getData(self->env); int size = TableStream_getSize(self->table); int envsize = TableStream_getSize(self->env); fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *ph = Stream_getData((Stream *)self->phase_stream); MYFLT *frac = Stream_getData((Stream *)self->frac_stream); inc = fr / self->sr; for (i=0; ibufsize; i++) { curfrac = frac[i]; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos = 1.0 + self->pointerPos; else if (self->pointerPos >= 1.0) self->pointerPos -= 1.0; pos = self->pointerPos + ph[i]; if (pos >= 1.0) pos -= 1.0; if (pos < curfrac) { scl_pos = pos / curfrac; t_pos = scl_pos * size; ipart = (int)t_pos; fpart = t_pos - ipart; tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); e_pos = scl_pos * envsize; ipart = (int)e_pos; fpart = e_pos - ipart; self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart); } else { self->data[i] = 0.0; } } } static void Pulsar_readframes_aaa(Pulsar *self) { MYFLT pos, curfrac, scl_pos, t_pos, e_pos, fpart, tmp, oneOnSr; double inc; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); MYFLT *envlist = TableStream_getData(self->env); int size = TableStream_getSize(self->table); int envsize = TableStream_getSize(self->env); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *ph = Stream_getData((Stream *)self->phase_stream); MYFLT *frac = Stream_getData((Stream *)self->frac_stream); oneOnSr = 1.0 / self->sr; for (i=0; ibufsize; i++) { curfrac = frac[i]; inc = fr[i] * oneOnSr; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos = 1.0 + self->pointerPos; else if (self->pointerPos >= 1.0) self->pointerPos -= 1.0; pos = self->pointerPos + ph[i]; if (pos >= 1.0) pos -= 1.0; if (pos < curfrac) { scl_pos = pos / curfrac; t_pos = scl_pos * size; ipart = (int)t_pos; fpart = t_pos - ipart; tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); e_pos = scl_pos * envsize; ipart = (int)e_pos; fpart = e_pos - ipart; self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart); } else { self->data[i] = 0.0; } } } static void Pulsar_postprocessing_ii(Pulsar *self) { POST_PROCESSING_II }; static void Pulsar_postprocessing_ai(Pulsar *self) { POST_PROCESSING_AI }; static void Pulsar_postprocessing_ia(Pulsar *self) { POST_PROCESSING_IA }; static void Pulsar_postprocessing_aa(Pulsar *self) { POST_PROCESSING_AA }; static void Pulsar_postprocessing_ireva(Pulsar *self) { POST_PROCESSING_IREVA }; static void Pulsar_postprocessing_areva(Pulsar *self) { POST_PROCESSING_AREVA }; static void Pulsar_postprocessing_revai(Pulsar *self) { POST_PROCESSING_REVAI }; static void Pulsar_postprocessing_revaa(Pulsar *self) { POST_PROCESSING_REVAA }; static void Pulsar_postprocessing_revareva(Pulsar *self) { POST_PROCESSING_REVAREVA }; static void Pulsar_setProcMode(Pulsar *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Pulsar_readframes_iii; break; case 1: self->proc_func_ptr = Pulsar_readframes_aii; break; case 10: self->proc_func_ptr = Pulsar_readframes_iai; break; case 11: self->proc_func_ptr = Pulsar_readframes_aai; break; case 100: self->proc_func_ptr = Pulsar_readframes_iia; break; case 101: self->proc_func_ptr = Pulsar_readframes_aia; break; case 110: self->proc_func_ptr = Pulsar_readframes_iaa; break; case 111: self->proc_func_ptr = Pulsar_readframes_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Pulsar_postprocessing_ii; break; case 1: self->muladd_func_ptr = Pulsar_postprocessing_ai; break; case 2: self->muladd_func_ptr = Pulsar_postprocessing_revai; break; case 10: self->muladd_func_ptr = Pulsar_postprocessing_ia; break; case 11: self->muladd_func_ptr = Pulsar_postprocessing_aa; break; case 12: self->muladd_func_ptr = Pulsar_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Pulsar_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Pulsar_postprocessing_areva; break; case 22: self->muladd_func_ptr = Pulsar_postprocessing_revareva; break; } } static void Pulsar_compute_next_data_frame(Pulsar *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Pulsar_traverse(Pulsar *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->env); Py_VISIT(self->phase); Py_VISIT(self->phase_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->frac); Py_VISIT(self->frac_stream); return 0; } static int Pulsar_clear(Pulsar *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->env); Py_CLEAR(self->phase); Py_CLEAR(self->phase_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->frac); Py_CLEAR(self->frac_stream); return 0; } static void Pulsar_dealloc(Pulsar* self) { pyo_DEALLOC Pulsar_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Pulsar_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *tabletmp, *envtmp, *freqtmp=NULL, *phasetmp=NULL, *fractmp=NULL, *multmp=NULL, *addtmp=NULL; Pulsar *self; self = (Pulsar *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(100); self->phase = PyFloat_FromDouble(0); self->frac = PyFloat_FromDouble(0.5); self->interp = 2; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->pointerPos = 0.; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Pulsar_compute_next_data_frame); self->mode_func_ptr = Pulsar_setProcMode; static char *kwlist[] = {"table", "env", "freq", "frac", "phase", "interp", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOOiOO", kwlist, &tabletmp, &envtmp, &freqtmp, &fractmp, &phasetmp, &self->interp, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of Pulsar must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if ( PyObject_HasAttrString((PyObject *)envtmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"env\" argument of Pulsar must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->env); self->env = PyObject_CallMethod((PyObject *)envtmp, "getTableStream", ""); if (phasetmp) { PyObject_CallMethod((PyObject *)self, "setPhase", "O", phasetmp); } if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (fractmp) { PyObject_CallMethod((PyObject *)self, "setFrac", "O", fractmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); SET_INTERP_POINTER return (PyObject *)self; } static PyObject * Pulsar_getServer(Pulsar* self) { GET_SERVER }; static PyObject * Pulsar_getStream(Pulsar* self) { GET_STREAM }; static PyObject * Pulsar_setMul(Pulsar *self, PyObject *arg) { SET_MUL }; static PyObject * Pulsar_setAdd(Pulsar *self, PyObject *arg) { SET_ADD }; static PyObject * Pulsar_setSub(Pulsar *self, PyObject *arg) { SET_SUB }; static PyObject * Pulsar_setDiv(Pulsar *self, PyObject *arg) { SET_DIV }; static PyObject * Pulsar_play(Pulsar *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Pulsar_out(Pulsar *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Pulsar_stop(Pulsar *self) { STOP }; static PyObject * Pulsar_multiply(Pulsar *self, PyObject *arg) { MULTIPLY }; static PyObject * Pulsar_inplace_multiply(Pulsar *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Pulsar_add(Pulsar *self, PyObject *arg) { ADD }; static PyObject * Pulsar_inplace_add(Pulsar *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Pulsar_sub(Pulsar *self, PyObject *arg) { SUB }; static PyObject * Pulsar_inplace_sub(Pulsar *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Pulsar_div(Pulsar *self, PyObject *arg) { DIV }; static PyObject * Pulsar_inplace_div(Pulsar *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Pulsar_getTable(Pulsar* self) { Py_INCREF(self->table); return self->table; }; static PyObject * Pulsar_getEnv(Pulsar* self) { Py_INCREF(self->env); return self->env; }; static PyObject * Pulsar_setTable(Pulsar *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * Pulsar_setEnv(Pulsar *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->env); self->env = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * Pulsar_setFreq(Pulsar *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Pulsar_setPhase(Pulsar *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->phase); if (isNumber == 1) { self->phase = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->phase = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->phase, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->phase_stream); self->phase_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Pulsar_setFrac(Pulsar *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->frac); if (isNumber == 1) { self->frac = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->frac = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->frac, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->frac_stream); self->frac_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Pulsar_setInterp(Pulsar *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->interp = PyInt_AsLong(PyNumber_Int(arg)); } SET_INTERP_POINTER Py_INCREF(Py_None); return Py_None; } static PyMemberDef Pulsar_members[] = { {"server", T_OBJECT_EX, offsetof(Pulsar, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Pulsar, stream), 0, "Stream object."}, {"table", T_OBJECT_EX, offsetof(Pulsar, table), 0, "Waveform table."}, {"freq", T_OBJECT_EX, offsetof(Pulsar, freq), 0, "Frequency in cycle per second."}, {"phase", T_OBJECT_EX, offsetof(Pulsar, phase), 0, "Oscillator phase."}, {"frac", T_OBJECT_EX, offsetof(Pulsar, frac), 0, "Table width inside whole length."}, {"mul", T_OBJECT_EX, offsetof(Pulsar, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Pulsar, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Pulsar_methods[] = { {"getTable", (PyCFunction)Pulsar_getTable, METH_NOARGS, "Returns waveform table object."}, {"getEnv", (PyCFunction)Pulsar_getEnv, METH_NOARGS, "Returns object envelope."}, {"getServer", (PyCFunction)Pulsar_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Pulsar_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Pulsar_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Pulsar_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Pulsar_stop, METH_NOARGS, "Stops computing."}, {"setTable", (PyCFunction)Pulsar_setTable, METH_O, "Sets oscillator table."}, {"setEnv", (PyCFunction)Pulsar_setEnv, METH_O, "Sets envelope table."}, {"setFreq", (PyCFunction)Pulsar_setFreq, METH_O, "Sets oscillator frequency in cycle per second."}, {"setPhase", (PyCFunction)Pulsar_setPhase, METH_O, "Sets oscillator phase."}, {"setFrac", (PyCFunction)Pulsar_setFrac, METH_O, "Sets waveform width inside whole period length."}, {"setInterp", (PyCFunction)Pulsar_setInterp, METH_O, "Sets Pulsar interpolation mode."}, {"setMul", (PyCFunction)Pulsar_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Pulsar_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Pulsar_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)Pulsar_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Pulsar_as_number = { (binaryfunc)Pulsar_add, /*nb_add*/ (binaryfunc)Pulsar_sub, /*nb_subtract*/ (binaryfunc)Pulsar_multiply, /*nb_multiply*/ (binaryfunc)Pulsar_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Pulsar_inplace_add, /*inplace_add*/ (binaryfunc)Pulsar_inplace_sub, /*inplace_subtract*/ (binaryfunc)Pulsar_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Pulsar_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject PulsarType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Pulsar_base", /*tp_name*/ sizeof(Pulsar), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Pulsar_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Pulsar_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Pulsar objects. Generates pulsar synthesis oscillator.", /* tp_doc */ (traverseproc)Pulsar_traverse, /* tp_traverse */ (inquiry)Pulsar_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Pulsar_methods, /* tp_methods */ Pulsar_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Pulsar_new, /* tp_new */ }; /**************/ /* TableRead object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *table; PyObject *freq; Stream *freq_stream; int loop; int go; int modebuffer[3]; double pointerPos; MYFLT *trigsBuffer; TriggerStream *trig_stream; int init; int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */ MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int); } TableRead; static void TableRead_readframes_i(TableRead *self) { MYFLT fr, inc, fpart; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); fr = PyFloat_AS_DOUBLE(self->freq); inc = fr * size / self->sr; if (self->go == 0) PyObject_CallMethod((PyObject *)self, "stop", NULL); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; if (self->pointerPos < 0) { if (self->init == 0) self->trigsBuffer[i] = 1.0; else self->init = 0; self->pointerPos = size + self->pointerPos; } else if (self->pointerPos >= size) { self->trigsBuffer[i] = 1.0; if (self->loop == 1) self->pointerPos -= size; else self->go = 0; } if (self->go == 1) { ipart = (int)self->pointerPos; fpart = self->pointerPos - ipart; self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); } else self->data[i] = 0.0; self->pointerPos += inc; } } static void TableRead_readframes_a(TableRead *self) { MYFLT inc, fpart, sizeOnSr; int i, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); sizeOnSr = size / self->sr; if (self->go == 0) PyObject_CallMethod((PyObject *)self, "stop", NULL); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; if (self->pointerPos < 0) { if (self->init == 0) self->trigsBuffer[i] = 1.0; else self->init = 0; self->pointerPos = size + self->pointerPos; } else if (self->pointerPos >= size) { self->trigsBuffer[i] = 1.0; if (self->loop == 1) self->pointerPos -= size; else self->go = 0; } if (self->go == 1) { ipart = (int)self->pointerPos; fpart = self->pointerPos - ipart; self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); } else self->data[i] = 0.0; inc = fr[i] * sizeOnSr; self->pointerPos += inc; } } static void TableRead_postprocessing_ii(TableRead *self) { POST_PROCESSING_II }; static void TableRead_postprocessing_ai(TableRead *self) { POST_PROCESSING_AI }; static void TableRead_postprocessing_ia(TableRead *self) { POST_PROCESSING_IA }; static void TableRead_postprocessing_aa(TableRead *self) { POST_PROCESSING_AA }; static void TableRead_postprocessing_ireva(TableRead *self) { POST_PROCESSING_IREVA }; static void TableRead_postprocessing_areva(TableRead *self) { POST_PROCESSING_AREVA }; static void TableRead_postprocessing_revai(TableRead *self) { POST_PROCESSING_REVAI }; static void TableRead_postprocessing_revaa(TableRead *self) { POST_PROCESSING_REVAA }; static void TableRead_postprocessing_revareva(TableRead *self) { POST_PROCESSING_REVAREVA }; static void TableRead_setProcMode(TableRead *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = TableRead_readframes_i; break; case 1: self->proc_func_ptr = TableRead_readframes_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = TableRead_postprocessing_ii; break; case 1: self->muladd_func_ptr = TableRead_postprocessing_ai; break; case 2: self->muladd_func_ptr = TableRead_postprocessing_revai; break; case 10: self->muladd_func_ptr = TableRead_postprocessing_ia; break; case 11: self->muladd_func_ptr = TableRead_postprocessing_aa; break; case 12: self->muladd_func_ptr = TableRead_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TableRead_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TableRead_postprocessing_areva; break; case 22: self->muladd_func_ptr = TableRead_postprocessing_revareva; break; } } static void TableRead_compute_next_data_frame(TableRead *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int TableRead_traverse(TableRead *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->trig_stream); return 0; } static int TableRead_clear(TableRead *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->trig_stream); return 0; } static void TableRead_dealloc(TableRead* self) { pyo_DEALLOC free(self->trigsBuffer); TableRead_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TableRead_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT *tablelist; PyObject *tabletmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL; TableRead *self; self = (TableRead *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1); self->loop = 0; self->init = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->pointerPos = 0.; self->interp = 2; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TableRead_compute_next_data_frame); self->mode_func_ptr = TableRead_setProcMode; static char *kwlist[] = {"table", "freq", "loop", "interp", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OiiOO", kwlist, &tabletmp, &freqtmp, &self->loop, &self->interp, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableRead must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); tablelist = TableStream_getData(self->table); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; self->data[i] = tablelist[0]; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); (*self->mode_func_ptr)(self); SET_INTERP_POINTER self->init = 1; return (PyObject *)self; } static PyObject * TableRead_getServer(TableRead* self) { GET_SERVER }; static PyObject * TableRead_getStream(TableRead* self) { GET_STREAM }; static PyObject * TableRead_getTriggerStream(TableRead* self) { GET_TRIGGER_STREAM }; static PyObject * TableRead_setMul(TableRead *self, PyObject *arg) { SET_MUL }; static PyObject * TableRead_setAdd(TableRead *self, PyObject *arg) { SET_ADD }; static PyObject * TableRead_setSub(TableRead *self, PyObject *arg) { SET_SUB }; static PyObject * TableRead_setDiv(TableRead *self, PyObject *arg) { SET_DIV }; static PyObject * TableRead_play(TableRead *self, PyObject *args, PyObject *kwds) { self->pointerPos = 0.0; self->init = 1; self->go = 1; PLAY }; static PyObject * TableRead_out(TableRead *self, PyObject *args, PyObject *kwds) { self->pointerPos = 0.0; self->init = 1; self->go = 1; OUT }; static PyObject * TableRead_stop(TableRead *self) { self->go = 0; STOP }; static PyObject * TableRead_multiply(TableRead *self, PyObject *arg) { MULTIPLY }; static PyObject * TableRead_inplace_multiply(TableRead *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TableRead_add(TableRead *self, PyObject *arg) { ADD }; static PyObject * TableRead_inplace_add(TableRead *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TableRead_sub(TableRead *self, PyObject *arg) { SUB }; static PyObject * TableRead_inplace_sub(TableRead *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TableRead_div(TableRead *self, PyObject *arg) { DIV }; static PyObject * TableRead_inplace_div(TableRead *self, PyObject *arg) { INPLACE_DIV }; static PyObject * TableRead_getTable(TableRead* self) { Py_INCREF(self->table); return self->table; }; static PyObject * TableRead_setTable(TableRead *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * TableRead_setFreq(TableRead *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * TableRead_setLoop(TableRead *self, PyObject *arg) { ASSERT_ARG_NOT_NULL self->loop = PyInt_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * TableRead_setInterp(TableRead *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->interp = PyInt_AsLong(PyNumber_Int(arg)); } SET_INTERP_POINTER Py_INCREF(Py_None); return Py_None; } static PyObject * TableRead_reset(TableRead *self) { self->pointerPos = 0.0; Py_INCREF(Py_None); return Py_None; } static PyMemberDef TableRead_members[] = { {"server", T_OBJECT_EX, offsetof(TableRead, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TableRead, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(TableRead, trig_stream), 0, "Trigger Stream object."}, {"table", T_OBJECT_EX, offsetof(TableRead, table), 0, "Waveform table."}, {"freq", T_OBJECT_EX, offsetof(TableRead, freq), 0, "Frequency in cycle per second."}, {"mul", T_OBJECT_EX, offsetof(TableRead, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TableRead, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TableRead_methods[] = { {"getTable", (PyCFunction)TableRead_getTable, METH_NOARGS, "Returns waveform table object."}, {"getServer", (PyCFunction)TableRead_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TableRead_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)TableRead_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"play", (PyCFunction)TableRead_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TableRead_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TableRead_stop, METH_NOARGS, "Stops computing."}, {"setTable", (PyCFunction)TableRead_setTable, METH_O, "Sets oscillator table."}, {"setFreq", (PyCFunction)TableRead_setFreq, METH_O, "Sets oscillator frequency in cycle per second."}, {"setLoop", (PyCFunction)TableRead_setLoop, METH_O, "Sets the looping mode."}, {"setInterp", (PyCFunction)TableRead_setInterp, METH_O, "Sets reader interpolation mode."}, {"reset", (PyCFunction)TableRead_reset, METH_NOARGS, "Resets pointer position to 0."}, {"setMul", (PyCFunction)TableRead_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TableRead_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TableRead_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)TableRead_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TableRead_as_number = { (binaryfunc)TableRead_add, /*nb_add*/ (binaryfunc)TableRead_sub, /*nb_subtract*/ (binaryfunc)TableRead_multiply, /*nb_multiply*/ (binaryfunc)TableRead_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TableRead_inplace_add, /*inplace_add*/ (binaryfunc)TableRead_inplace_sub, /*inplace_subtract*/ (binaryfunc)TableRead_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TableRead_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TableReadType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TableRead_base", /*tp_name*/ sizeof(TableRead), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TableRead_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TableRead_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TableRead objects. Generates an oscillatory waveform.", /* tp_doc */ (traverseproc)TableRead_traverse, /* tp_traverse */ (inquiry)TableRead_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TableRead_methods, /* tp_methods */ TableRead_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TableRead_new, /* tp_new */ }; /*************/ /* Fm object */ /*************/ typedef struct { pyo_audio_HEAD PyObject *car; Stream *car_stream; PyObject *ratio; Stream *ratio_stream; PyObject *index; Stream *index_stream; int modebuffer[5]; MYFLT pointerPos_car; MYFLT pointerPos_mod; MYFLT scaleFactor; } Fm; static void Fm_readframes_iii(Fm *self) { MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart; int i, ipart; MYFLT car = PyFloat_AS_DOUBLE(self->car); MYFLT rat = PyFloat_AS_DOUBLE(self->ratio); MYFLT ind = PyFloat_AS_DOUBLE(self->index); mod_freq = car * rat; mod_amp = mod_freq * ind; mod_delta = mod_freq * self->scaleFactor; for (i=0; ibufsize; i++) { self->pointerPos_mod = Sine_clip(self->pointerPos_mod); ipart = (int)self->pointerPos_mod; fpart = self->pointerPos_mod - ipart; mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart); self->pointerPos_mod += mod_delta; car_freq = car + mod_val; car_delta = car_freq * self->scaleFactor; self->pointerPos_car = Sine_clip(self->pointerPos_car); ipart = (int)self->pointerPos_car; fpart = self->pointerPos_car - ipart; self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos_car += car_delta; } } static void Fm_readframes_aii(Fm *self) { MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart; int i, ipart; MYFLT *car = Stream_getData((Stream *)self->car_stream); MYFLT rat = PyFloat_AS_DOUBLE(self->ratio); MYFLT ind = PyFloat_AS_DOUBLE(self->index); for (i=0; ibufsize; i++) { mod_freq = car[i] * rat; mod_amp = mod_freq * ind; mod_delta = mod_freq * self->scaleFactor; self->pointerPos_mod = Sine_clip(self->pointerPos_mod); ipart = (int)self->pointerPos_mod; fpart = self->pointerPos_mod - ipart; mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart); self->pointerPos_mod += mod_delta; car_freq = car[i] + mod_val; car_delta = car_freq * self->scaleFactor; self->pointerPos_car = Sine_clip(self->pointerPos_car); ipart = (int)self->pointerPos_car; fpart = self->pointerPos_car - ipart; self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos_car += car_delta; } } static void Fm_readframes_iai(Fm *self) { MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart; int i, ipart; MYFLT car = PyFloat_AS_DOUBLE(self->car); MYFLT *rat = Stream_getData((Stream *)self->ratio_stream); MYFLT ind = PyFloat_AS_DOUBLE(self->index); for (i=0; ibufsize; i++) { mod_freq = car * rat[i]; mod_amp = mod_freq * ind; mod_delta = mod_freq * self->scaleFactor; self->pointerPos_mod = Sine_clip(self->pointerPos_mod); ipart = (int)self->pointerPos_mod; fpart = self->pointerPos_mod - ipart; mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart); self->pointerPos_mod += mod_delta; car_freq = car + mod_val; car_delta = car_freq * self->scaleFactor; self->pointerPos_car = Sine_clip(self->pointerPos_car); ipart = (int)self->pointerPos_car; fpart = self->pointerPos_car - ipart; self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos_car += car_delta; } } static void Fm_readframes_aai(Fm *self) { MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart; int i, ipart; MYFLT *car = Stream_getData((Stream *)self->car_stream); MYFLT *rat = Stream_getData((Stream *)self->ratio_stream); MYFLT ind = PyFloat_AS_DOUBLE(self->index); for (i=0; ibufsize; i++) { mod_freq = car[i] * rat[i]; mod_amp = mod_freq * ind; mod_delta = mod_freq * self->scaleFactor; self->pointerPos_mod = Sine_clip(self->pointerPos_mod); ipart = (int)self->pointerPos_mod; fpart = self->pointerPos_mod - ipart; mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart); self->pointerPos_mod += mod_delta; car_freq = car[i] + mod_val; car_delta = car_freq * self->scaleFactor; self->pointerPos_car = Sine_clip(self->pointerPos_car); ipart = (int)self->pointerPos_car; fpart = self->pointerPos_car - ipart; self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos_car += car_delta; }} static void Fm_readframes_iia(Fm *self) { MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart; int i, ipart; MYFLT car = PyFloat_AS_DOUBLE(self->car); MYFLT rat = PyFloat_AS_DOUBLE(self->ratio); MYFLT *ind = Stream_getData((Stream *)self->index_stream); mod_freq = car * rat; mod_delta = mod_freq * self->scaleFactor; for (i=0; ibufsize; i++) { mod_amp = mod_freq * ind[i]; self->pointerPos_mod = Sine_clip(self->pointerPos_mod); ipart = (int)self->pointerPos_mod; fpart = self->pointerPos_mod - ipart; mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart); self->pointerPos_mod += mod_delta; car_freq = car + mod_val; car_delta = car_freq * self->scaleFactor; self->pointerPos_car = Sine_clip(self->pointerPos_car); ipart = (int)self->pointerPos_car; fpart = self->pointerPos_car - ipart; self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos_car += car_delta; } } static void Fm_readframes_aia(Fm *self) { MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart; int i, ipart; MYFLT *car = Stream_getData((Stream *)self->car_stream); MYFLT rat = PyFloat_AS_DOUBLE(self->ratio); MYFLT *ind = Stream_getData((Stream *)self->index_stream); for (i=0; ibufsize; i++) { mod_freq = car[i] * rat; mod_amp = mod_freq * ind[i]; mod_delta = mod_freq * self->scaleFactor; self->pointerPos_mod = Sine_clip(self->pointerPos_mod); ipart = (int)self->pointerPos_mod; fpart = self->pointerPos_mod - ipart; mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart); self->pointerPos_mod += mod_delta; car_freq = car[i] + mod_val; car_delta = car_freq * self->scaleFactor; self->pointerPos_car = Sine_clip(self->pointerPos_car); ipart = (int)self->pointerPos_car; fpart = self->pointerPos_car - ipart; self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos_car += car_delta; } } static void Fm_readframes_iaa(Fm *self) { MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart; int i, ipart; MYFLT car = PyFloat_AS_DOUBLE(self->car); MYFLT *rat = Stream_getData((Stream *)self->ratio_stream); MYFLT *ind = Stream_getData((Stream *)self->index_stream); for (i=0; ibufsize; i++) { mod_freq = car * rat[i]; mod_amp = mod_freq * ind[i]; mod_delta = mod_freq * self->scaleFactor; self->pointerPos_mod = Sine_clip(self->pointerPos_mod); ipart = (int)self->pointerPos_mod; fpart = self->pointerPos_mod - ipart; mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart); self->pointerPos_mod += mod_delta; car_freq = car + mod_val; car_delta = car_freq * self->scaleFactor; self->pointerPos_car = Sine_clip(self->pointerPos_car); ipart = (int)self->pointerPos_car; fpart = self->pointerPos_car - ipart; self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos_car += car_delta; } } static void Fm_readframes_aaa(Fm *self) { MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart; int i, ipart; MYFLT *car = Stream_getData((Stream *)self->car_stream); MYFLT *rat = Stream_getData((Stream *)self->ratio_stream); MYFLT *ind = Stream_getData((Stream *)self->index_stream); for (i=0; ibufsize; i++) { mod_freq = car[i] * rat[i]; mod_amp = mod_freq * ind[i]; mod_delta = mod_freq * self->scaleFactor; self->pointerPos_mod = Sine_clip(self->pointerPos_mod); ipart = (int)self->pointerPos_mod; fpart = self->pointerPos_mod - ipart; mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart); self->pointerPos_mod += mod_delta; car_freq = car[i] + mod_val; car_delta = car_freq * self->scaleFactor; self->pointerPos_car = Sine_clip(self->pointerPos_car); ipart = (int)self->pointerPos_car; fpart = self->pointerPos_car - ipart; self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos_car += car_delta; } } static void Fm_postprocessing_ii(Fm *self) { POST_PROCESSING_II }; static void Fm_postprocessing_ai(Fm *self) { POST_PROCESSING_AI }; static void Fm_postprocessing_ia(Fm *self) { POST_PROCESSING_IA }; static void Fm_postprocessing_aa(Fm *self) { POST_PROCESSING_AA }; static void Fm_postprocessing_ireva(Fm *self) { POST_PROCESSING_IREVA }; static void Fm_postprocessing_areva(Fm *self) { POST_PROCESSING_AREVA }; static void Fm_postprocessing_revai(Fm *self) { POST_PROCESSING_REVAI }; static void Fm_postprocessing_revaa(Fm *self) { POST_PROCESSING_REVAA }; static void Fm_postprocessing_revareva(Fm *self) { POST_PROCESSING_REVAREVA }; static void Fm_setProcMode(Fm *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Fm_readframes_iii; break; case 1: self->proc_func_ptr = Fm_readframes_aii; break; case 10: self->proc_func_ptr = Fm_readframes_iai; break; case 11: self->proc_func_ptr = Fm_readframes_aai; break; case 100: self->proc_func_ptr = Fm_readframes_iia; break; case 101: self->proc_func_ptr = Fm_readframes_aia; break; case 110: self->proc_func_ptr = Fm_readframes_iaa; break; case 111: self->proc_func_ptr = Fm_readframes_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Fm_postprocessing_ii; break; case 1: self->muladd_func_ptr = Fm_postprocessing_ai; break; case 2: self->muladd_func_ptr = Fm_postprocessing_revai; break; case 10: self->muladd_func_ptr = Fm_postprocessing_ia; break; case 11: self->muladd_func_ptr = Fm_postprocessing_aa; break; case 12: self->muladd_func_ptr = Fm_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Fm_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Fm_postprocessing_areva; break; case 22: self->muladd_func_ptr = Fm_postprocessing_revareva; break; } } static void Fm_compute_next_data_frame(Fm *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Fm_traverse(Fm *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->car); Py_VISIT(self->car_stream); Py_VISIT(self->ratio); Py_VISIT(self->ratio_stream); Py_VISIT(self->index); Py_VISIT(self->index_stream); return 0; } static int Fm_clear(Fm *self) { pyo_CLEAR Py_CLEAR(self->car); Py_CLEAR(self->car_stream); Py_CLEAR(self->ratio); Py_CLEAR(self->ratio_stream); Py_CLEAR(self->index); Py_CLEAR(self->index_stream); return 0; } static void Fm_dealloc(Fm* self) { pyo_DEALLOC Fm_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Fm_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *cartmp=NULL, *ratiotmp=NULL, *indextmp=NULL, *multmp=NULL, *addtmp=NULL; Fm *self; self = (Fm *)type->tp_alloc(type, 0); self->car = PyFloat_FromDouble(100); self->ratio = PyFloat_FromDouble(0.5); self->index = PyFloat_FromDouble(5); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->pointerPos_car = self->pointerPos_mod = 0.; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Fm_compute_next_data_frame); self->mode_func_ptr = Fm_setProcMode; self->scaleFactor = 512.0 / self->sr; static char *kwlist[] = {"carrier", "ratio", "index", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &cartmp, &ratiotmp, &indextmp, &multmp, &addtmp)) Py_RETURN_NONE; if (cartmp) { PyObject_CallMethod((PyObject *)self, "setCarrier", "O", cartmp); } if (ratiotmp) { PyObject_CallMethod((PyObject *)self, "setRatio", "O", ratiotmp); } if (indextmp) { PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Fm_getServer(Fm* self) { GET_SERVER }; static PyObject * Fm_getStream(Fm* self) { GET_STREAM }; static PyObject * Fm_setMul(Fm *self, PyObject *arg) { SET_MUL }; static PyObject * Fm_setAdd(Fm *self, PyObject *arg) { SET_ADD }; static PyObject * Fm_setSub(Fm *self, PyObject *arg) { SET_SUB }; static PyObject * Fm_setDiv(Fm *self, PyObject *arg) { SET_DIV }; static PyObject * Fm_play(Fm *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Fm_out(Fm *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Fm_stop(Fm *self) { STOP }; static PyObject * Fm_multiply(Fm *self, PyObject *arg) { MULTIPLY }; static PyObject * Fm_inplace_multiply(Fm *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Fm_add(Fm *self, PyObject *arg) { ADD }; static PyObject * Fm_inplace_add(Fm *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Fm_sub(Fm *self, PyObject *arg) { SUB }; static PyObject * Fm_inplace_sub(Fm *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Fm_div(Fm *self, PyObject *arg) { DIV }; static PyObject * Fm_inplace_div(Fm *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Fm_setCarrier(Fm *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->car); if (isNumber == 1) { self->car = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->car = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->car, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->car_stream); self->car_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Fm_setRatio(Fm *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->ratio); if (isNumber == 1) { self->ratio = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->ratio = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->ratio, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->ratio_stream); self->ratio_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Fm_setIndex(Fm *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->index); if (isNumber == 1) { self->index = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->index = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->index_stream); self->index_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Fm_members[] = { {"server", T_OBJECT_EX, offsetof(Fm, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Fm, stream), 0, "Stream object."}, {"carrier", T_OBJECT_EX, offsetof(Fm, car), 0, "Frequency in cycle per second."}, {"ratio", T_OBJECT_EX, offsetof(Fm, ratio), 0, "Ratio carrier:modulator (mod freq = car*mod)."}, {"index", T_OBJECT_EX, offsetof(Fm, index), 0, "Modulation index (mod amp = mod freq*index)."}, {"mul", T_OBJECT_EX, offsetof(Fm, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Fm, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Fm_methods[] = { {"getServer", (PyCFunction)Fm_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Fm_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Fm_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Fm_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Fm_stop, METH_NOARGS, "Stops computing."}, {"setCarrier", (PyCFunction)Fm_setCarrier, METH_O, "Sets carrier frequency in cycle per second."}, {"setRatio", (PyCFunction)Fm_setRatio, METH_O, "Sets car:mod ratio."}, {"setIndex", (PyCFunction)Fm_setIndex, METH_O, "Sets modulation index."}, {"setMul", (PyCFunction)Fm_setMul, METH_O, "Sets Fm mul factor."}, {"setAdd", (PyCFunction)Fm_setAdd, METH_O, "Sets Fm add factor."}, {"setSub", (PyCFunction)Fm_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Fm_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Fm_as_number = { (binaryfunc)Fm_add, /*nb_add*/ (binaryfunc)Fm_sub, /*nb_subtract*/ (binaryfunc)Fm_multiply, /*nb_multiply*/ (binaryfunc)Fm_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Fm_inplace_add, /*inplace_add*/ (binaryfunc)Fm_inplace_sub, /*inplace_subtract*/ (binaryfunc)Fm_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Fm_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject FmType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Fm_base", /*tp_name*/ sizeof(Fm), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Fm_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Fm_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Fm objects. Generates a frequency modulation synthesis.", /* tp_doc */ (traverseproc)Fm_traverse, /* tp_traverse */ (inquiry)Fm_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Fm_methods, /* tp_methods */ Fm_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Fm_new, /* tp_new */ }; /*************/ /* CrossFm object */ /*************/ typedef struct { pyo_audio_HEAD PyObject *car; Stream *car_stream; PyObject *ratio; Stream *ratio_stream; PyObject *ind1; Stream *ind1_stream; PyObject *ind2; Stream *ind2_stream; int modebuffer[6]; MYFLT pointerPos_car; MYFLT pointerPos_mod; MYFLT scaleFactor; MYFLT car_val; } CrossFm; static void CrossFm_readframes(CrossFm *self) { MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_amp, car_delta, fpart; int i, ipart; MYFLT car[self->bufsize]; MYFLT rat[self->bufsize]; MYFLT ind1[self->bufsize]; MYFLT ind2[self->bufsize]; if (self->modebuffer[2] == 0) { MYFLT tmpcar = PyFloat_AS_DOUBLE(self->car); for (i=0; ibufsize; i++) { car[i] = tmpcar; } } else { MYFLT *tmpcar = Stream_getData((Stream *)self->car_stream); for (i=0; ibufsize; i++) { car[i] = tmpcar[i]; } } if (self->modebuffer[3] == 0) { MYFLT tmprat = PyFloat_AS_DOUBLE(self->ratio); for (i=0; ibufsize; i++) { rat[i] = tmprat; } } else { MYFLT *tmprat = Stream_getData((Stream *)self->ratio_stream); for (i=0; ibufsize; i++) { rat[i] = tmprat[i]; } } if (self->modebuffer[4] == 0) { MYFLT tmpind1 = PyFloat_AS_DOUBLE(self->ind1); for (i=0; ibufsize; i++) { ind1[i] = tmpind1; } } else { MYFLT *tmpind1 = Stream_getData((Stream *)self->ind1_stream); for (i=0; ibufsize; i++) { ind1[i] = tmpind1[i]; } } if (self->modebuffer[5] == 0) { MYFLT tmpind2 = PyFloat_AS_DOUBLE(self->ind2); for (i=0; ibufsize; i++) { ind2[i] = tmpind2; } } else { MYFLT *tmpind2 = Stream_getData((Stream *)self->ind2_stream); for (i=0; ibufsize; i++) { ind2[i] = tmpind2[i]; } } for (i=0; ibufsize; i++) { car_amp = car[i] * ind1[i]; mod_freq = car[i] * rat[i]; mod_amp = mod_freq * ind2[i]; mod_delta = (mod_freq + self->car_val * car_amp) * self->scaleFactor; self->pointerPos_mod = Sine_clip(self->pointerPos_mod); ipart = (int)self->pointerPos_mod; fpart = self->pointerPos_mod - ipart; mod_val = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos_mod += mod_delta; car_freq = car[i] + (mod_val * mod_amp); car_delta = car_freq * self->scaleFactor; self->pointerPos_car = Sine_clip(self->pointerPos_car); ipart = (int)self->pointerPos_car; fpart = self->pointerPos_car - ipart; self->car_val = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart; self->pointerPos_car += car_delta; self->data[i] = (self->car_val + mod_val) * 0.5; } } static void CrossFm_postprocessing_ii(CrossFm *self) { POST_PROCESSING_II }; static void CrossFm_postprocessing_ai(CrossFm *self) { POST_PROCESSING_AI }; static void CrossFm_postprocessing_ia(CrossFm *self) { POST_PROCESSING_IA }; static void CrossFm_postprocessing_aa(CrossFm *self) { POST_PROCESSING_AA }; static void CrossFm_postprocessing_ireva(CrossFm *self) { POST_PROCESSING_IREVA }; static void CrossFm_postprocessing_areva(CrossFm *self) { POST_PROCESSING_AREVA }; static void CrossFm_postprocessing_revai(CrossFm *self) { POST_PROCESSING_REVAI }; static void CrossFm_postprocessing_revaa(CrossFm *self) { POST_PROCESSING_REVAA }; static void CrossFm_postprocessing_revareva(CrossFm *self) { POST_PROCESSING_REVAREVA }; static void CrossFm_setProcMode(CrossFm *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = CrossFm_readframes; switch (muladdmode) { case 0: self->muladd_func_ptr = CrossFm_postprocessing_ii; break; case 1: self->muladd_func_ptr = CrossFm_postprocessing_ai; break; case 2: self->muladd_func_ptr = CrossFm_postprocessing_revai; break; case 10: self->muladd_func_ptr = CrossFm_postprocessing_ia; break; case 11: self->muladd_func_ptr = CrossFm_postprocessing_aa; break; case 12: self->muladd_func_ptr = CrossFm_postprocessing_revaa; break; case 20: self->muladd_func_ptr = CrossFm_postprocessing_ireva; break; case 21: self->muladd_func_ptr = CrossFm_postprocessing_areva; break; case 22: self->muladd_func_ptr = CrossFm_postprocessing_revareva; break; } } static void CrossFm_compute_next_data_frame(CrossFm *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int CrossFm_traverse(CrossFm *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->car); Py_VISIT(self->car_stream); Py_VISIT(self->ratio); Py_VISIT(self->ratio_stream); Py_VISIT(self->ind1); Py_VISIT(self->ind1_stream); Py_VISIT(self->ind2); Py_VISIT(self->ind2_stream); return 0; } static int CrossFm_clear(CrossFm *self) { pyo_CLEAR Py_CLEAR(self->car); Py_CLEAR(self->car_stream); Py_CLEAR(self->ratio); Py_CLEAR(self->ratio_stream); Py_CLEAR(self->ind1); Py_CLEAR(self->ind1_stream); Py_CLEAR(self->ind2); Py_CLEAR(self->ind2_stream); return 0; } static void CrossFm_dealloc(CrossFm* self) { pyo_DEALLOC CrossFm_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * CrossFm_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *cartmp=NULL, *ratiotmp=NULL, *ind1tmp=NULL, *ind2tmp=NULL, *multmp=NULL, *addtmp=NULL; CrossFm *self; self = (CrossFm *)type->tp_alloc(type, 0); self->car = PyFloat_FromDouble(100); self->ratio = PyFloat_FromDouble(0.5); self->ind1 = PyFloat_FromDouble(2); self->ind2 = PyFloat_FromDouble(2); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->modebuffer[5] = 0; self->pointerPos_car = self->pointerPos_mod = 0.; self->car_val = 0.; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, CrossFm_compute_next_data_frame); self->mode_func_ptr = CrossFm_setProcMode; self->scaleFactor = 512.0 / self->sr; static char *kwlist[] = {"carrier", "ratio", "ind1", "ind2", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOO", kwlist, &cartmp, &ratiotmp, &ind1tmp, &ind2tmp, &multmp, &addtmp)) Py_RETURN_NONE; if (cartmp) { PyObject_CallMethod((PyObject *)self, "setCarrier", "O", cartmp); } if (ratiotmp) { PyObject_CallMethod((PyObject *)self, "setRatio", "O", ratiotmp); } if (ind1tmp) { PyObject_CallMethod((PyObject *)self, "setInd1", "O", ind1tmp); } if (ind2tmp) { PyObject_CallMethod((PyObject *)self, "setInd2", "O", ind2tmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * CrossFm_getServer(CrossFm* self) { GET_SERVER }; static PyObject * CrossFm_getStream(CrossFm* self) { GET_STREAM }; static PyObject * CrossFm_setMul(CrossFm *self, PyObject *arg) { SET_MUL }; static PyObject * CrossFm_setAdd(CrossFm *self, PyObject *arg) { SET_ADD }; static PyObject * CrossFm_setSub(CrossFm *self, PyObject *arg) { SET_SUB }; static PyObject * CrossFm_setDiv(CrossFm *self, PyObject *arg) { SET_DIV }; static PyObject * CrossFm_play(CrossFm *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * CrossFm_out(CrossFm *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * CrossFm_stop(CrossFm *self) { STOP }; static PyObject * CrossFm_multiply(CrossFm *self, PyObject *arg) { MULTIPLY }; static PyObject * CrossFm_inplace_multiply(CrossFm *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * CrossFm_add(CrossFm *self, PyObject *arg) { ADD }; static PyObject * CrossFm_inplace_add(CrossFm *self, PyObject *arg) { INPLACE_ADD }; static PyObject * CrossFm_sub(CrossFm *self, PyObject *arg) { SUB }; static PyObject * CrossFm_inplace_sub(CrossFm *self, PyObject *arg) { INPLACE_SUB }; static PyObject * CrossFm_div(CrossFm *self, PyObject *arg) { DIV }; static PyObject * CrossFm_inplace_div(CrossFm *self, PyObject *arg) { INPLACE_DIV }; static PyObject * CrossFm_setCarrier(CrossFm *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->car); if (isNumber == 1) { self->car = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->car = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->car, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->car_stream); self->car_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * CrossFm_setRatio(CrossFm *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->ratio); if (isNumber == 1) { self->ratio = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->ratio = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->ratio, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->ratio_stream); self->ratio_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * CrossFm_setInd1(CrossFm *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->ind1); if (isNumber == 1) { self->ind1 = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->ind1 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->ind1, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->ind1_stream); self->ind1_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * CrossFm_setInd2(CrossFm *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->ind2); if (isNumber == 1) { self->ind2 = PyNumber_Float(tmp); self->modebuffer[5] = 0; } else { self->ind2 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->ind2, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->ind2_stream); self->ind2_stream = (Stream *)streamtmp; self->modebuffer[5] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef CrossFm_members[] = { {"server", T_OBJECT_EX, offsetof(CrossFm, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(CrossFm, stream), 0, "Stream object."}, {"carrier", T_OBJECT_EX, offsetof(CrossFm, car), 0, "Frequency in cycle per second."}, {"ratio", T_OBJECT_EX, offsetof(CrossFm, ratio), 0, "Ratio carrier:modulator (mod freq = car*mod)."}, {"ind1", T_OBJECT_EX, offsetof(CrossFm, ind1), 0, "Modulation ind1 (car amp = car freq*ind1)."}, {"ind2", T_OBJECT_EX, offsetof(CrossFm, ind2), 0, "Modulation ind2 (mod amp = mod freq*ind2)."}, {"mul", T_OBJECT_EX, offsetof(CrossFm, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(CrossFm, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef CrossFm_methods[] = { {"getServer", (PyCFunction)CrossFm_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)CrossFm_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)CrossFm_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)CrossFm_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)CrossFm_stop, METH_NOARGS, "Stops computing."}, {"setCarrier", (PyCFunction)CrossFm_setCarrier, METH_O, "Sets carrier frequency in cycle per second."}, {"setRatio", (PyCFunction)CrossFm_setRatio, METH_O, "Sets car:mod ratio."}, {"setInd1", (PyCFunction)CrossFm_setInd1, METH_O, "Sets carrier index."}, {"setInd2", (PyCFunction)CrossFm_setInd2, METH_O, "Sets modulation index."}, {"setMul", (PyCFunction)CrossFm_setMul, METH_O, "Sets CrossFm mul factor."}, {"setAdd", (PyCFunction)CrossFm_setAdd, METH_O, "Sets CrossFm add factor."}, {"setSub", (PyCFunction)CrossFm_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)CrossFm_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods CrossFm_as_number = { (binaryfunc)CrossFm_add, /*nb_add*/ (binaryfunc)CrossFm_sub, /*nb_subtract*/ (binaryfunc)CrossFm_multiply, /*nb_multiply*/ (binaryfunc)CrossFm_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)CrossFm_inplace_add, /*inplace_add*/ (binaryfunc)CrossFm_inplace_sub, /*inplace_subtract*/ (binaryfunc)CrossFm_inplace_multiply, /*inplace_multiply*/ (binaryfunc)CrossFm_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_ind1 */ }; PyTypeObject CrossFmType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.CrossFm_base", /*tp_name*/ sizeof(CrossFm), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)CrossFm_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &CrossFm_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "CrossFm objects. Generates a cross frequency modulation synthesis.", /* tp_doc */ (traverseproc)CrossFm_traverse, /* tp_traverse */ (inquiry)CrossFm_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ CrossFm_methods, /* tp_methods */ CrossFm_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ CrossFm_new, /* tp_new */ }; /*************/ /* Blit object */ /*************/ typedef struct { pyo_audio_HEAD PyObject *freq; Stream *freq_stream; PyObject *harms; Stream *harms_stream; int modebuffer[4]; MYFLT phase; } Blit; static void Blit_readframes_ii(Blit *self) { MYFLT p, m, rate, val; int i, nHarms; MYFLT freq = PyFloat_AS_DOUBLE(self->freq); MYFLT hrms = PyFloat_AS_DOUBLE(self->harms); nHarms = (int)hrms; m = 2.0 * nHarms + 1.0; p = self->sr / freq; rate = PI / p; for (i=0; ibufsize; i++) { if (self->phase <= 0.0) val = 1.0; else { val = MYSIN(m * self->phase); val /= m * MYSIN(self->phase); } self->phase += rate; if (self->phase >= PI) self->phase -= PI; self->data[i] = val; } } static void Blit_readframes_ai(Blit *self) { MYFLT p, m, rate, val; int i, nHarms; MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT hrms = PyFloat_AS_DOUBLE(self->harms); nHarms = (int)hrms; m = 2.0 * nHarms + 1.0; for (i=0; ibufsize; i++) { p = self->sr / freq[i]; rate = PI / p; if (self->phase <= 0.0) val = 1.0; else { val = MYSIN(m * self->phase); val /= m * MYSIN(self->phase); } self->phase += rate; if (self->phase >= PI) self->phase -= PI; self->data[i] = val; } } static void Blit_readframes_ia(Blit *self) { MYFLT p, m, rate, val; int i, nHarms; MYFLT freq = PyFloat_AS_DOUBLE(self->freq); MYFLT *hrms = Stream_getData((Stream *)self->harms_stream); p = self->sr / freq; rate = PI / p; for (i=0; ibufsize; i++) { nHarms = (int)hrms[i]; m = 2.0 * nHarms + 1.0; if (self->phase <= 0.0) val = 1.0; else { val = MYSIN(m * self->phase); val /= m * MYSIN(self->phase); } self->phase += rate; if (self->phase >= PI) self->phase -= PI; self->data[i] = val; } } static void Blit_readframes_aa(Blit *self) { MYFLT p, m, rate, val; int i, nHarms; MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT *hrms = Stream_getData((Stream *)self->harms_stream); for (i=0; ibufsize; i++) { nHarms = (int)hrms[i]; m = 2.0 * nHarms + 1.0; p = self->sr / freq[i]; rate = PI / p; if (self->phase <= 0.0) val = 1.0; else { val = MYSIN(m * self->phase); val /= m * MYSIN(self->phase); } self->phase += rate; if (self->phase >= PI) self->phase -= PI; self->data[i] = val; } } static void Blit_postprocessing_ii(Blit *self) { POST_PROCESSING_II }; static void Blit_postprocessing_ai(Blit *self) { POST_PROCESSING_AI }; static void Blit_postprocessing_ia(Blit *self) { POST_PROCESSING_IA }; static void Blit_postprocessing_aa(Blit *self) { POST_PROCESSING_AA }; static void Blit_postprocessing_ireva(Blit *self) { POST_PROCESSING_IREVA }; static void Blit_postprocessing_areva(Blit *self) { POST_PROCESSING_AREVA }; static void Blit_postprocessing_revai(Blit *self) { POST_PROCESSING_REVAI }; static void Blit_postprocessing_revaa(Blit *self) { POST_PROCESSING_REVAA }; static void Blit_postprocessing_revareva(Blit *self) { POST_PROCESSING_REVAREVA }; static void Blit_setProcMode(Blit *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Blit_readframes_ii; break; case 1: self->proc_func_ptr = Blit_readframes_ai; break; case 10: self->proc_func_ptr = Blit_readframes_ia; break; case 11: self->proc_func_ptr = Blit_readframes_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Blit_postprocessing_ii; break; case 1: self->muladd_func_ptr = Blit_postprocessing_ai; break; case 2: self->muladd_func_ptr = Blit_postprocessing_revai; break; case 10: self->muladd_func_ptr = Blit_postprocessing_ia; break; case 11: self->muladd_func_ptr = Blit_postprocessing_aa; break; case 12: self->muladd_func_ptr = Blit_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Blit_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Blit_postprocessing_areva; break; case 22: self->muladd_func_ptr = Blit_postprocessing_revareva; break; } } static void Blit_compute_next_data_frame(Blit *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Blit_traverse(Blit *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->harms); Py_VISIT(self->harms_stream); return 0; } static int Blit_clear(Blit *self) { pyo_CLEAR Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->harms); Py_CLEAR(self->harms_stream); return 0; } static void Blit_dealloc(Blit* self) { pyo_DEALLOC Blit_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Blit_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *freqtmp=NULL, *harmstmp=NULL, *multmp=NULL, *addtmp=NULL; Blit *self; self = (Blit *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(100); self->harms = PyFloat_FromDouble(40); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->phase = 0.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Blit_compute_next_data_frame); self->mode_func_ptr = Blit_setProcMode; static char *kwlist[] = {"freq", "harms", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &harmstmp, &multmp, &addtmp)) Py_RETURN_NONE; if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (harmstmp) { PyObject_CallMethod((PyObject *)self, "setHarms", "O", harmstmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Blit_getServer(Blit* self) { GET_SERVER }; static PyObject * Blit_getStream(Blit* self) { GET_STREAM }; static PyObject * Blit_setMul(Blit *self, PyObject *arg) { SET_MUL }; static PyObject * Blit_setAdd(Blit *self, PyObject *arg) { SET_ADD }; static PyObject * Blit_setSub(Blit *self, PyObject *arg) { SET_SUB }; static PyObject * Blit_setDiv(Blit *self, PyObject *arg) { SET_DIV }; static PyObject * Blit_play(Blit *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Blit_out(Blit *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Blit_stop(Blit *self) { STOP }; static PyObject * Blit_multiply(Blit *self, PyObject *arg) { MULTIPLY }; static PyObject * Blit_inplace_multiply(Blit *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Blit_add(Blit *self, PyObject *arg) { ADD }; static PyObject * Blit_inplace_add(Blit *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Blit_sub(Blit *self, PyObject *arg) { SUB }; static PyObject * Blit_inplace_sub(Blit *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Blit_div(Blit *self, PyObject *arg) { DIV }; static PyObject * Blit_inplace_div(Blit *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Blit_setFreq(Blit *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Blit_setHarms(Blit *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->harms); if (isNumber == 1) { self->harms = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->harms = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->harms, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->harms_stream); self->harms_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Blit_members[] = { {"server", T_OBJECT_EX, offsetof(Blit, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Blit, stream), 0, "Stream object."}, {"freq", T_OBJECT_EX, offsetof(Blit, freq), 0, "Frequency in cycle per second."}, {"harms", T_OBJECT_EX, offsetof(Blit, harms), 0, "Number of harmonics."}, {"mul", T_OBJECT_EX, offsetof(Blit, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Blit, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Blit_methods[] = { {"getServer", (PyCFunction)Blit_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Blit_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Blit_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundfreqd."}, {"out", (PyCFunction)Blit_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundfreqd channel speficied by argument."}, {"stop", (PyCFunction)Blit_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Blit_setFreq, METH_O, "Sets frequency in cycle per second."}, {"setHarms", (PyCFunction)Blit_setHarms, METH_O, "Sets the number of harmonics."}, {"setMul", (PyCFunction)Blit_setMul, METH_O, "Sets Blit mul factor."}, {"setAdd", (PyCFunction)Blit_setAdd, METH_O, "Sets Blit add factor."}, {"setSub", (PyCFunction)Blit_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Blit_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Blit_as_number = { (binaryfunc)Blit_add, /*nb_add*/ (binaryfunc)Blit_sub, /*nb_subtract*/ (binaryfunc)Blit_multiply, /*nb_multiply*/ (binaryfunc)Blit_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Blit_inplace_add, /*inplace_add*/ (binaryfunc)Blit_inplace_sub, /*inplace_subtract*/ (binaryfunc)Blit_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Blit_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_cutoff */ }; PyTypeObject BlitType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Blit_base", /*tp_name*/ sizeof(Blit), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Blit_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Blit_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Blit objects. Generates a band limited impulse train.", /* tp_doc */ (traverseproc)Blit_traverse, /* tp_traverse */ (inquiry)Blit_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Blit_methods, /* tp_methods */ Blit_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Blit_new, /* tp_new */ }; /* Rossler object */ typedef struct { pyo_audio_HEAD PyObject *pitch; Stream *pitch_stream; PyObject *chaos; Stream *chaos_stream; MYFLT *altBuffer; MYFLT vDX; MYFLT vDY; MYFLT vDZ; MYFLT vX; MYFLT vY; MYFLT vZ; MYFLT pA; MYFLT pB; MYFLT scalePitch; int modebuffer[4]; } Rossler; static void Rossler_readframes_ii(Rossler *self) { MYFLT delta, pit, chao; int i; pit = PyFloat_AS_DOUBLE(self->pitch); chao = PyFloat_AS_DOUBLE(self->chaos); if (pit < 0.0) pit = 1.0; else if (pit > 1.0) pit = 1000.0; else pit = pit * 999.0 + 1.0; delta = self->scalePitch * pit; if (chao < 0.0) chao = 3.0; else if (chao > 1.0) chao = 10.0; else chao = chao * 7.0 + 3.0; for (i=0; ibufsize; i++) { self->vDX = -self->vY - self->vZ; self->vDY = self->vX + self->pA * self->vY; self->vDZ = self->pB + self->vZ * (self->vX - chao); self->vX += self->vDX * delta; self->vY += self->vDY * delta; self->vZ += self->vDZ * delta; self->data[i] = self->vX * ROSSLER_SCALE; self->altBuffer[i] = self->vY * ROSSLER_ALT_SCALE; } } static void Rossler_readframes_ai(Rossler *self) { MYFLT delta, pit, chao; int i; MYFLT *fr = Stream_getData((Stream *)self->pitch_stream); chao = PyFloat_AS_DOUBLE(self->chaos); if (chao < 0.0) chao = 3.0; else if (chao > 1.0) chao = 10.0; else chao = chao * 7.0 + 3.0; for (i=0; ibufsize; i++) { pit = fr[i]; if (pit < 0.0) pit = 1.0; else if (pit > 1.0) pit = 1000.0; else pit = pit * 999.0 + 1.0; delta = self->scalePitch * pit; self->vDX = -self->vY - self->vZ; self->vDY = self->vX + self->pA * self->vY; self->vDZ = self->pB + self->vZ * (self->vX - chao); self->vX += self->vDX * delta; self->vY += self->vDY * delta; self->vZ += self->vDZ * delta; self->data[i] = self->vX * ROSSLER_SCALE; self->altBuffer[i] = self->vY * ROSSLER_ALT_SCALE; } } static void Rossler_readframes_ia(Rossler *self) { MYFLT delta, pit, chao; int i; pit = PyFloat_AS_DOUBLE(self->pitch); MYFLT *ch = Stream_getData((Stream *)self->chaos_stream); if (pit < 0.0) pit = 1.0; else if (pit > 1.0) pit = 1000.0; else pit = pit * 999.0 + 1.0; delta = self->scalePitch * pit; for (i=0; ibufsize; i++) { chao = ch[i]; if (chao < 0.0) chao = 3.0; else if (chao > 1.0) chao = 10.0; else chao = chao * 7.0 + 3.0; self->vDX = -self->vY - self->vZ; self->vDY = self->vX + self->pA * self->vY; self->vDZ = self->pB + self->vZ * (self->vX - chao); self->vX += self->vDX * delta; self->vY += self->vDY * delta; self->vZ += self->vDZ * delta; self->data[i] = self->vX * ROSSLER_SCALE; self->altBuffer[i] = self->vY * ROSSLER_ALT_SCALE; } } static void Rossler_readframes_aa(Rossler *self) { MYFLT delta, pit, chao; int i; MYFLT *fr = Stream_getData((Stream *)self->pitch_stream); MYFLT *ch = Stream_getData((Stream *)self->chaos_stream); for (i=0; ibufsize; i++) { pit = fr[i]; if (pit < 0.0) pit = 1.0; else if (pit > 1.0) pit = 1000.0; else pit = pit * 999.0 + 1.0; delta = self->scalePitch * pit; chao = ch[i]; if (chao < 0.0) chao = 3.0; else if (chao > 1.0) chao = 10.0; else chao = chao * 7.0 + 3.0; self->vDX = -self->vY - self->vZ; self->vDY = self->vX + self->pA * self->vY; self->vDZ = self->pB + self->vZ * (self->vX - chao); self->vX += self->vDX * delta; self->vY += self->vDY * delta; self->vZ += self->vDZ * delta; self->data[i] = self->vX * ROSSLER_SCALE; self->altBuffer[i] = self->vY * ROSSLER_ALT_SCALE; } } static void Rossler_postprocessing_ii(Rossler *self) { POST_PROCESSING_II }; static void Rossler_postprocessing_ai(Rossler *self) { POST_PROCESSING_AI }; static void Rossler_postprocessing_ia(Rossler *self) { POST_PROCESSING_IA }; static void Rossler_postprocessing_aa(Rossler *self) { POST_PROCESSING_AA }; static void Rossler_postprocessing_ireva(Rossler *self) { POST_PROCESSING_IREVA }; static void Rossler_postprocessing_areva(Rossler *self) { POST_PROCESSING_AREVA }; static void Rossler_postprocessing_revai(Rossler *self) { POST_PROCESSING_REVAI }; static void Rossler_postprocessing_revaa(Rossler *self) { POST_PROCESSING_REVAA }; static void Rossler_postprocessing_revareva(Rossler *self) { POST_PROCESSING_REVAREVA }; static void Rossler_setProcMode(Rossler *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Rossler_readframes_ii; break; case 1: self->proc_func_ptr = Rossler_readframes_ai; break; case 10: self->proc_func_ptr = Rossler_readframes_ia; break; case 11: self->proc_func_ptr = Rossler_readframes_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Rossler_postprocessing_ii; break; case 1: self->muladd_func_ptr = Rossler_postprocessing_ai; break; case 2: self->muladd_func_ptr = Rossler_postprocessing_revai; break; case 10: self->muladd_func_ptr = Rossler_postprocessing_ia; break; case 11: self->muladd_func_ptr = Rossler_postprocessing_aa; break; case 12: self->muladd_func_ptr = Rossler_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Rossler_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Rossler_postprocessing_areva; break; case 22: self->muladd_func_ptr = Rossler_postprocessing_revareva; break; } } static void Rossler_compute_next_data_frame(Rossler *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Rossler_traverse(Rossler *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->pitch); Py_VISIT(self->pitch_stream); Py_VISIT(self->chaos); Py_VISIT(self->chaos_stream); return 0; } static int Rossler_clear(Rossler *self) { pyo_CLEAR Py_CLEAR(self->pitch); Py_CLEAR(self->pitch_stream); Py_CLEAR(self->chaos); Py_CLEAR(self->chaos_stream); return 0; } static void Rossler_dealloc(Rossler* self) { pyo_DEALLOC free(self->altBuffer); Rossler_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Rossler_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *pitchtmp=NULL, *chaostmp=NULL, *multmp=NULL, *addtmp=NULL; Rossler *self; self = (Rossler *)type->tp_alloc(type, 0); self->pitch = PyFloat_FromDouble(0.25); self->chaos = PyFloat_FromDouble(0.5); self->pA = 0.15; self->pB = 0.20; self->vDX = self->vDY = self->vDZ = 0.0; self->vX = self->vY = self->vZ = 1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Rossler_compute_next_data_frame); self->mode_func_ptr = Rossler_setProcMode; self->scalePitch = 2.91 / self->sr; static char *kwlist[] = {"pitch", "chaos", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &pitchtmp, &chaostmp, &multmp, &addtmp)) Py_RETURN_NONE; if (pitchtmp) { PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp); } if (chaostmp) { PyObject_CallMethod((PyObject *)self, "setChaos", "O", chaostmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->altBuffer = (MYFLT *)realloc(self->altBuffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->altBuffer[i] = 0.0; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Rossler_getServer(Rossler* self) { GET_SERVER }; static PyObject * Rossler_getStream(Rossler* self) { GET_STREAM }; static PyObject * Rossler_setMul(Rossler *self, PyObject *arg) { SET_MUL }; static PyObject * Rossler_setAdd(Rossler *self, PyObject *arg) { SET_ADD }; static PyObject * Rossler_setSub(Rossler *self, PyObject *arg) { SET_SUB }; static PyObject * Rossler_setDiv(Rossler *self, PyObject *arg) { SET_DIV }; static PyObject * Rossler_play(Rossler *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Rossler_out(Rossler *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Rossler_stop(Rossler *self) { STOP }; static PyObject * Rossler_multiply(Rossler *self, PyObject *arg) { MULTIPLY }; static PyObject * Rossler_inplace_multiply(Rossler *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Rossler_add(Rossler *self, PyObject *arg) { ADD }; static PyObject * Rossler_inplace_add(Rossler *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Rossler_sub(Rossler *self, PyObject *arg) { SUB }; static PyObject * Rossler_inplace_sub(Rossler *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Rossler_div(Rossler *self, PyObject *arg) { DIV }; static PyObject * Rossler_inplace_div(Rossler *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Rossler_setPitch(Rossler *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pitch); if (isNumber == 1) { self->pitch = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->pitch = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pitch, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pitch_stream); self->pitch_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Rossler_setChaos(Rossler *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->chaos); if (isNumber == 1) { self->chaos = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->chaos = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->chaos, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->chaos_stream); self->chaos_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } MYFLT * Rossler_getAltBuffer(Rossler *self) { return (MYFLT *)self->altBuffer; } static PyMemberDef Rossler_members[] = { {"server", T_OBJECT_EX, offsetof(Rossler, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Rossler, stream), 0, "Stream object."}, {"pitch", T_OBJECT_EX, offsetof(Rossler, pitch), 0, "Pitch."}, {"chaos", T_OBJECT_EX, offsetof(Rossler, chaos), 0, "Chaotic behavior."}, {"mul", T_OBJECT_EX, offsetof(Rossler, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Rossler, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Rossler_methods[] = { {"getServer", (PyCFunction)Rossler_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Rossler_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Rossler_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Rossler_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Rossler_stop, METH_NOARGS, "Stops computing."}, {"setPitch", (PyCFunction)Rossler_setPitch, METH_O, "Sets oscillator pitch."}, {"setChaos", (PyCFunction)Rossler_setChaos, METH_O, "Sets oscillator chaotic behavior."}, {"setMul", (PyCFunction)Rossler_setMul, METH_O, "Sets Rossler mul factor."}, {"setAdd", (PyCFunction)Rossler_setAdd, METH_O, "Sets Rossler add factor."}, {"setSub", (PyCFunction)Rossler_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Rossler_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Rossler_as_number = { (binaryfunc)Rossler_add, /*nb_add*/ (binaryfunc)Rossler_sub, /*nb_subtract*/ (binaryfunc)Rossler_multiply, /*nb_multiply*/ (binaryfunc)Rossler_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Rossler_inplace_add, /*inplace_add*/ (binaryfunc)Rossler_inplace_sub, /*inplace_subtract*/ (binaryfunc)Rossler_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Rossler_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject RosslerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Rossler_base", /*tp_name*/ sizeof(Rossler), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Rossler_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Rossler_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Rossler objects. Rossler attractor.", /* tp_doc */ (traverseproc)Rossler_traverse, /* tp_traverse */ (inquiry)Rossler_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Rossler_methods, /* tp_methods */ Rossler_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Rossler_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD Rossler *mainRossler; int modebuffer[2]; } RosslerAlt; static void RosslerAlt_postprocessing_ii(RosslerAlt *self) { POST_PROCESSING_II }; static void RosslerAlt_postprocessing_ai(RosslerAlt *self) { POST_PROCESSING_AI }; static void RosslerAlt_postprocessing_ia(RosslerAlt *self) { POST_PROCESSING_IA }; static void RosslerAlt_postprocessing_aa(RosslerAlt *self) { POST_PROCESSING_AA }; static void RosslerAlt_postprocessing_ireva(RosslerAlt *self) { POST_PROCESSING_IREVA }; static void RosslerAlt_postprocessing_areva(RosslerAlt *self) { POST_PROCESSING_AREVA }; static void RosslerAlt_postprocessing_revai(RosslerAlt *self) { POST_PROCESSING_REVAI }; static void RosslerAlt_postprocessing_revaa(RosslerAlt *self) { POST_PROCESSING_REVAA }; static void RosslerAlt_postprocessing_revareva(RosslerAlt *self) { POST_PROCESSING_REVAREVA }; static void RosslerAlt_setProcMode(RosslerAlt *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = RosslerAlt_postprocessing_ii; break; case 1: self->muladd_func_ptr = RosslerAlt_postprocessing_ai; break; case 2: self->muladd_func_ptr = RosslerAlt_postprocessing_revai; break; case 10: self->muladd_func_ptr = RosslerAlt_postprocessing_ia; break; case 11: self->muladd_func_ptr = RosslerAlt_postprocessing_aa; break; case 12: self->muladd_func_ptr = RosslerAlt_postprocessing_revaa; break; case 20: self->muladd_func_ptr = RosslerAlt_postprocessing_ireva; break; case 21: self->muladd_func_ptr = RosslerAlt_postprocessing_areva; break; case 22: self->muladd_func_ptr = RosslerAlt_postprocessing_revareva; break; } } static void RosslerAlt_compute_next_data_frame(RosslerAlt *self) { int i; MYFLT *tmp; tmp = Rossler_getAltBuffer((Rossler *)self->mainRossler); for (i=0; ibufsize; i++) { self->data[i] = tmp[i]; } (*self->muladd_func_ptr)(self); } static int RosslerAlt_traverse(RosslerAlt *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainRossler); return 0; } static int RosslerAlt_clear(RosslerAlt *self) { pyo_CLEAR Py_CLEAR(self->mainRossler); return 0; } static void RosslerAlt_dealloc(RosslerAlt* self) { pyo_DEALLOC RosslerAlt_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * RosslerAlt_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; RosslerAlt *self; self = (RosslerAlt *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, RosslerAlt_compute_next_data_frame); self->mode_func_ptr = RosslerAlt_setProcMode; static char *kwlist[] = {"mainRossler", "mul", "alt", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &maintmp, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainRossler); Py_INCREF(maintmp); self->mainRossler = (Rossler *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * RosslerAlt_getServer(RosslerAlt* self) { GET_SERVER }; static PyObject * RosslerAlt_getStream(RosslerAlt* self) { GET_STREAM }; static PyObject * RosslerAlt_setMul(RosslerAlt *self, PyObject *arg) { SET_MUL }; static PyObject * RosslerAlt_setAdd(RosslerAlt *self, PyObject *arg) { SET_ADD }; static PyObject * RosslerAlt_setSub(RosslerAlt *self, PyObject *arg) { SET_SUB }; static PyObject * RosslerAlt_setDiv(RosslerAlt *self, PyObject *arg) { SET_DIV }; static PyObject * RosslerAlt_play(RosslerAlt *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * RosslerAlt_out(RosslerAlt *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * RosslerAlt_stop(RosslerAlt *self) { STOP }; static PyObject * RosslerAlt_multiply(RosslerAlt *self, PyObject *arg) { MULTIPLY }; static PyObject * RosslerAlt_inplace_multiply(RosslerAlt *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * RosslerAlt_add(RosslerAlt *self, PyObject *arg) { ADD }; static PyObject * RosslerAlt_inplace_add(RosslerAlt *self, PyObject *arg) { INPLACE_ADD }; static PyObject * RosslerAlt_sub(RosslerAlt *self, PyObject *arg) { SUB }; static PyObject * RosslerAlt_inplace_sub(RosslerAlt *self, PyObject *arg) { INPLACE_SUB }; static PyObject * RosslerAlt_div(RosslerAlt *self, PyObject *arg) { DIV }; static PyObject * RosslerAlt_inplace_div(RosslerAlt *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef RosslerAlt_members[] = { {"server", T_OBJECT_EX, offsetof(RosslerAlt, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(RosslerAlt, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(RosslerAlt, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(RosslerAlt, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef RosslerAlt_methods[] = { {"getServer", (PyCFunction)RosslerAlt_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)RosslerAlt_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)RosslerAlt_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)RosslerAlt_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)RosslerAlt_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)RosslerAlt_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)RosslerAlt_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)RosslerAlt_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)RosslerAlt_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods RosslerAlt_as_number = { (binaryfunc)RosslerAlt_add, /*nb_add*/ (binaryfunc)RosslerAlt_sub, /*nb_subtract*/ (binaryfunc)RosslerAlt_multiply, /*nb_multiply*/ (binaryfunc)RosslerAlt_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)RosslerAlt_inplace_add, /*inplace_add*/ (binaryfunc)RosslerAlt_inplace_sub, /*inplace_subtract*/ (binaryfunc)RosslerAlt_inplace_multiply, /*inplace_multiply*/ (binaryfunc)RosslerAlt_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject RosslerAltType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.RosslerAlt_base", /*tp_name*/ sizeof(RosslerAlt), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)RosslerAlt_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &RosslerAlt_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "RosslerAlt objects. Sends the alternate signal of a Rossler attractor.", /* tp_doc */ (traverseproc)RosslerAlt_traverse, /* tp_traverse */ (inquiry)RosslerAlt_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ RosslerAlt_methods, /* tp_methods */ RosslerAlt_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ RosslerAlt_new, /* tp_new */ }; /* Lorenz object */ typedef struct { pyo_audio_HEAD PyObject *pitch; Stream *pitch_stream; PyObject *chaos; Stream *chaos_stream; MYFLT *altBuffer; MYFLT vDX; MYFLT vDY; MYFLT vDZ; MYFLT vX; MYFLT vY; MYFLT vZ; MYFLT pA; MYFLT pB; MYFLT oneOnSr; int modebuffer[4]; } Lorenz; static void Lorenz_readframes_ii(Lorenz *self) { MYFLT delta, pit, chao; int i; pit = PyFloat_AS_DOUBLE(self->pitch); chao = PyFloat_AS_DOUBLE(self->chaos); if (pit < 0.0) pit = 1.0; else if (pit > 1.0) pit = 750.0; else pit = pit * 749.0 + 1.0; delta = self->oneOnSr * pit; if (chao < 0.0) chao = 0.5; else if (chao > 1.0) chao = 3.0; else chao = chao * 2.5 + 0.5; for (i=0; ibufsize; i++) { self->vDX = self->pA * (self->vY - self->vX); self->vDY = self->vX * (self->pB - self->vZ) - self->vY; self->vDZ = self->vX * self->vY - chao * self->vZ; self->vX += self->vDX * delta; self->vY += self->vDY * delta; self->vZ += self->vDZ * delta; self->data[i] = self->vX * LORENZ_SCALE; self->altBuffer[i] = self->vY * LORENZ_ALT_SCALE; } } static void Lorenz_readframes_ai(Lorenz *self) { MYFLT delta, pit, chao; int i; MYFLT *fr = Stream_getData((Stream *)self->pitch_stream); chao = PyFloat_AS_DOUBLE(self->chaos); if (chao < 0.0) chao = 0.5; else if (chao > 1.0) chao = 3.0; else chao = chao * 2.5 + 0.5; for (i=0; ibufsize; i++) { pit = fr[i]; if (pit < 0.0) pit = 1.0; else if (pit > 1.0) pit = 750.0; else pit = pit * 749.0 + 1.0; delta = self->oneOnSr * pit; self->vDX = self->pA * (self->vY - self->vX); self->vDY = self->vX * (self->pB - self->vZ) - self->vY; self->vDZ = self->vX * self->vY - chao * self->vZ; self->vX += self->vDX * delta; self->vY += self->vDY * delta; self->vZ += self->vDZ * delta; self->data[i] = self->vX * LORENZ_SCALE; self->altBuffer[i] = self->vY * LORENZ_ALT_SCALE; } } static void Lorenz_readframes_ia(Lorenz *self) { MYFLT delta, pit, chao; int i; pit = PyFloat_AS_DOUBLE(self->pitch); MYFLT *ch = Stream_getData((Stream *)self->chaos_stream); if (pit < 0.0) pit = 1.0; else if (pit > 1.0) pit = 750.0; else pit = pit * 749.0 + 1.0; delta = self->oneOnSr * pit; for (i=0; ibufsize; i++) { chao = ch[i]; if (chao < 0.0) chao = 0.5; else if (chao > 1.0) chao = 3.0; else chao = chao * 2.5 + 0.5; self->vDX = self->pA * (self->vY - self->vX); self->vDY = self->vX * (self->pB - self->vZ) - self->vY; self->vDZ = self->vX * self->vY - chao * self->vZ; self->vX += self->vDX * delta; self->vY += self->vDY * delta; self->vZ += self->vDZ * delta; self->data[i] = self->vX * LORENZ_SCALE; self->altBuffer[i] = self->vY * LORENZ_ALT_SCALE; } } static void Lorenz_readframes_aa(Lorenz *self) { MYFLT delta, pit, chao; int i; MYFLT *fr = Stream_getData((Stream *)self->pitch_stream); MYFLT *ch = Stream_getData((Stream *)self->chaos_stream); for (i=0; ibufsize; i++) { pit = fr[i]; if (pit < 0.0) pit = 1.0; else if (pit > 1.0) pit = 750.0; else pit = pit * 749.0 + 1.0; delta = self->oneOnSr * pit; chao = ch[i]; if (chao < 0.0) chao = 0.5; else if (chao > 1.0) chao = 3.0; else chao = chao * 2.5 + 0.5; self->vDX = self->pA * (self->vY - self->vX); self->vDY = self->vX * (self->pB - self->vZ) - self->vY; self->vDZ = self->vX * self->vY - chao * self->vZ; self->vX += self->vDX * delta; self->vY += self->vDY * delta; self->vZ += self->vDZ * delta; self->data[i] = self->vX * LORENZ_SCALE; self->altBuffer[i] = self->vY * LORENZ_ALT_SCALE; } } static void Lorenz_postprocessing_ii(Lorenz *self) { POST_PROCESSING_II }; static void Lorenz_postprocessing_ai(Lorenz *self) { POST_PROCESSING_AI }; static void Lorenz_postprocessing_ia(Lorenz *self) { POST_PROCESSING_IA }; static void Lorenz_postprocessing_aa(Lorenz *self) { POST_PROCESSING_AA }; static void Lorenz_postprocessing_ireva(Lorenz *self) { POST_PROCESSING_IREVA }; static void Lorenz_postprocessing_areva(Lorenz *self) { POST_PROCESSING_AREVA }; static void Lorenz_postprocessing_revai(Lorenz *self) { POST_PROCESSING_REVAI }; static void Lorenz_postprocessing_revaa(Lorenz *self) { POST_PROCESSING_REVAA }; static void Lorenz_postprocessing_revareva(Lorenz *self) { POST_PROCESSING_REVAREVA }; static void Lorenz_setProcMode(Lorenz *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Lorenz_readframes_ii; break; case 1: self->proc_func_ptr = Lorenz_readframes_ai; break; case 10: self->proc_func_ptr = Lorenz_readframes_ia; break; case 11: self->proc_func_ptr = Lorenz_readframes_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Lorenz_postprocessing_ii; break; case 1: self->muladd_func_ptr = Lorenz_postprocessing_ai; break; case 2: self->muladd_func_ptr = Lorenz_postprocessing_revai; break; case 10: self->muladd_func_ptr = Lorenz_postprocessing_ia; break; case 11: self->muladd_func_ptr = Lorenz_postprocessing_aa; break; case 12: self->muladd_func_ptr = Lorenz_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Lorenz_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Lorenz_postprocessing_areva; break; case 22: self->muladd_func_ptr = Lorenz_postprocessing_revareva; break; } } static void Lorenz_compute_next_data_frame(Lorenz *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Lorenz_traverse(Lorenz *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->pitch); Py_VISIT(self->pitch_stream); Py_VISIT(self->chaos); Py_VISIT(self->chaos_stream); return 0; } static int Lorenz_clear(Lorenz *self) { pyo_CLEAR Py_CLEAR(self->pitch); Py_CLEAR(self->pitch_stream); Py_CLEAR(self->chaos); Py_CLEAR(self->chaos_stream); return 0; } static void Lorenz_dealloc(Lorenz* self) { pyo_DEALLOC free(self->altBuffer); Lorenz_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Lorenz_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *pitchtmp=NULL, *chaostmp=NULL, *multmp=NULL, *addtmp=NULL; Lorenz *self; self = (Lorenz *)type->tp_alloc(type, 0); self->pitch = PyFloat_FromDouble(0.25); self->chaos = PyFloat_FromDouble(0.5); self->pA = 10.0; self->pB = 28.0; self->vDX = self->vDY = self->vDZ = 0.0; self->vX = self->vY = self->vZ = 1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Lorenz_compute_next_data_frame); self->mode_func_ptr = Lorenz_setProcMode; self->oneOnSr = 1.0 / self->sr; static char *kwlist[] = {"pitch", "chaos", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &pitchtmp, &chaostmp, &multmp, &addtmp)) Py_RETURN_NONE; if (pitchtmp) { PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp); } if (chaostmp) { PyObject_CallMethod((PyObject *)self, "setChaos", "O", chaostmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->altBuffer = (MYFLT *)realloc(self->altBuffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->altBuffer[i] = 0.0; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Lorenz_getServer(Lorenz* self) { GET_SERVER }; static PyObject * Lorenz_getStream(Lorenz* self) { GET_STREAM }; static PyObject * Lorenz_setMul(Lorenz *self, PyObject *arg) { SET_MUL }; static PyObject * Lorenz_setAdd(Lorenz *self, PyObject *arg) { SET_ADD }; static PyObject * Lorenz_setSub(Lorenz *self, PyObject *arg) { SET_SUB }; static PyObject * Lorenz_setDiv(Lorenz *self, PyObject *arg) { SET_DIV }; static PyObject * Lorenz_play(Lorenz *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Lorenz_out(Lorenz *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Lorenz_stop(Lorenz *self) { STOP }; static PyObject * Lorenz_multiply(Lorenz *self, PyObject *arg) { MULTIPLY }; static PyObject * Lorenz_inplace_multiply(Lorenz *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Lorenz_add(Lorenz *self, PyObject *arg) { ADD }; static PyObject * Lorenz_inplace_add(Lorenz *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Lorenz_sub(Lorenz *self, PyObject *arg) { SUB }; static PyObject * Lorenz_inplace_sub(Lorenz *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Lorenz_div(Lorenz *self, PyObject *arg) { DIV }; static PyObject * Lorenz_inplace_div(Lorenz *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Lorenz_setPitch(Lorenz *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pitch); if (isNumber == 1) { self->pitch = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->pitch = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pitch, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pitch_stream); self->pitch_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Lorenz_setChaos(Lorenz *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->chaos); if (isNumber == 1) { self->chaos = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->chaos = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->chaos, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->chaos_stream); self->chaos_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } MYFLT * Lorenz_getAltBuffer(Lorenz *self) { return (MYFLT *)self->altBuffer; } static PyMemberDef Lorenz_members[] = { {"server", T_OBJECT_EX, offsetof(Lorenz, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Lorenz, stream), 0, "Stream object."}, {"pitch", T_OBJECT_EX, offsetof(Lorenz, pitch), 0, "Pitch."}, {"chaos", T_OBJECT_EX, offsetof(Lorenz, chaos), 0, "Chaotic behavior."}, {"mul", T_OBJECT_EX, offsetof(Lorenz, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Lorenz, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Lorenz_methods[] = { {"getServer", (PyCFunction)Lorenz_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Lorenz_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Lorenz_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Lorenz_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Lorenz_stop, METH_NOARGS, "Stops computing."}, {"setPitch", (PyCFunction)Lorenz_setPitch, METH_O, "Sets oscillator pitch."}, {"setChaos", (PyCFunction)Lorenz_setChaos, METH_O, "Sets oscillator chaotic behavior."}, {"setMul", (PyCFunction)Lorenz_setMul, METH_O, "Sets Lorenz mul factor."}, {"setAdd", (PyCFunction)Lorenz_setAdd, METH_O, "Sets Lorenz add factor."}, {"setSub", (PyCFunction)Lorenz_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Lorenz_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Lorenz_as_number = { (binaryfunc)Lorenz_add, /*nb_add*/ (binaryfunc)Lorenz_sub, /*nb_subtract*/ (binaryfunc)Lorenz_multiply, /*nb_multiply*/ (binaryfunc)Lorenz_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Lorenz_inplace_add, /*inplace_add*/ (binaryfunc)Lorenz_inplace_sub, /*inplace_subtract*/ (binaryfunc)Lorenz_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Lorenz_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject LorenzType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Lorenz_base", /*tp_name*/ sizeof(Lorenz), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Lorenz_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Lorenz_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Lorenz objects. Lorenz attractor.", /* tp_doc */ (traverseproc)Lorenz_traverse, /* tp_traverse */ (inquiry)Lorenz_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Lorenz_methods, /* tp_methods */ Lorenz_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Lorenz_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD Lorenz *mainLorenz; int modebuffer[2]; } LorenzAlt; static void LorenzAlt_postprocessing_ii(LorenzAlt *self) { POST_PROCESSING_II }; static void LorenzAlt_postprocessing_ai(LorenzAlt *self) { POST_PROCESSING_AI }; static void LorenzAlt_postprocessing_ia(LorenzAlt *self) { POST_PROCESSING_IA }; static void LorenzAlt_postprocessing_aa(LorenzAlt *self) { POST_PROCESSING_AA }; static void LorenzAlt_postprocessing_ireva(LorenzAlt *self) { POST_PROCESSING_IREVA }; static void LorenzAlt_postprocessing_areva(LorenzAlt *self) { POST_PROCESSING_AREVA }; static void LorenzAlt_postprocessing_revai(LorenzAlt *self) { POST_PROCESSING_REVAI }; static void LorenzAlt_postprocessing_revaa(LorenzAlt *self) { POST_PROCESSING_REVAA }; static void LorenzAlt_postprocessing_revareva(LorenzAlt *self) { POST_PROCESSING_REVAREVA }; static void LorenzAlt_setProcMode(LorenzAlt *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = LorenzAlt_postprocessing_ii; break; case 1: self->muladd_func_ptr = LorenzAlt_postprocessing_ai; break; case 2: self->muladd_func_ptr = LorenzAlt_postprocessing_revai; break; case 10: self->muladd_func_ptr = LorenzAlt_postprocessing_ia; break; case 11: self->muladd_func_ptr = LorenzAlt_postprocessing_aa; break; case 12: self->muladd_func_ptr = LorenzAlt_postprocessing_revaa; break; case 20: self->muladd_func_ptr = LorenzAlt_postprocessing_ireva; break; case 21: self->muladd_func_ptr = LorenzAlt_postprocessing_areva; break; case 22: self->muladd_func_ptr = LorenzAlt_postprocessing_revareva; break; } } static void LorenzAlt_compute_next_data_frame(LorenzAlt *self) { int i; MYFLT *tmp; tmp = Lorenz_getAltBuffer((Lorenz *)self->mainLorenz); for (i=0; ibufsize; i++) { self->data[i] = tmp[i]; } (*self->muladd_func_ptr)(self); } static int LorenzAlt_traverse(LorenzAlt *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainLorenz); return 0; } static int LorenzAlt_clear(LorenzAlt *self) { pyo_CLEAR Py_CLEAR(self->mainLorenz); return 0; } static void LorenzAlt_dealloc(LorenzAlt* self) { pyo_DEALLOC LorenzAlt_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * LorenzAlt_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; LorenzAlt *self; self = (LorenzAlt *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, LorenzAlt_compute_next_data_frame); self->mode_func_ptr = LorenzAlt_setProcMode; static char *kwlist[] = {"mainLorenz", "mul", "alt", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &maintmp, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainLorenz); Py_INCREF(maintmp); self->mainLorenz = (Lorenz *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * LorenzAlt_getServer(LorenzAlt* self) { GET_SERVER }; static PyObject * LorenzAlt_getStream(LorenzAlt* self) { GET_STREAM }; static PyObject * LorenzAlt_setMul(LorenzAlt *self, PyObject *arg) { SET_MUL }; static PyObject * LorenzAlt_setAdd(LorenzAlt *self, PyObject *arg) { SET_ADD }; static PyObject * LorenzAlt_setSub(LorenzAlt *self, PyObject *arg) { SET_SUB }; static PyObject * LorenzAlt_setDiv(LorenzAlt *self, PyObject *arg) { SET_DIV }; static PyObject * LorenzAlt_play(LorenzAlt *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * LorenzAlt_out(LorenzAlt *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * LorenzAlt_stop(LorenzAlt *self) { STOP }; static PyObject * LorenzAlt_multiply(LorenzAlt *self, PyObject *arg) { MULTIPLY }; static PyObject * LorenzAlt_inplace_multiply(LorenzAlt *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * LorenzAlt_add(LorenzAlt *self, PyObject *arg) { ADD }; static PyObject * LorenzAlt_inplace_add(LorenzAlt *self, PyObject *arg) { INPLACE_ADD }; static PyObject * LorenzAlt_sub(LorenzAlt *self, PyObject *arg) { SUB }; static PyObject * LorenzAlt_inplace_sub(LorenzAlt *self, PyObject *arg) { INPLACE_SUB }; static PyObject * LorenzAlt_div(LorenzAlt *self, PyObject *arg) { DIV }; static PyObject * LorenzAlt_inplace_div(LorenzAlt *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef LorenzAlt_members[] = { {"server", T_OBJECT_EX, offsetof(LorenzAlt, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(LorenzAlt, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(LorenzAlt, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(LorenzAlt, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef LorenzAlt_methods[] = { {"getServer", (PyCFunction)LorenzAlt_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)LorenzAlt_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)LorenzAlt_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)LorenzAlt_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)LorenzAlt_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)LorenzAlt_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)LorenzAlt_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)LorenzAlt_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)LorenzAlt_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods LorenzAlt_as_number = { (binaryfunc)LorenzAlt_add, /*nb_add*/ (binaryfunc)LorenzAlt_sub, /*nb_subtract*/ (binaryfunc)LorenzAlt_multiply, /*nb_multiply*/ (binaryfunc)LorenzAlt_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)LorenzAlt_inplace_add, /*inplace_add*/ (binaryfunc)LorenzAlt_inplace_sub, /*inplace_subtract*/ (binaryfunc)LorenzAlt_inplace_multiply, /*inplace_multiply*/ (binaryfunc)LorenzAlt_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject LorenzAltType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.LorenzAlt_base", /*tp_name*/ sizeof(LorenzAlt), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)LorenzAlt_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &LorenzAlt_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "LorenzAlt objects. Sends the alternate signal of a Lorenz attractor.", /* tp_doc */ (traverseproc)LorenzAlt_traverse, /* tp_traverse */ (inquiry)LorenzAlt_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ LorenzAlt_methods, /* tp_methods */ LorenzAlt_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ LorenzAlt_new, /* tp_new */ }; /*************/ /* SumOsc object */ /*************/ typedef struct { pyo_audio_HEAD PyObject *freq; Stream *freq_stream; PyObject *ratio; Stream *ratio_stream; PyObject *index; Stream *index_stream; int modebuffer[5]; MYFLT theta; MYFLT beta; MYFLT scaleFactor; MYFLT xn1; // dc block input delay MYFLT yn1; // dc block output delay } SumOsc; static void SumOsc_readframes_iii(SumOsc *self) { MYFLT mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1; int i, ipart; MYFLT freq = PyFloat_AS_DOUBLE(self->freq); MYFLT rat = PyFloat_AS_DOUBLE(self->ratio); MYFLT ind = PyFloat_AS_DOUBLE(self->index); freq_delta = freq * self->scaleFactor; mod_freq = freq * rat; mod_delta = mod_freq * self->scaleFactor; if (ind < 0) ind = 0; else if (ind > 0.999) ind = 0.999; ind2 = ind * ind; for (i=0; ibufsize; i++) { ipart = (int)self->theta; sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart); theta_minus_beta = Sine_clip(self->theta - self->beta); ipart = (int)theta_minus_beta; sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart); ipart = (int)self->beta; cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart); x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1); self->theta += freq_delta; self->beta += mod_delta; self->theta = Sine_clip(self->theta); self->beta = Sine_clip(self->beta); /* DC filtering */ y = x - self->xn1 + 0.995 * self->yn1; self->xn1 = x; self->yn1 = y; self->data[i] = y * (1 - ind2); } } static void SumOsc_readframes_aii(SumOsc *self) { MYFLT freq, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1; int i, ipart; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT rat = PyFloat_AS_DOUBLE(self->ratio); MYFLT ind = PyFloat_AS_DOUBLE(self->index); if (ind < 0) ind = 0; else if (ind > 0.999) ind = 0.999; ind2 = ind * ind; for (i=0; ibufsize; i++) { freq = fr[i]; freq_delta = freq * self->scaleFactor; mod_freq = freq * rat; mod_delta = mod_freq * self->scaleFactor; ipart = (int)self->theta; sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart); theta_minus_beta = Sine_clip(self->theta - self->beta); ipart = (int)theta_minus_beta; sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart); ipart = (int)self->beta; cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart); x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1); self->theta += freq_delta; self->beta += mod_delta; self->theta = Sine_clip(self->theta); self->beta = Sine_clip(self->beta); y = x - self->xn1 + 0.995 * self->yn1; self->xn1 = x; self->yn1 = y; self->data[i] = y * (1 - ind2); } } static void SumOsc_readframes_iai(SumOsc *self) { MYFLT ratio, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1; int i, ipart; MYFLT freq = PyFloat_AS_DOUBLE(self->freq); MYFLT *rat = Stream_getData((Stream *)self->ratio_stream); MYFLT ind = PyFloat_AS_DOUBLE(self->index); freq_delta = freq * self->scaleFactor; if (ind < 0) ind = 0; else if (ind > 0.999) ind = 0.999; ind2 = ind * ind; for (i=0; ibufsize; i++) { ratio = rat[i]; mod_freq = freq * ratio; mod_delta = mod_freq * self->scaleFactor; ipart = (int)self->theta; sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart); theta_minus_beta = Sine_clip(self->theta - self->beta); ipart = (int)theta_minus_beta; sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart); ipart = (int)self->beta; cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart); x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1); self->theta += freq_delta; self->beta += mod_delta; self->theta = Sine_clip(self->theta); self->beta = Sine_clip(self->beta); y = x - self->xn1 + 0.995 * self->yn1; self->xn1 = x; self->yn1 = y; self->data[i] = y * (1 - ind2); } } static void SumOsc_readframes_aai(SumOsc *self) { MYFLT freq, ratio, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1; int i, ipart; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *rat = Stream_getData((Stream *)self->ratio_stream); MYFLT ind = PyFloat_AS_DOUBLE(self->index); if (ind < 0) ind = 0; else if (ind > 0.999) ind = 0.999; ind2 = ind * ind; for (i=0; ibufsize; i++) { freq = fr[i]; ratio = rat[i]; freq_delta = freq * self->scaleFactor; mod_freq = freq * ratio; mod_delta = mod_freq * self->scaleFactor; ipart = (int)self->theta; sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart); theta_minus_beta = Sine_clip(self->theta - self->beta); ipart = (int)theta_minus_beta; sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart); ipart = (int)self->beta; cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart); x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1); self->theta += freq_delta; self->beta += mod_delta; self->theta = Sine_clip(self->theta); self->beta = Sine_clip(self->beta); y = x - self->xn1 + 0.995 * self->yn1; self->xn1 = x; self->yn1 = y; self->data[i] = y * (1 - ind2); } } static void SumOsc_readframes_iia(SumOsc *self) { MYFLT ind, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1; int i, ipart; MYFLT freq = PyFloat_AS_DOUBLE(self->freq); MYFLT rat = PyFloat_AS_DOUBLE(self->ratio); MYFLT *index = Stream_getData((Stream *)self->index_stream); freq_delta = freq * self->scaleFactor; mod_freq = freq * rat; mod_delta = mod_freq * self->scaleFactor; for (i=0; ibufsize; i++) { ind = index[i]; if (ind < 0) ind = 0; else if (ind > 0.999) ind = 0.999; ind2 = ind * ind; ipart = (int)self->theta; sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart); theta_minus_beta = Sine_clip(self->theta - self->beta); ipart = (int)theta_minus_beta; sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart); ipart = (int)self->beta; cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart); x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1); self->theta += freq_delta; self->beta += mod_delta; self->theta = Sine_clip(self->theta); self->beta = Sine_clip(self->beta); y = x - self->xn1 + 0.995 * self->yn1; self->xn1 = x; self->yn1 = y; self->data[i] = y * (1 - ind2); } } static void SumOsc_readframes_aia(SumOsc *self) { MYFLT freq, ind, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1; int i, ipart; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT rat = PyFloat_AS_DOUBLE(self->ratio); MYFLT *index = Stream_getData((Stream *)self->index_stream); for (i=0; ibufsize; i++) { freq = fr[i]; ind = index[i]; freq_delta = freq * self->scaleFactor; mod_freq = freq * rat; mod_delta = mod_freq * self->scaleFactor; if (ind < 0) ind = 0; else if (ind > 0.999) ind = 0.999; ind2 = ind * ind; ipart = (int)self->theta; sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart); theta_minus_beta = Sine_clip(self->theta - self->beta); ipart = (int)theta_minus_beta; sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart); ipart = (int)self->beta; cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart); x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1); self->theta += freq_delta; self->beta += mod_delta; self->theta = Sine_clip(self->theta); self->beta = Sine_clip(self->beta); y = x - self->xn1 + 0.995 * self->yn1; self->xn1 = x; self->yn1 = y; self->data[i] = y * (1 - ind2); } } static void SumOsc_readframes_iaa(SumOsc *self) { MYFLT ratio, ind, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1; int i, ipart; MYFLT freq = PyFloat_AS_DOUBLE(self->freq); MYFLT *rat = Stream_getData((Stream *)self->ratio_stream); MYFLT *index = Stream_getData((Stream *)self->index_stream); freq_delta = freq * self->scaleFactor; for (i=0; ibufsize; i++) { ind = index[i]; ratio = rat[i]; mod_freq = freq * ratio; mod_delta = mod_freq * self->scaleFactor; if (ind < 0) ind = 0; else if (ind > 0.999) ind = 0.999; ind2 = ind * ind; ipart = (int)self->theta; sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart); theta_minus_beta = Sine_clip(self->theta - self->beta); ipart = (int)theta_minus_beta; sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart); ipart = (int)self->beta; cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart); x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1); self->theta += freq_delta; self->beta += mod_delta; self->theta = Sine_clip(self->theta); self->beta = Sine_clip(self->beta); y = x - self->xn1 + 0.995 * self->yn1; self->xn1 = x; self->yn1 = y; self->data[i] = y * (1 - ind2); } } static void SumOsc_readframes_aaa(SumOsc *self) { MYFLT freq, ratio, ind, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1; int i, ipart; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *rat = Stream_getData((Stream *)self->ratio_stream); MYFLT *index = Stream_getData((Stream *)self->index_stream); for (i=0; ibufsize; i++) { freq = fr[i]; ind = index[i]; ratio = rat[i]; freq_delta = freq * self->scaleFactor; mod_freq = freq * ratio; mod_delta = mod_freq * self->scaleFactor; if (ind < 0) ind = 0; else if (ind > 0.999) ind = 0.999; ind2 = ind * ind; ipart = (int)self->theta; sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart); theta_minus_beta = Sine_clip(self->theta - self->beta); ipart = (int)theta_minus_beta; sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart); ipart = (int)self->beta; cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart); x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1); self->theta += freq_delta; self->beta += mod_delta; self->theta = Sine_clip(self->theta); self->beta = Sine_clip(self->beta); y = x - self->xn1 + 0.995 * self->yn1; self->xn1 = x; self->yn1 = y; self->data[i] = y * (1 - ind2); } } static void SumOsc_postprocessing_ii(SumOsc *self) { POST_PROCESSING_II }; static void SumOsc_postprocessing_ai(SumOsc *self) { POST_PROCESSING_AI }; static void SumOsc_postprocessing_ia(SumOsc *self) { POST_PROCESSING_IA }; static void SumOsc_postprocessing_aa(SumOsc *self) { POST_PROCESSING_AA }; static void SumOsc_postprocessing_ireva(SumOsc *self) { POST_PROCESSING_IREVA }; static void SumOsc_postprocessing_areva(SumOsc *self) { POST_PROCESSING_AREVA }; static void SumOsc_postprocessing_revai(SumOsc *self) { POST_PROCESSING_REVAI }; static void SumOsc_postprocessing_revaa(SumOsc *self) { POST_PROCESSING_REVAA }; static void SumOsc_postprocessing_revareva(SumOsc *self) { POST_PROCESSING_REVAREVA }; static void SumOsc_setProcMode(SumOsc *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = SumOsc_readframes_iii; break; case 1: self->proc_func_ptr = SumOsc_readframes_aii; break; case 10: self->proc_func_ptr = SumOsc_readframes_iai; break; case 11: self->proc_func_ptr = SumOsc_readframes_aai; break; case 100: self->proc_func_ptr = SumOsc_readframes_iia; break; case 101: self->proc_func_ptr = SumOsc_readframes_aia; break; case 110: self->proc_func_ptr = SumOsc_readframes_iaa; break; case 111: self->proc_func_ptr = SumOsc_readframes_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = SumOsc_postprocessing_ii; break; case 1: self->muladd_func_ptr = SumOsc_postprocessing_ai; break; case 2: self->muladd_func_ptr = SumOsc_postprocessing_revai; break; case 10: self->muladd_func_ptr = SumOsc_postprocessing_ia; break; case 11: self->muladd_func_ptr = SumOsc_postprocessing_aa; break; case 12: self->muladd_func_ptr = SumOsc_postprocessing_revaa; break; case 20: self->muladd_func_ptr = SumOsc_postprocessing_ireva; break; case 21: self->muladd_func_ptr = SumOsc_postprocessing_areva; break; case 22: self->muladd_func_ptr = SumOsc_postprocessing_revareva; break; } } static void SumOsc_compute_next_data_frame(SumOsc *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int SumOsc_traverse(SumOsc *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->ratio); Py_VISIT(self->ratio_stream); Py_VISIT(self->index); Py_VISIT(self->index_stream); return 0; } static int SumOsc_clear(SumOsc *self) { pyo_CLEAR Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->ratio); Py_CLEAR(self->ratio_stream); Py_CLEAR(self->index); Py_CLEAR(self->index_stream); return 0; } static void SumOsc_dealloc(SumOsc* self) { pyo_DEALLOC SumOsc_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SumOsc_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *freqtmp=NULL, *ratiotmp=NULL, *indextmp=NULL, *multmp=NULL, *addtmp=NULL; SumOsc *self; self = (SumOsc *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(100); self->ratio = PyFloat_FromDouble(0.5); self->index = PyFloat_FromDouble(0.5); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->theta = self->beta = 0.; self->xn1 = self->yn1 = 0.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, SumOsc_compute_next_data_frame); self->mode_func_ptr = SumOsc_setProcMode; self->scaleFactor = 512.0 / self->sr; static char *kwlist[] = {"freq", "ratio", "index", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &freqtmp, &ratiotmp, &indextmp, &multmp, &addtmp)) Py_RETURN_NONE; if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (ratiotmp) { PyObject_CallMethod((PyObject *)self, "setRatio", "O", ratiotmp); } if (indextmp) { PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * SumOsc_getServer(SumOsc* self) { GET_SERVER }; static PyObject * SumOsc_getStream(SumOsc* self) { GET_STREAM }; static PyObject * SumOsc_setMul(SumOsc *self, PyObject *arg) { SET_MUL }; static PyObject * SumOsc_setAdd(SumOsc *self, PyObject *arg) { SET_ADD }; static PyObject * SumOsc_setSub(SumOsc *self, PyObject *arg) { SET_SUB }; static PyObject * SumOsc_setDiv(SumOsc *self, PyObject *arg) { SET_DIV }; static PyObject * SumOsc_play(SumOsc *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SumOsc_out(SumOsc *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * SumOsc_stop(SumOsc *self) { STOP }; static PyObject * SumOsc_multiply(SumOsc *self, PyObject *arg) { MULTIPLY }; static PyObject * SumOsc_inplace_multiply(SumOsc *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * SumOsc_add(SumOsc *self, PyObject *arg) { ADD }; static PyObject * SumOsc_inplace_add(SumOsc *self, PyObject *arg) { INPLACE_ADD }; static PyObject * SumOsc_sub(SumOsc *self, PyObject *arg) { SUB }; static PyObject * SumOsc_inplace_sub(SumOsc *self, PyObject *arg) { INPLACE_SUB }; static PyObject * SumOsc_div(SumOsc *self, PyObject *arg) { DIV }; static PyObject * SumOsc_inplace_div(SumOsc *self, PyObject *arg) { INPLACE_DIV }; static PyObject * SumOsc_setFreq(SumOsc *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SumOsc_setRatio(SumOsc *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->ratio); if (isNumber == 1) { self->ratio = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->ratio = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->ratio, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->ratio_stream); self->ratio_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SumOsc_setIndex(SumOsc *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->index); if (isNumber == 1) { self->index = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->index = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->index_stream); self->index_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef SumOsc_members[] = { {"server", T_OBJECT_EX, offsetof(SumOsc, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SumOsc, stream), 0, "Stream object."}, {"freq", T_OBJECT_EX, offsetof(SumOsc, freq), 0, "Frequency in cycle per second."}, {"ratio", T_OBJECT_EX, offsetof(SumOsc, ratio), 0, "Ratio freq:modulator (mod freq = freq*ratio)."}, {"index", T_OBJECT_EX, offsetof(SumOsc, index), 0, "Index, high frequency damping."}, {"mul", T_OBJECT_EX, offsetof(SumOsc, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(SumOsc, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef SumOsc_methods[] = { {"getServer", (PyCFunction)SumOsc_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SumOsc_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SumOsc_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundfreqd."}, {"out", (PyCFunction)SumOsc_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundfreqd channel speficied by argument."}, {"stop", (PyCFunction)SumOsc_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)SumOsc_setFreq, METH_O, "Sets oscillator frequency in cycle per second."}, {"setRatio", (PyCFunction)SumOsc_setRatio, METH_O, "Sets freq:mod ratio."}, {"setIndex", (PyCFunction)SumOsc_setIndex, METH_O, "Sets high frequency damping."}, {"setMul", (PyCFunction)SumOsc_setMul, METH_O, "Sets SumOsc mul factor."}, {"setAdd", (PyCFunction)SumOsc_setAdd, METH_O, "Sets SumOsc add factor."}, {"setSub", (PyCFunction)SumOsc_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)SumOsc_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods SumOsc_as_number = { (binaryfunc)SumOsc_add, /*nb_add*/ (binaryfunc)SumOsc_sub, /*nb_subtract*/ (binaryfunc)SumOsc_multiply, /*nb_multiply*/ (binaryfunc)SumOsc_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)SumOsc_inplace_add, /*inplace_add*/ (binaryfunc)SumOsc_inplace_sub, /*inplace_subtract*/ (binaryfunc)SumOsc_inplace_multiply, /*inplace_multiply*/ (binaryfunc)SumOsc_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SumOscType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SumOsc_base", /*tp_name*/ sizeof(SumOsc), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SumOsc_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &SumOsc_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SumOsc objects. Infite summation oscillator.", /* tp_doc */ (traverseproc)SumOsc_traverse, /* tp_traverse */ (inquiry)SumOsc_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SumOsc_methods, /* tp_methods */ SumOsc_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SumOsc_new, /* tp_new */ }; static MYFLT SUPERSAW_DETUNES[7][128] = {{1.0, 0.9999999999999738, 0.9999999999983218, 0.9999999999808844, 0.9999999998925958, 0.9999999995902856, 0.9999999987765995, 0.999999996915041, 0.9999999931261337, 0.9999999860647035, 0.9999999737782811, 0.9999999535466255, 0.999999921702367, 0.9999998734327713, 0.9999998025626238, 0.9999997013182335, 0.9999995600725585, 0.9999993670714514, 0.999999108141024, 0.9999987663761343, 0.999998321809992, 0.9999977510648862, 0.9999970269840314, 0.9999961182445354, 0.9999949889514873, 0.9999935982131656, 0.999991899697366, 0.9999898411688514, 0.9999873640079204, 0.999984402710097, 0.9999808843669409, 0.9999767281279772, 0.9999718446437478, 0.9999661354899821, 0.9999594925728883, 0.9999517975155655, 0.9999429210255355, 0.9999327222433956, 0.9999210480725913, 0.9999077324903094, 0.9998925958394921, 0.9998754441019703, 0.9998560681527183, 0.9998342429952286, 0.9998097269780065, 0.9997822609921857, 0.9997515676502643, 0.9997173504459607, 0.99967929289519, 0.9996370576581611, 0.9995902856425938, 0.9995385950880562, 0.999481580631423, 0.9994188123534535, 0.9993498348064905, 0.9992741660232791, 0.999191296506906, 0.9991006882018598, 0.9990017734462106, 0.9988939539049104, 0.9987765994842147, 0.9986490472272227, 0.9985106001905395, 0.9983605263020577, 0.9981980571998603, 0.9980223870522424, 0.9978326713588549, 0.9976280257329677, 0.9974075246648535, 0.9971702002662917, 0.996915040996193, 0.9966409903673441, 0.9963469456342734, 0.9960317564622357, 0.995694223577319, 0.9953330973976697, 0.9949470766458405, 0.9945348069422566, 0.994094879379803, 0.9936258290795327, 0.9931261337274945, 0.9925942120926815, 0.9920284225260998, 0.9914270614409579, 0.9907883617739762, 0.9901104914278165, 0.9893915516946329, 0.988629575660742, 0.9878225265924139, 0.9869682963027838, 0.9860647034998833, 0.985109492115793, 0.9841003296169146, 0.9830348052953636, 0.9819104285414826, 0.9807246270974751, 0.9794747452921589, 0.9781580422568408, 0.9767716901223106, 0.9753127721969568, 0.9737782811260014, 0.9721651170318559, 0.9704700856355972, 0.9686898963595642, 0.9668211604110741, 0.9648603888472602, 0.9628039906210292, 0.9606482706081385, 0.9583894276153956, 0.9560235523699754, 0.9535466254898602, 0.9509545154353983, 0.9482429764419842, 0.9454076464338582, 0.9424440449190272, 0.9393475708653054, 0.9361135005574749, 0.9327369854355683, 0.9292130499142693, 0.9255365891834358, 0.9217023669897422, 0.9177050133994422, 0.9135390225422524, 0.9091987503363557, 0.9046784121945255, 0.8999720807113701, 0.8950736833316975, 0.889977}, {1.0, 0.999999999999985, 0.9999999999990408, 0.9999999999890743, 0.9999999999386124, 0.999999999765825, 0.999999999300757, 0.9999999982367705, 0.9999999960711946, 0.9999999920351857, 0.9999999850127967, 0.9999999734492553, 0.999999955248451, 0.9999999276596326, 0.9999998871533139, 0.9999998292863885, 0.9999997485564546, 0.9999996382453485, 0.9999994902518874, 0.9999992949138214, 0.9999990408189948, 0.9999987146057163, 0.9999983007523392, 0.9999977813560498, 0.9999971359008654, 0.9999963410148422, 0.9999953702164914, 0.9999941936504051, 0.9999927778120908, 0.9999910852620164, 0.9999890743288626, 0.9999866988019865, 0.9999839076130926, 0.9999806445071142, 0.9999768477023036, 0.9999724495395311, 0.9999673761207947, 0.9999615469369367, 0.999954874484572, 0.9999472638722232, 0.9999386124156673, 0.9999288092224893, 0.9999177347658472, 0.9999052604474442, 0.9998912481497119, 0.9998755497772012, 0.9998580067871834, 0.9998384497094605, 0.9998166976553837, 0.9997925578160827, 0.9997658249499025, 0.999736280859051, 0.9997036938554544, 0.9996678182158232, 0.9996283936259261, 0.9995851446140742, 0.9995377799738134, 0.9994859921758271, 0.9994294567690473, 0.9993678317709748, 0.9993007570472097, 0.9992278536801902, 0.9991487233271403, 0.9990629475672279, 0.9989700872379311, 0.998869681760614, 0.9987612484553119, 0.9986442818447255, 0.9985182529474248, 0.998382608560261, 0.9982367705299892, 0.998080135014099, 0.9979120717308554, 0.9977319231985478, 0.9975390039639489, 0.9973325998199832, 0.9971119670126036, 0.996876331436878, 0.9966248878222852, 0.9963567989072191, 0.9960711946027035, 0.9957671711453152, 0.9954437902393161, 0.9951000781879951, 0.9947350250142191, 0.9943475835701934, 0.9939366686364304, 0.9935011560099285, 0.9930398815815602, 0.9925516404026683, 0.9920351857408729, 0.9914892281250863, 0.9909124343797379, 0.9903034266482077, 0.9896607814054699, 0.9889830284599445, 0.9882686499445592, 0.9875160792970205, 0.9867237002292923, 0.9858898456862866, 0.9850127967937606, 0.984090781795425, 0.9831219749792602, 0.982104495593043, 0.9810364067490811, 0.9799157143181576, 0.978740365812685, 0.9775082492590679, 0.9762171920592747, 0.9748649598416194, 0.9734492553007513, 0.9719677170268558, 0.9704179183240623, 0.9687973660180627, 0.9671034992529387, 0.9653336882771985, 0.9634852332190221, 0.9615553628507172, 0.9595412333423818, 0.9574399270047795, 0.9552484510214205, 0.9529637361698543, 0.9505826355321707, 0.9481019231947095, 0.9455182929369806, 0.9428283569097924, 0.9400286443025894, 0.9371156}, {1.0, 0.9999999999999953, 0.9999999999997022, 0.9999999999966079, 0.9999999999809411, 0.9999999999272962, 0.9999999997829073, 0.9999999994525735, 0.9999999987802313, 0.9999999975271793, 0.9999999953469515, 0.9999999917568408, 0.9999999861060718, 0.9999999775406239, 0.9999999649647041, 0.9999999469988698, 0.9999999219348009, 0.9999998876867218, 0.9999998417394735, 0.999999781093236, 0.9999997022048986, 0.9999996009260829, 0.9999994724378124, 0.9999993111818348, 0.999999110788592, 0.999998864001841, 0.9999985625999245, 0.9999981973136907, 0.9999977577410636, 0.9999972322582629, 0.9999966079276733, 0.9999958704023647, 0.9999950038272605, 0.9999939907369569, 0.9999928119501926, 0.9999914464609663, 0.9999898713263058, 0.9999880615506863, 0.9999859899670982, 0.9999836271147652, 0.9999809411135118, 0.9999778975347812, 0.999974459269302, 0.9999705863914059, 0.999966236019994, 0.9999613621761544, 0.9999559156374276, 0.9999498437887238, 0.9999430904698884, 0.9999355958199183, 0.9999272961178276, 0.9999181236201629, 0.9999080063951687, 0.9998968681536032, 0.9998846280762023, 0.9998712006377948, 0.9998564954280671, 0.9998404169689776, 0.9998228645288206, 0.9998037319329405, 0.9997829073710953, 0.9997602732014707, 0.9997357057513431, 0.999709075114393, 0.9996802449446679, 0.9996490722471952, 0.9996154071652449, 0.9995790927642417, 0.9995399648123278, 0.9994978515575741, 0.999452573501843, 0.9994039431712994, 0.9993517648835726, 0.9992958345115667, 0.9992359392439231, 0.9991718573421298, 0.9991033578942833, 0.9990302005654985, 0.998952135344969, 0.9988689022896773, 0.9987802312647548, 0.9986858416804911, 0.9985854422259942, 0.9984787305994991, 0.9983653932353271, 0.9982451050274953, 0.9981175290499744, 0.9979823162735979, 0.9978391052796202, 0.9976875219699247, 0.997527179273882, 0.9973576768518573, 0.9971786007953681, 0.9969895233238919, 0.9967900024783226, 0.9965795818110783, 0.9963577900728574, 0.9961241408960458, 0.995878132474773, 0.9956192472416178, 0.9953469515409651, 0.9950606952990115, 0.9947599116904207, 0.9944440168016286, 0.9941124092907996, 0.9937644700444305, 0.9933995618306056, 0.9930170289489021, 0.9926161968769434, 0.992196371913604, 0.9917568408188636, 0.9912968704503108, 0.9908157073962964, 0.9903125776057377, 0.9897866860145708, 0.9892372161688545, 0.9886633298445227, 0.9880641666637873, 0.9874388437081904, 0.9867864551283071, 0.9861060717500971, 0.985396740677907, 0.9846574848941214, 0.9838873028554654, 0.9830851680859551, 0.9822500287664989, 0.9813808073211485, 0.9804764}, {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}, {1.0, 1.0000000000000047, 1.0000000000003038, 1.0000000000034597, 1.0000000000194382, 1.000000000074151, 1.0000000002214138, 1.0000000005583225, 1.000000001244047, 1.0000000025220401, 1.0000000047456632, 1.000000008407232, 1.0000000141704746, 1.00000002290641, 1.0000000357326424, 1.0000000540560707, 1.0000000796190178, 1.0000001145487747, 1.0000001614105622, 1.0000002232639098, 1.0000003037224496, 1.0000004070171307, 1.0000005380628465, 1.0000007025284818, 1.000000906910375, 1.0000011586091981, 1.0000014660102534, 1.000001838567187, 1.0000022868891185, 1.00000282283119, 1.0000034595885279, 1.0000042117936259, 1.0000050956171416, 1.000006128872112, 1.000007331121585, 1.0000087237896673, 1.0000103302759908, 1.0000121760735943, 1.0000142888902226, 1.0000166987730426, 1.0000194382367766, 1.0000225423952513, 1.0000260490963657, 1.0000299990604729, 1.000034436022182, 1.0000394068755751, 1.0000449618228406, 1.0000511545263258, 1.0000580422640029, 1.0000656860883557, 1.0000741509886801, 1.0000835060568027, 1.0000938246562172, 1.0001051845946354, 1.0001176682999573, 1.000131362999657, 1.0001463609035854, 1.0001627593901905, 1.0001806611961532, 1.000200174609442, 1.0002214136657828, 1.0002444983485461, 1.000269554792052, 1.0002967154882902, 1.0003261194970592, 1.0003579126595197, 1.000392247815168, 1.0004292850222227, 1.0004691917814321, 1.0005121432632953, 1.000558322538702, 1.0006079208129879, 1.0006611376634087, 1.0007181812800294, 1.0007792687100308, 1.0008446261054336, 1.000914488974239, 1.0009891024349855, 1.0010687214747234, 1.0011536112104062, 1.0012440471536985, 1.0013403154792009, 1.0014427132960908, 1.001551548923183, 1.0016671421674035, 1.0017898246056827, 1.0019199398702647, 1.0020578439374328, 1.0022039054196534, 1.0023585058611355, 1.0025220400368071, 1.0026949162547094, 1.0028775566618078, 1.0030703975532176, 1.0032738896848503, 1.0034884985894736, 1.0037147048961896, 1.00395300465333, 1.004203909654768, 1.0044679477696459, 1.0047456632755227, 1.0050376171949345, 1.005344387635375, 1.0056665701326912, 1.006004777997897, 1.0063596426674022, 1.0067318140566603, 1.0071219609172322, 1.0075307711972652, 1.0079589524053931, 1.0084072319780484, 1.0088763576501938, 1.0093670978294713, 1.0098802419737667, 1.0104166009721909, 1.010977007529479, 1.0115623165538064, 1.0121734055480207, 1.0128111750042907, 1.013476548802174, 1.0141704746100983, 1.0148939242902633, 1.0156478943069556, 1.016433406138284, 1.0172515066913297, 1.0181032687207134, 1.01898979125058, 1.0199122}, {1.0, 1.0000000000000149, 1.0000000000009481, 1.0000000000108007, 1.0000000000606857, 1.0000000002314975, 1.000000000691248, 1.0000000017430692, 1.0000000038838848, 1.0000000078737472, 1.0000000148158443, 1.000000026247172, 1.0000000442398742, 1.0000000715132509, 1.0000001115564334, 1.000000168761727, 1.0000002485686208, 1.0000003576184653, 1.0000005039198165, 1.00000069702445, 1.0000009482140382, 1.000001270697499, 1.0000016798190097, 1.0000021932766892, 1.0000028313519465, 1.0000036171494986, 1.0000045768480532, 1.0000057399616615, 1.000007139611736, 1.0000088128097373, 1.0000108007505284, 1.0000131491163944, 1.0000159083917324, 1.0000191341884066, 1.0000228875817727, 1.0000272354573667, 1.0000322508682655, 1.0000380134031104, 1.0000446095648012, 1.0000521331598566, 1.0000606856984415, 1.0000703768050623, 1.0000813246399298, 1.000093656330989, 1.0001075084166169, 1.0001230272989865, 1.0001403697080997, 1.0001597031764875, 1.0001812065245754, 1.0002050703567196, 1.0002314975679076, 1.0002607038611286, 1.000292918275409, 1.0003283837245178, 1.0003673575463365, 1.0004101120629, 1.000456935151101, 1.000508130824065, 1.000564019823191, 1.00062494022086, 1.000691248033811, 1.0007633178471849, 1.0008415434492337, 1.0009263384767009, 1.0010181370708653, 1.0011173945442546, 1.0012245880580264, 1.0013402173100148, 1.0014648052334467, 1.0015988987063238, 1.0017430692714728, 1.0018979138672632, 1.0020640555689915, 1.0022421443409335, 1.002432857799065, 1.0026369019844479, 1.0028550121472843, 1.00308795354164, 1.0033365222308317, 1.0036015459034857, 1.003883884700261, 1.0041844320512403, 1.0045041155239904, 1.004843897682287, 1.00520477695551, 1.0055877885187026, 1.0059940051833023, 1.0064245382985348, 1.006880538663479, 1.0073631974497963, 1.0078737471351296, 1.008413462447169, 1.008983661318385, 1.0095857058514275, 1.0102210032951957, 1.0108910070315718, 1.011597217572824, 1.0123411835696772, 1.0131245028300493, 1.0139488233484573, 1.0148158443460882, 1.0157273173215406, 1.0166850471122297, 1.017690892966463, 1.018746769626182, 1.0198546484203714, 1.0210165583691362, 1.022234587298445, 1.0235108829655426, 1.0248476541950278, 1.0262471720256006, 1.027711770867476, 1.0292438496704641, 1.0308458731027206, 1.0325203727401608, 1.0342699482665438, 1.0360972686842238, 1.0380050735355673, 1.0399961741350399, 1.042073454811958, 1.04423987416391, 1.0464984663208448, 1.0488523422198255, 1.051304690890453, 1.053858780750956, 1.0565179609149487, 1.0592856625088545, 1.0621654}, {1.0, 1.0000000000000255, 1.000000000001639, 1.0000000000186688, 1.0000000001048943, 1.0000000004001401, 1.0000000011948122, 1.0000000030128702, 1.0000000067132389, 1.0000000136096587, 1.0000000256089738, 1.0000000453678595, 1.0000000764679864, 1.0000001236096256, 1.000000192823691, 1.0000002917022184, 1.0000004296472869, 1.0000006181383747, 1.000000871018157, 1.000001204796739, 1.0000016389743303, 1.000002196382355, 1.0000029035430034, 1.000003791047219, 1.0000048939511264, 1.000006252190896, 1.0000079110160478, 1.0000099214411948, 1.0000123407162225, 1.0000152328149083, 1.00001866894198, 1.0000227280586114, 1.0000274974263563, 1.000033073169523, 1.0000395608559847, 1.0000470760964295, 1.0000557451620493, 1.000065705620667, 1.000077106991301, 1.0000901114171699, 1.0001048943571336, 1.0001216452955755, 1.0001405684707207, 1.0001618836213946, 1.0001858267522177, 1.0002126509172415, 1.0002426270220208, 1.0002760446441257, 1.0003132128720909, 1.0003544611628048, 1.0004001402173366, 1.0004506228752006, 1.000506305027061, 1.0005676065458742, 1.0006349722364685, 1.000708872803565, 1.0007898058382332, 1.0008782968227894, 1.0009749001541295, 1.0010802001855026, 1.0011948122867234, 1.0013193839228205, 1.001454595751126, 1.001601162736803, 1.0017598352868091, 1.0019314004023019, 1.0021166828494799, 1.0023165463488648, 1.0025318947830195, 1.0027636734227063, 1.003012870171483, 1.003280516828737, 1.0035676903711592, 1.0038755142526548, 1.0042051597226938, 1.0045578471630987, 1.0049348474432722, 1.0053374832938626, 1.0057671306988667, 1.0062252203061728, 1.0067132388565414, 1.0072327306310243, 1.0077852989168221, 1.0083726074915806, 1.0089963821261256, 1.009658412105635, 1.010360551769251, 1.0111047220681308, 1.0118929121419333, 1.012727180913748, 1.0136096587034578, 1.0145425488595459, 1.0155281294093352, 1.0165687547276714, 1.0176668572240406, 1.0188249490481271, 1.0200456238138111, 1.0213315583416007, 1.0226855144195075, 1.0241103405823564, 1.0256089739095362, 1.027184441841188, 1.028839864012832, 1.0305784541084329, 1.0324035217319039, 1.0343184742970488, 1.0363268189359423, 1.0384321644257501, 1.0406382231339857, 1.0429488129822073, 1.0453678594281517, 1.0478993974663078, 1.0505475736469276, 1.053316648113477, 1.0562109966585231, 1.0592351127980624, 1.0623936098642848, 1.0656912231167786, 1.0691328118721717, 1.0727233616522132, 1.0764679863502924, 1.080371930416396, 1.0844405710605045, 1.0886794204744272, 1.0930941280720745, 1.0976904827481695, 1.102474415155399, 1.107452} }; static MYFLT SUPERSAW_BALANCES[7][128] = {{0.044372, 0.0540113055986112, 0.0635591436542873, 0.07301551416702834, 0.08238041713683428, 0.09165385256370512, 0.10083582044764089, 0.10992632078864159, 0.11892535358670717, 0.12783291884183767, 0.1366490165540331, 0.14537364672329345, 0.1540068093496187, 0.16254850443300886, 0.17099873197346394, 0.17935749197098394, 0.18762478442556885, 0.19580060933721868, 0.2038849667059334, 0.21187785653171307, 0.2197792788145576, 0.2275892335544671, 0.2353077207514415, 0.24293474040548083, 0.25047029251658504, 0.2579143770847542, 0.2652669941099882, 0.2725281435922872, 0.27969782553165107, 0.2867760399280799, 0.2937627867815736, 0.30065806609213225, 0.3074618778597557, 0.3141742220844442, 0.32079509876619755, 0.3273245079050158, 0.333762449500899, 0.34010892355384714, 0.3463639300638601, 0.35252746903093807, 0.3585995404550809, 0.36458014433628866, 0.3704692806745614, 0.37626694946989897, 0.3819731507223015, 0.3875878844317689, 0.39311115059830126, 0.3985429492218985, 0.40388328030256065, 0.4091321438402877, 0.4142895398350797, 0.4193554682869366, 0.4243299291958584, 0.4292129225618452, 0.4340044483848969, 0.4387045066650134, 0.4433130974021948, 0.4478302205964412, 0.4522558762477525, 0.45659006435612876, 0.4608327849215699, 0.4649840379440759, 0.4690438234236469, 0.47301214136028275, 0.4768889917539835, 0.4806743746047492, 0.4843682899125799, 0.4879707376774754, 0.4914817178994358, 0.4949012305784613, 0.4982292757145515, 0.5014658533077067, 0.5046109633579267, 0.5076646058652117, 0.5106267808295617, 0.5134974882509765, 0.5162767281294562, 0.518964500465001, 0.5215608052576105, 0.524065642507285, 0.5264790122140244, 0.5288009143778287, 0.531031348998698, 0.5331703160766321, 0.5352178156116313, 0.5371738476036952, 0.5390384120528241, 0.5408115089590179, 0.5424931383222766, 0.5440833001426003, 0.5455819944199888, 0.5469892211544423, 0.5483049803459606, 0.549529271994544, 0.5506620961001921, 0.5517034526629053, 0.5526533416826834, 0.5535117631595262, 0.5542787170934341, 0.5549542034844069, 0.5555382223324447, 0.5560307736375473, 0.5564318573997148, 0.5567414736189472, 0.5569596222952445, 0.557086303428607, 0.5571215170190341, 0.5570652630665262, 0.5569175415710832, 0.5566783525327051, 0.556347695951392, 0.5559255718271436, 0.5554119801599603, 0.5548069209498419, 0.5541103941967883, 0.5533223999007997, 0.552442938061876, 0.5514720086800173, 0.5504096117552235, 0.5492557472874944, 0.5480104152768307, 0.5466736157232315, 0.5452453486266973, 0.543725613987228, 0.5421144118048237, 0.5404117420794842, 0.5386176048112096, 0.536732}, {0.044372, 0.0540113055986112, 0.0635591436542873, 0.07301551416702834, 0.08238041713683428, 0.09165385256370512, 0.10083582044764089, 0.10992632078864159, 0.11892535358670717, 0.12783291884183767, 0.1366490165540331, 0.14537364672329345, 0.1540068093496187, 0.16254850443300886, 0.17099873197346394, 0.17935749197098394, 0.18762478442556885, 0.19580060933721868, 0.2038849667059334, 0.21187785653171307, 0.2197792788145576, 0.2275892335544671, 0.2353077207514415, 0.24293474040548083, 0.25047029251658504, 0.2579143770847542, 0.2652669941099882, 0.2725281435922872, 0.27969782553165107, 0.2867760399280799, 0.2937627867815736, 0.30065806609213225, 0.3074618778597557, 0.3141742220844442, 0.32079509876619755, 0.3273245079050158, 0.333762449500899, 0.34010892355384714, 0.3463639300638601, 0.35252746903093807, 0.3585995404550809, 0.36458014433628866, 0.3704692806745614, 0.37626694946989897, 0.3819731507223015, 0.3875878844317689, 0.39311115059830126, 0.3985429492218985, 0.40388328030256065, 0.4091321438402877, 0.4142895398350797, 0.4193554682869366, 0.4243299291958584, 0.4292129225618452, 0.4340044483848969, 0.4387045066650134, 0.4433130974021948, 0.4478302205964412, 0.4522558762477525, 0.45659006435612876, 0.4608327849215699, 0.4649840379440759, 0.4690438234236469, 0.47301214136028275, 0.4768889917539835, 0.4806743746047492, 0.4843682899125799, 0.4879707376774754, 0.4914817178994358, 0.4949012305784613, 0.4982292757145515, 0.5014658533077067, 0.5046109633579267, 0.5076646058652117, 0.5106267808295617, 0.5134974882509765, 0.5162767281294562, 0.518964500465001, 0.5215608052576105, 0.524065642507285, 0.5264790122140244, 0.5288009143778287, 0.531031348998698, 0.5331703160766321, 0.5352178156116313, 0.5371738476036952, 0.5390384120528241, 0.5408115089590179, 0.5424931383222766, 0.5440833001426003, 0.5455819944199888, 0.5469892211544423, 0.5483049803459606, 0.549529271994544, 0.5506620961001921, 0.5517034526629053, 0.5526533416826834, 0.5535117631595262, 0.5542787170934341, 0.5549542034844069, 0.5555382223324447, 0.5560307736375473, 0.5564318573997148, 0.5567414736189472, 0.5569596222952445, 0.557086303428607, 0.5571215170190341, 0.5570652630665262, 0.5569175415710832, 0.5566783525327051, 0.556347695951392, 0.5559255718271436, 0.5554119801599603, 0.5548069209498419, 0.5541103941967883, 0.5533223999007997, 0.552442938061876, 0.5514720086800173, 0.5504096117552235, 0.5492557472874944, 0.5480104152768307, 0.5466736157232315, 0.5452453486266973, 0.543725613987228, 0.5421144118048237, 0.5404117420794842, 0.5386176048112096, 0.536732}, {0.044372, 0.0540113055986112, 0.0635591436542873, 0.07301551416702834, 0.08238041713683428, 0.09165385256370512, 0.10083582044764089, 0.10992632078864159, 0.11892535358670717, 0.12783291884183767, 0.1366490165540331, 0.14537364672329345, 0.1540068093496187, 0.16254850443300886, 0.17099873197346394, 0.17935749197098394, 0.18762478442556885, 0.19580060933721868, 0.2038849667059334, 0.21187785653171307, 0.2197792788145576, 0.2275892335544671, 0.2353077207514415, 0.24293474040548083, 0.25047029251658504, 0.2579143770847542, 0.2652669941099882, 0.2725281435922872, 0.27969782553165107, 0.2867760399280799, 0.2937627867815736, 0.30065806609213225, 0.3074618778597557, 0.3141742220844442, 0.32079509876619755, 0.3273245079050158, 0.333762449500899, 0.34010892355384714, 0.3463639300638601, 0.35252746903093807, 0.3585995404550809, 0.36458014433628866, 0.3704692806745614, 0.37626694946989897, 0.3819731507223015, 0.3875878844317689, 0.39311115059830126, 0.3985429492218985, 0.40388328030256065, 0.4091321438402877, 0.4142895398350797, 0.4193554682869366, 0.4243299291958584, 0.4292129225618452, 0.4340044483848969, 0.4387045066650134, 0.4433130974021948, 0.4478302205964412, 0.4522558762477525, 0.45659006435612876, 0.4608327849215699, 0.4649840379440759, 0.4690438234236469, 0.47301214136028275, 0.4768889917539835, 0.4806743746047492, 0.4843682899125799, 0.4879707376774754, 0.4914817178994358, 0.4949012305784613, 0.4982292757145515, 0.5014658533077067, 0.5046109633579267, 0.5076646058652117, 0.5106267808295617, 0.5134974882509765, 0.5162767281294562, 0.518964500465001, 0.5215608052576105, 0.524065642507285, 0.5264790122140244, 0.5288009143778287, 0.531031348998698, 0.5331703160766321, 0.5352178156116313, 0.5371738476036952, 0.5390384120528241, 0.5408115089590179, 0.5424931383222766, 0.5440833001426003, 0.5455819944199888, 0.5469892211544423, 0.5483049803459606, 0.549529271994544, 0.5506620961001921, 0.5517034526629053, 0.5526533416826834, 0.5535117631595262, 0.5542787170934341, 0.5549542034844069, 0.5555382223324447, 0.5560307736375473, 0.5564318573997148, 0.5567414736189472, 0.5569596222952445, 0.557086303428607, 0.5571215170190341, 0.5570652630665262, 0.5569175415710832, 0.5566783525327051, 0.556347695951392, 0.5559255718271436, 0.5554119801599603, 0.5548069209498419, 0.5541103941967883, 0.5533223999007997, 0.552442938061876, 0.5514720086800173, 0.5504096117552235, 0.5492557472874944, 0.5480104152768307, 0.5466736157232315, 0.5452453486266973, 0.543725613987228, 0.5421144118048237, 0.5404117420794842, 0.5386176048112096, 0.536732}, {0.99785, 0.9934904251968504, 0.9891308503937009, 0.9847712755905512, 0.9804117007874016, 0.976052125984252, 0.9716925511811024, 0.9673329763779528, 0.9629734015748032, 0.9586138267716535, 0.954254251968504, 0.9498946771653544, 0.9455351023622047, 0.9411755275590551, 0.9368159527559056, 0.9324563779527559, 0.9280968031496063, 0.9237372283464567, 0.9193776535433071, 0.9150180787401575, 0.9106585039370079, 0.9062989291338582, 0.9019393543307087, 0.8975797795275591, 0.8932202047244094, 0.8888606299212598, 0.8845010551181103, 0.8801414803149606, 0.875781905511811, 0.8714223307086615, 0.8670627559055119, 0.8627031811023622, 0.8583436062992126, 0.8539840314960631, 0.8496244566929134, 0.8452648818897638, 0.8409053070866142, 0.8365457322834646, 0.832186157480315, 0.8278265826771654, 0.8234670078740158, 0.8191074330708662, 0.8147478582677166, 0.8103882834645669, 0.8060287086614173, 0.8016691338582678, 0.7973095590551181, 0.7929499842519685, 0.788590409448819, 0.7842308346456693, 0.7798712598425197, 0.7755116850393701, 0.7711521102362204, 0.7667925354330709, 0.7624329606299213, 0.7580733858267716, 0.7537138110236221, 0.7493542362204725, 0.7449946614173228, 0.7406350866141733, 0.7362755118110236, 0.731915937007874, 0.7275563622047244, 0.7231967874015748, 0.7188372125984253, 0.7144776377952756, 0.710118062992126, 0.7057584881889765, 0.7013989133858267, 0.6970393385826772, 0.6926797637795276, 0.6883201889763779, 0.6839606141732284, 0.6796010393700788, 0.6752414645669291, 0.6708818897637796, 0.6665223149606299, 0.6621627401574803, 0.6578031653543307, 0.6534435905511811, 0.6490840157480315, 0.6447244409448819, 0.6403648661417323, 0.6360052913385827, 0.631645716535433, 0.6272861417322835, 0.622926566929134, 0.6185669921259842, 0.6142074173228347, 0.609847842519685, 0.6054882677165354, 0.6011286929133859, 0.5967691181102361, 0.5924095433070866, 0.5880499685039371, 0.5836903937007873, 0.5793308188976378, 0.5749712440944883, 0.5706116692913386, 0.566252094488189, 0.5618925196850394, 0.5575329448818898, 0.5531733700787402, 0.5488137952755906, 0.544454220472441, 0.5400946456692914, 0.5357350708661417, 0.5313754960629922, 0.5270159212598425, 0.5226563464566929, 0.5182967716535434, 0.5139371968503937, 0.5095776220472441, 0.5052180472440946, 0.500858472440945, 0.4964988976377953, 0.4921393228346457, 0.48777974803149604, 0.4834201732283465, 0.4790605984251969, 0.47470102362204725, 0.4703414488188977, 0.4659818740157481, 0.46162229921259845, 0.4572627244094488, 0.4529031496062992, 0.44854357480314966, 0.444184}, {0.044372, 0.054437289850579704, 0.06441111215822432, 0.07429346692293384, 0.08408435414470829, 0.09378377382354765, 0.10339172595945192, 0.11290821055242112, 0.12233322760245521, 0.1316667771095542, 0.14090885907371814, 0.150059473494947, 0.15911862037324073, 0.16808629970859942, 0.176962511501023, 0.1857472557505115, 0.1944405324570649, 0.20304234162068327, 0.21155268324136647, 0.21997155731911466, 0.2282989638539277, 0.23653490284580572, 0.2446793742947486, 0.25273237820075645, 0.2606939145638291, 0.26856398338396675, 0.27634258466116934, 0.2840297183954368, 0.2916253845867692, 0.2991295832351665, 0.3065423143406287, 0.31386357790315583, 0.3210933739227479, 0.3282317023994048, 0.3352785633331267, 0.3422339567239135, 0.34909788257176516, 0.3558703408766818, 0.3625513316386633, 0.3691408548577098, 0.3756389105338211, 0.3820454986669974, 0.3883606192572386, 0.3945842723045447, 0.4007164578089156, 0.4067571757703516, 0.41270642618885245, 0.4185642090644182, 0.4243305243970488, 0.4300053721867444, 0.43558875243350487, 0.44108066513733035, 0.44648111029822063, 0.4517900879161758, 0.457007597991196, 0.46213364052328115, 0.46716821551243104, 0.4721113229586459, 0.4769629628619257, 0.48172313522227056, 0.4863918400396801, 0.4909690773141547, 0.4954548470456941, 0.4998491492342985, 0.5041519838799677, 0.508363350982702, 0.5124832505425011, 0.5165116825593651, 0.5204486470332941, 0.524294143964288, 0.5280481733523468, 0.5317107351974705, 0.535281829499659, 0.5387614562589126, 0.542149615475231, 0.5454463071486143, 0.5486515312790626, 0.5517652878665756, 0.5547875769111539, 0.5577183984127968, 0.5605577523715047, 0.5633056387872776, 0.5659620576601153, 0.568527008990018, 0.5710004927769856, 0.5733825090210181, 0.5756730577221155, 0.5778721388802778, 0.5799797524955049, 0.5819958985677972, 0.5839205770971542, 0.5857537880835761, 0.587495531527063, 0.5891458074276149, 0.5907046157852317, 0.5921719565999132, 0.5935478298716598, 0.5948322356004713, 0.5960251737863476, 0.597126644429289, 0.598136647529295, 0.5990551830863663, 0.5998822511005023, 0.6006178515717031, 0.601261984499969, 0.6018146498852998, 0.6022758477276954, 0.6026455780271561, 0.6029238407836814, 0.6031106359972721, 0.6032059636679274, 0.6032098237956476, 0.6031222163804327, 0.6029431414222828, 0.6026725989211977, 0.6023105888771778, 0.6018571112902225, 0.6013121661603325, 0.6006757534875071, 0.5999478732717465, 0.5991285255130511, 0.5982177102114203, 0.5972154273668548, 0.596121676979354, 0.594936459048918, 0.5936597735755472, 0.5922916205592411, 0.590832}, {0.044372, 0.054437289850579704, 0.06441111215822432, 0.07429346692293384, 0.08408435414470829, 0.09378377382354765, 0.10339172595945192, 0.11290821055242112, 0.12233322760245521, 0.1316667771095542, 0.14090885907371814, 0.150059473494947, 0.15911862037324073, 0.16808629970859942, 0.176962511501023, 0.1857472557505115, 0.1944405324570649, 0.20304234162068327, 0.21155268324136647, 0.21997155731911466, 0.2282989638539277, 0.23653490284580572, 0.2446793742947486, 0.25273237820075645, 0.2606939145638291, 0.26856398338396675, 0.27634258466116934, 0.2840297183954368, 0.2916253845867692, 0.2991295832351665, 0.3065423143406287, 0.31386357790315583, 0.3210933739227479, 0.3282317023994048, 0.3352785633331267, 0.3422339567239135, 0.34909788257176516, 0.3558703408766818, 0.3625513316386633, 0.3691408548577098, 0.3756389105338211, 0.3820454986669974, 0.3883606192572386, 0.3945842723045447, 0.4007164578089156, 0.4067571757703516, 0.41270642618885245, 0.4185642090644182, 0.4243305243970488, 0.4300053721867444, 0.43558875243350487, 0.44108066513733035, 0.44648111029822063, 0.4517900879161758, 0.457007597991196, 0.46213364052328115, 0.46716821551243104, 0.4721113229586459, 0.4769629628619257, 0.48172313522227056, 0.4863918400396801, 0.4909690773141547, 0.4954548470456941, 0.4998491492342985, 0.5041519838799677, 0.508363350982702, 0.5124832505425011, 0.5165116825593651, 0.5204486470332941, 0.524294143964288, 0.5280481733523468, 0.5317107351974705, 0.535281829499659, 0.5387614562589126, 0.542149615475231, 0.5454463071486143, 0.5486515312790626, 0.5517652878665756, 0.5547875769111539, 0.5577183984127968, 0.5605577523715047, 0.5633056387872776, 0.5659620576601153, 0.568527008990018, 0.5710004927769856, 0.5733825090210181, 0.5756730577221155, 0.5778721388802778, 0.5799797524955049, 0.5819958985677972, 0.5839205770971542, 0.5857537880835761, 0.587495531527063, 0.5891458074276149, 0.5907046157852317, 0.5921719565999132, 0.5935478298716598, 0.5948322356004713, 0.5960251737863476, 0.597126644429289, 0.598136647529295, 0.5990551830863663, 0.5998822511005023, 0.6006178515717031, 0.601261984499969, 0.6018146498852998, 0.6022758477276954, 0.6026455780271561, 0.6029238407836814, 0.6031106359972721, 0.6032059636679274, 0.6032098237956476, 0.6031222163804327, 0.6029431414222828, 0.6026725989211977, 0.6023105888771778, 0.6018571112902225, 0.6013121661603325, 0.6006757534875071, 0.5999478732717465, 0.5991285255130511, 0.5982177102114203, 0.5972154273668548, 0.596121676979354, 0.594936459048918, 0.5936597735755472, 0.5922916205592411, 0.590832}, {0.044372, 0.054437289850579704, 0.06441111215822432, 0.07429346692293384, 0.08408435414470829, 0.09378377382354765, 0.10339172595945192, 0.11290821055242112, 0.12233322760245521, 0.1316667771095542, 0.14090885907371814, 0.150059473494947, 0.15911862037324073, 0.16808629970859942, 0.176962511501023, 0.1857472557505115, 0.1944405324570649, 0.20304234162068327, 0.21155268324136647, 0.21997155731911466, 0.2282989638539277, 0.23653490284580572, 0.2446793742947486, 0.25273237820075645, 0.2606939145638291, 0.26856398338396675, 0.27634258466116934, 0.2840297183954368, 0.2916253845867692, 0.2991295832351665, 0.3065423143406287, 0.31386357790315583, 0.3210933739227479, 0.3282317023994048, 0.3352785633331267, 0.3422339567239135, 0.34909788257176516, 0.3558703408766818, 0.3625513316386633, 0.3691408548577098, 0.3756389105338211, 0.3820454986669974, 0.3883606192572386, 0.3945842723045447, 0.4007164578089156, 0.4067571757703516, 0.41270642618885245, 0.4185642090644182, 0.4243305243970488, 0.4300053721867444, 0.43558875243350487, 0.44108066513733035, 0.44648111029822063, 0.4517900879161758, 0.457007597991196, 0.46213364052328115, 0.46716821551243104, 0.4721113229586459, 0.4769629628619257, 0.48172313522227056, 0.4863918400396801, 0.4909690773141547, 0.4954548470456941, 0.4998491492342985, 0.5041519838799677, 0.508363350982702, 0.5124832505425011, 0.5165116825593651, 0.5204486470332941, 0.524294143964288, 0.5280481733523468, 0.5317107351974705, 0.535281829499659, 0.5387614562589126, 0.542149615475231, 0.5454463071486143, 0.5486515312790626, 0.5517652878665756, 0.5547875769111539, 0.5577183984127968, 0.5605577523715047, 0.5633056387872776, 0.5659620576601153, 0.568527008990018, 0.5710004927769856, 0.5733825090210181, 0.5756730577221155, 0.5778721388802778, 0.5799797524955049, 0.5819958985677972, 0.5839205770971542, 0.5857537880835761, 0.587495531527063, 0.5891458074276149, 0.5907046157852317, 0.5921719565999132, 0.5935478298716598, 0.5948322356004713, 0.5960251737863476, 0.597126644429289, 0.598136647529295, 0.5990551830863663, 0.5998822511005023, 0.6006178515717031, 0.601261984499969, 0.6018146498852998, 0.6022758477276954, 0.6026455780271561, 0.6029238407836814, 0.6031106359972721, 0.6032059636679274, 0.6032098237956476, 0.6031222163804327, 0.6029431414222828, 0.6026725989211977, 0.6023105888771778, 0.6018571112902225, 0.6013121661603325, 0.6006757534875071, 0.5999478732717465, 0.5991285255130511, 0.5982177102114203, 0.5972154273668548, 0.596121676979354, 0.594936459048918, 0.5936597735755472, 0.5922916205592411, 0.590832} }; /**************/ /* SuperSaw object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *freq; Stream *freq_stream; PyObject *detune; Stream *detune_stream; PyObject *bal; Stream *bal_stream; int modebuffer[5]; double pointerPos[7]; // sample memories MYFLT x1; MYFLT x2; MYFLT y1; MYFLT y2; // variables MYFLT c; MYFLT w0; MYFLT alpha; // coefficients MYFLT b0; MYFLT b1; MYFLT b2; MYFLT a0; MYFLT a1; MYFLT a2; MYFLT lastFilterFreq; MYFLT nyquist; } SuperSaw; static void SuperSaw_readframes_iii(SuperSaw *self) { MYFLT fr, det, bal, twoOnSr, val; int i, j, det_ind, bal_ind; MYFLT inc[7]; MYFLT amp[7]; fr = PyFloat_AS_DOUBLE(self->freq); det = _clip(PyFloat_AS_DOUBLE(self->detune)); bal = _clip(PyFloat_AS_DOUBLE(self->bal)); twoOnSr = 2.0 / self->sr; if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; det_ind = (int)(det * 126); bal_ind = (int)(bal * 126); if (fr != self->lastFilterFreq) { self->lastFilterFreq = fr; self->w0 = TWOPI * fr / self->sr; self->c = MYCOS(self->w0); self->alpha = MYSIN(self->w0) * 0.5; self->b0 = self->b2 = (1 + self->c) * 0.5; self->b1 = -(1 + self->c); self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } for (j=0; j<7; j++) { inc[j] = fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr; amp[j] = SUPERSAW_BALANCES[j][bal_ind]; } for (i=0; ibufsize; i++) { val = 0.0; for (j=0; j<7; j++) { val += self->pointerPos[j] * amp[j]; self->pointerPos[j] += inc[j]; if (self->pointerPos[j] < -1.0) self->pointerPos[j] += 2.0; else if (self->pointerPos[j] >= 1.0) self->pointerPos[j] -= 2.0; } self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = self->data[i]; self->x2 = self->x1; self->x1 = val; self->data[i] *= 0.2; } } static void SuperSaw_readframes_aii(SuperSaw *self) { MYFLT fr, det, bal, twoOnSr, val; int i, j, det_ind, bal_ind; MYFLT *freq = Stream_getData((Stream *)self->freq_stream); det = _clip(PyFloat_AS_DOUBLE(self->detune)); bal = _clip(PyFloat_AS_DOUBLE(self->bal)); twoOnSr = 2.0 / self->sr; det_ind = (int)(det * 126); bal_ind = (int)(bal * 126); for (i=0; ibufsize; i++) { fr = freq[i]; if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; if (fr != self->lastFilterFreq) { self->lastFilterFreq = fr; self->w0 = TWOPI * fr / self->sr; self->c = MYCOS(self->w0); self->alpha = MYSIN(self->w0) * 0.5; self->b0 = self->b2 = (1 + self->c) * 0.5; self->b1 = -(1 + self->c); self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } val = 0.0; for (j=0; j<7; j++) { val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind]; self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr; if (self->pointerPos[j] < -1.0) self->pointerPos[j] += 2.0; else if (self->pointerPos[j] >= 1.0) self->pointerPos[j] -= 2.0; } self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = self->data[i]; self->x2 = self->x1; self->x1 = val; self->data[i] *= 0.2; } } static void SuperSaw_readframes_iai(SuperSaw *self) { MYFLT fr, bal, twoOnSr, val; int i, j, det_ind, bal_ind; fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *detune = Stream_getData((Stream *)self->detune_stream); bal = _clip(PyFloat_AS_DOUBLE(self->bal)); twoOnSr = 2.0 / self->sr; if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; bal_ind = (int)(bal * 126); if (fr != self->lastFilterFreq) { self->lastFilterFreq = fr; self->w0 = TWOPI * fr / self->sr; self->c = MYCOS(self->w0); self->alpha = MYSIN(self->w0) * 0.5; self->b0 = self->b2 = (1 + self->c) * 0.5; self->b1 = -(1 + self->c); self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } for (i=0; ibufsize; i++) { det_ind = (int)(_clip(detune[i]) * 126); val = 0.0; for (j=0; j<7; j++) { val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind]; self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr; if (self->pointerPos[j] < -1.0) self->pointerPos[j] += 2.0; else if (self->pointerPos[j] >= 1.0) self->pointerPos[j] -= 2.0; } self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = self->data[i]; self->x2 = self->x1; self->x1 = val; self->data[i] *= 0.2; } } static void SuperSaw_readframes_aai(SuperSaw *self) { MYFLT fr, bal, twoOnSr, val; int i, j, det_ind, bal_ind; MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT *detune = Stream_getData((Stream *)self->detune_stream); bal = _clip(PyFloat_AS_DOUBLE(self->bal)); twoOnSr = 2.0 / self->sr; bal_ind = (int)(bal * 126); for (i=0; ibufsize; i++) { fr = freq[i]; if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; if (fr != self->lastFilterFreq) { self->lastFilterFreq = fr; self->w0 = TWOPI * fr / self->sr; self->c = MYCOS(self->w0); self->alpha = MYSIN(self->w0) * 0.5; self->b0 = self->b2 = (1 + self->c) * 0.5; self->b1 = -(1 + self->c); self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } det_ind = (int)(_clip(detune[i]) * 126); val = 0.0; for (j=0; j<7; j++) { val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind]; self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr; if (self->pointerPos[j] < -1.0) self->pointerPos[j] += 2.0; else if (self->pointerPos[j] >= 1.0) self->pointerPos[j] -= 2.0; } self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = self->data[i]; self->x2 = self->x1; self->x1 = val; self->data[i] *= 0.2; } } static void SuperSaw_readframes_iia(SuperSaw *self) { MYFLT fr, det, twoOnSr, val; int i, j, det_ind, bal_ind; MYFLT inc[7]; fr = PyFloat_AS_DOUBLE(self->freq); det = _clip(PyFloat_AS_DOUBLE(self->detune)); MYFLT *balance = Stream_getData((Stream *)self->bal_stream); twoOnSr = 2.0 / self->sr; if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; det_ind = (int)(det * 126); if (fr != self->lastFilterFreq) { self->lastFilterFreq = fr; self->w0 = TWOPI * fr / self->sr; self->c = MYCOS(self->w0); self->alpha = MYSIN(self->w0) * 0.5; self->b0 = self->b2 = (1 + self->c) * 0.5; self->b1 = -(1 + self->c); self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } for (j=0; j<7; j++) { inc[j] = fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr; } for (i=0; ibufsize; i++) { bal_ind = (int)(_clip(balance[i]) * 126); val = 0.0; for (j=0; j<7; j++) { val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind]; self->pointerPos[j] += inc[j]; if (self->pointerPos[j] < -1.0) self->pointerPos[j] += 2.0; else if (self->pointerPos[j] >= 1.0) self->pointerPos[j] -= 2.0; } self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = self->data[i]; self->x2 = self->x1; self->x1 = val; self->data[i] *= 0.2; } } static void SuperSaw_readframes_aia(SuperSaw *self) { MYFLT fr, det, twoOnSr, val; int i, j, det_ind, bal_ind; MYFLT *freq = Stream_getData((Stream *)self->freq_stream); det = _clip(PyFloat_AS_DOUBLE(self->detune)); MYFLT *balance = Stream_getData((Stream *)self->bal_stream); twoOnSr = 2.0 / self->sr; det_ind = (int)(det * 126); for (i=0; ibufsize; i++) { fr = freq[i]; if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; if (fr != self->lastFilterFreq) { self->lastFilterFreq = fr; self->w0 = TWOPI * fr / self->sr; self->c = MYCOS(self->w0); self->alpha = MYSIN(self->w0) * 0.5; self->b0 = self->b2 = (1 + self->c) * 0.5; self->b1 = -(1 + self->c); self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } bal_ind = (int)(_clip(balance[i]) * 126); val = 0.0; for (j=0; j<7; j++) { val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind]; self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr; if (self->pointerPos[j] < -1.0) self->pointerPos[j] += 2.0; else if (self->pointerPos[j] >= 1.0) self->pointerPos[j] -= 2.0; } self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = self->data[i]; self->x2 = self->x1; self->x1 = val; self->data[i] *= 0.2; } } static void SuperSaw_readframes_iaa(SuperSaw *self) { MYFLT fr, twoOnSr, val; int i, j, det_ind, bal_ind; fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *detune = Stream_getData((Stream *)self->detune_stream); MYFLT *balance = Stream_getData((Stream *)self->bal_stream); twoOnSr = 2.0 / self->sr; if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; if (fr != self->lastFilterFreq) { self->lastFilterFreq = fr; self->w0 = TWOPI * fr / self->sr; self->c = MYCOS(self->w0); self->alpha = MYSIN(self->w0) * 0.5; self->b0 = self->b2 = (1 + self->c) * 0.5; self->b1 = -(1 + self->c); self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } for (i=0; ibufsize; i++) { det_ind = (int)(_clip(detune[i]) * 126); bal_ind = (int)(_clip(balance[i]) * 126); val = 0.0; for (j=0; j<7; j++) { val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind]; self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr; if (self->pointerPos[j] < -1.0) self->pointerPos[j] += 2.0; else if (self->pointerPos[j] >= 1.0) self->pointerPos[j] -= 2.0; } self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = self->data[i]; self->x2 = self->x1; self->x1 = val; self->data[i] *= 0.2; } } static void SuperSaw_readframes_aaa(SuperSaw *self) { MYFLT fr, twoOnSr, val; int i, j, det_ind, bal_ind; MYFLT *freq = Stream_getData((Stream *)self->freq_stream); MYFLT *detune = Stream_getData((Stream *)self->detune_stream); MYFLT *balance = Stream_getData((Stream *)self->bal_stream); twoOnSr = 2.0 / self->sr; for (i=0; ibufsize; i++) { fr = freq[i]; if (fr <= 1.0) fr = 1.0; else if (fr >= self->nyquist) fr = self->nyquist; if (fr != self->lastFilterFreq) { self->lastFilterFreq = fr; self->w0 = TWOPI * fr / self->sr; self->c = MYCOS(self->w0); self->alpha = MYSIN(self->w0) * 0.5; self->b0 = self->b2 = (1 + self->c) * 0.5; self->b1 = -(1 + self->c); self->a0 = 1 + self->alpha; self->a1 = -2 * self->c; self->a2 = 1 - self->alpha; } det_ind = (int)(_clip(detune[i]) * 126); bal_ind = (int)(_clip(balance[i]) * 126); val = 0.0; for (j=0; j<7; j++) { val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind]; self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr; if (self->pointerPos[j] < -1.0) self->pointerPos[j] += 2.0; else if (self->pointerPos[j] >= 1.0) self->pointerPos[j] -= 2.0; } self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0; self->y2 = self->y1; self->y1 = self->data[i]; self->x2 = self->x1; self->x1 = val; self->data[i] *= 0.2; } } static void SuperSaw_postprocessing_ii(SuperSaw *self) { POST_PROCESSING_II }; static void SuperSaw_postprocessing_ai(SuperSaw *self) { POST_PROCESSING_AI }; static void SuperSaw_postprocessing_ia(SuperSaw *self) { POST_PROCESSING_IA }; static void SuperSaw_postprocessing_aa(SuperSaw *self) { POST_PROCESSING_AA }; static void SuperSaw_postprocessing_ireva(SuperSaw *self) { POST_PROCESSING_IREVA }; static void SuperSaw_postprocessing_areva(SuperSaw *self) { POST_PROCESSING_AREVA }; static void SuperSaw_postprocessing_revai(SuperSaw *self) { POST_PROCESSING_REVAI }; static void SuperSaw_postprocessing_revaa(SuperSaw *self) { POST_PROCESSING_REVAA }; static void SuperSaw_postprocessing_revareva(SuperSaw *self) { POST_PROCESSING_REVAREVA }; static void SuperSaw_setProcMode(SuperSaw *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = SuperSaw_readframes_iii; break; case 1: self->proc_func_ptr = SuperSaw_readframes_aii; break; case 10: self->proc_func_ptr = SuperSaw_readframes_iai; break; case 11: self->proc_func_ptr = SuperSaw_readframes_aai; break; case 100: self->proc_func_ptr = SuperSaw_readframes_iia; break; case 101: self->proc_func_ptr = SuperSaw_readframes_aia; break; case 110: self->proc_func_ptr = SuperSaw_readframes_iaa; break; case 111: self->proc_func_ptr = SuperSaw_readframes_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = SuperSaw_postprocessing_ii; break; case 1: self->muladd_func_ptr = SuperSaw_postprocessing_ai; break; case 2: self->muladd_func_ptr = SuperSaw_postprocessing_revai; break; case 10: self->muladd_func_ptr = SuperSaw_postprocessing_ia; break; case 11: self->muladd_func_ptr = SuperSaw_postprocessing_aa; break; case 12: self->muladd_func_ptr = SuperSaw_postprocessing_revaa; break; case 20: self->muladd_func_ptr = SuperSaw_postprocessing_ireva; break; case 21: self->muladd_func_ptr = SuperSaw_postprocessing_areva; break; case 22: self->muladd_func_ptr = SuperSaw_postprocessing_revareva; break; } } static void SuperSaw_compute_next_data_frame(SuperSaw *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int SuperSaw_traverse(SuperSaw *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->detune); Py_VISIT(self->detune_stream); Py_VISIT(self->bal); Py_VISIT(self->bal_stream); return 0; } static int SuperSaw_clear(SuperSaw *self) { pyo_CLEAR Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->detune); Py_CLEAR(self->detune_stream); Py_CLEAR(self->bal); Py_CLEAR(self->bal_stream); return 0; } static void SuperSaw_dealloc(SuperSaw* self) { pyo_DEALLOC SuperSaw_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SuperSaw_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *freqtmp=NULL, *detunetmp=NULL, *baltmp=NULL, *multmp=NULL, *addtmp=NULL; SuperSaw *self; self = (SuperSaw *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(100); self->detune = PyFloat_FromDouble(0.5); self->bal = PyFloat_FromDouble(0.7); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->pointerPos[0] = -0.75; self->pointerPos[1] = -0.5; self->pointerPos[2] = -0.25; self->pointerPos[3] = 0.0; self->pointerPos[4] = 0.25; self->pointerPos[5] = 0.5; self->pointerPos[6] = 0.75; self->lastFilterFreq = -1.0; self->x1 = self->x2 = self->y1 = self->y2 = 0.0; INIT_OBJECT_COMMON self->nyquist = (MYFLT)self->sr * 0.49; Stream_setFunctionPtr(self->stream, SuperSaw_compute_next_data_frame); self->mode_func_ptr = SuperSaw_setProcMode; static char *kwlist[] = {"freq", "detune", "bal", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &freqtmp, &detunetmp, &baltmp, &multmp, &addtmp)) Py_RETURN_NONE; if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (detunetmp) { PyObject_CallMethod((PyObject *)self, "setDetune", "O", detunetmp); } if (baltmp) { PyObject_CallMethod((PyObject *)self, "setBal", "O", baltmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * SuperSaw_getServer(SuperSaw* self) { GET_SERVER }; static PyObject * SuperSaw_getStream(SuperSaw* self) { GET_STREAM }; static PyObject * SuperSaw_setMul(SuperSaw *self, PyObject *arg) { SET_MUL }; static PyObject * SuperSaw_setAdd(SuperSaw *self, PyObject *arg) { SET_ADD }; static PyObject * SuperSaw_setSub(SuperSaw *self, PyObject *arg) { SET_SUB }; static PyObject * SuperSaw_setDiv(SuperSaw *self, PyObject *arg) { SET_DIV }; static PyObject * SuperSaw_play(SuperSaw *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SuperSaw_out(SuperSaw *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * SuperSaw_stop(SuperSaw *self) { STOP }; static PyObject * SuperSaw_multiply(SuperSaw *self, PyObject *arg) { MULTIPLY }; static PyObject * SuperSaw_inplace_multiply(SuperSaw *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * SuperSaw_add(SuperSaw *self, PyObject *arg) { ADD }; static PyObject * SuperSaw_inplace_add(SuperSaw *self, PyObject *arg) { INPLACE_ADD }; static PyObject * SuperSaw_sub(SuperSaw *self, PyObject *arg) { SUB }; static PyObject * SuperSaw_inplace_sub(SuperSaw *self, PyObject *arg) { INPLACE_SUB }; static PyObject * SuperSaw_div(SuperSaw *self, PyObject *arg) { DIV }; static PyObject * SuperSaw_inplace_div(SuperSaw *self, PyObject *arg) { INPLACE_DIV }; static PyObject * SuperSaw_setFreq(SuperSaw *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SuperSaw_setDetune(SuperSaw *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->detune); if (isNumber == 1) { self->detune = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->detune = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->detune, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->detune_stream); self->detune_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SuperSaw_setBal(SuperSaw *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->bal); if (isNumber == 1) { self->bal = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->bal = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->bal, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->bal_stream); self->bal_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef SuperSaw_members[] = { {"server", T_OBJECT_EX, offsetof(SuperSaw, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SuperSaw, stream), 0, "Stream object."}, {"freq", T_OBJECT_EX, offsetof(SuperSaw, freq), 0, "Frequency in cycle per second."}, {"detune", T_OBJECT_EX, offsetof(SuperSaw, detune), 0, "Detune factor."}, {"bal", T_OBJECT_EX, offsetof(SuperSaw, bal), 0, "Mix factor."}, {"mul", T_OBJECT_EX, offsetof(SuperSaw, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(SuperSaw, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef SuperSaw_methods[] = { {"getServer", (PyCFunction)SuperSaw_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SuperSaw_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SuperSaw_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)SuperSaw_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)SuperSaw_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)SuperSaw_setFreq, METH_O, "Sets oscillator frequency in cycle per second."}, {"setDetune", (PyCFunction)SuperSaw_setDetune, METH_O, "Sets oscillator detune factor."}, {"setBal", (PyCFunction)SuperSaw_setBal, METH_O, "Sets oscillator mix factor."}, {"setMul", (PyCFunction)SuperSaw_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)SuperSaw_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)SuperSaw_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)SuperSaw_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods SuperSaw_as_number = { (binaryfunc)SuperSaw_add, /*nb_add*/ (binaryfunc)SuperSaw_sub, /*nb_subtract*/ (binaryfunc)SuperSaw_multiply, /*nb_multiply*/ (binaryfunc)SuperSaw_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)SuperSaw_inplace_add, /*inplace_add*/ (binaryfunc)SuperSaw_inplace_sub, /*inplace_subtract*/ (binaryfunc)SuperSaw_inplace_multiply, /*inplace_multiply*/ (binaryfunc)SuperSaw_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SuperSawType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SuperSaw_base", /*tp_name*/ sizeof(SuperSaw), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SuperSaw_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &SuperSaw_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SuperSaw objects. detune incrementor from 0 to 1.", /* tp_doc */ (traverseproc)SuperSaw_traverse, /* tp_traverse */ (inquiry)SuperSaw_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SuperSaw_methods, /* tp_methods */ SuperSaw_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SuperSaw_new, /* tp_new */ }; /**************/ /* RCOsc object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *freq; Stream *freq_stream; PyObject *sharp; Stream *sharp_stream; int modebuffer[4]; MYFLT pointerPos; } RCOsc; static void RCOsc_readframes_ii(RCOsc *self) { MYFLT fr, sh, inc, down_phase, up_phase; int i; fr = PyFloat_AS_DOUBLE(self->freq); sh = _clip(PyFloat_AS_DOUBLE(self->sharp)); sh = sh * sh * 99.0 + 1.0; inc = fr * 2 / self->sr; for (i=0; ibufsize; i++) { if (self->pointerPos < 1) { down_phase = 1.0 - self->pointerPos; up_phase = 1.0; } else { down_phase = 0.0; up_phase = 2.0 - self->pointerPos; } self->data[i] = ( (1.0 - MYPOW(down_phase, sh)) + (MYPOW(up_phase, sh)) ) * 2.0 - 3.0; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 2.0; else if (self->pointerPos >= 2) self->pointerPos -= 2.0; } } static void RCOsc_readframes_ai(RCOsc *self) { MYFLT sh, down_phase, up_phase, twoOverSr; int i; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); sh = _clip(PyFloat_AS_DOUBLE(self->sharp)); sh = sh * sh * 99.0 + 1.0; twoOverSr = 2.0 / self->sr; for (i=0; ibufsize; i++) { if (self->pointerPos < 1) { down_phase = 1.0 - self->pointerPos; up_phase = 1.0; } else { down_phase = 0.0; up_phase = 2.0 - self->pointerPos; } self->data[i] = ( (1.0 - MYPOW(down_phase, sh)) + (MYPOW(up_phase, sh)) ) * 2.0 - 3.0; self->pointerPos += fr[i] * twoOverSr; if (self->pointerPos < 0) self->pointerPos += 2.0; else if (self->pointerPos >= 2) self->pointerPos -= 2.0; } } static void RCOsc_readframes_ia(RCOsc *self) { MYFLT fr, sh, inc, down_phase, up_phase; int i; fr = PyFloat_AS_DOUBLE(self->freq); MYFLT *sharp = Stream_getData((Stream *)self->sharp_stream); inc = fr * 2 / self->sr; for (i=0; ibufsize; i++) { sh = _clip(sharp[i]); sh = sh * sh * 99.0 + 1.0; if (self->pointerPos < 1) { down_phase = 1.0 - self->pointerPos; up_phase = 1.0; } else { down_phase = 0.0; up_phase = 2.0 - self->pointerPos; } self->data[i] = ( (1.0 - MYPOW(down_phase, sh)) + (MYPOW(up_phase, sh)) ) * 2.0 - 3.0; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 2.0; else if (self->pointerPos >= 2) self->pointerPos -= 2.0; } } static void RCOsc_readframes_aa(RCOsc *self) { MYFLT sh, down_phase, up_phase, twoOverSr; int i; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT *sharp = Stream_getData((Stream *)self->sharp_stream); twoOverSr = 2.0 / self->sr; for (i=0; ibufsize; i++) { sh = _clip(sharp[i]); sh = sh * sh * 99.0 + 1.0; if (self->pointerPos < 1) { down_phase = 1.0 - self->pointerPos; up_phase = 1.0; } else { down_phase = 0.0; up_phase = 2.0 - self->pointerPos; } self->data[i] = ( (1.0 - MYPOW(down_phase, sh)) + (MYPOW(up_phase, sh)) ) * 2.0 - 3.0; self->pointerPos += fr[i] * twoOverSr; if (self->pointerPos < 0) self->pointerPos += 2.0; else if (self->pointerPos >= 2) self->pointerPos -= 2.0; } } static void RCOsc_postprocessing_ii(RCOsc *self) { POST_PROCESSING_II }; static void RCOsc_postprocessing_ai(RCOsc *self) { POST_PROCESSING_AI }; static void RCOsc_postprocessing_ia(RCOsc *self) { POST_PROCESSING_IA }; static void RCOsc_postprocessing_aa(RCOsc *self) { POST_PROCESSING_AA }; static void RCOsc_postprocessing_ireva(RCOsc *self) { POST_PROCESSING_IREVA }; static void RCOsc_postprocessing_areva(RCOsc *self) { POST_PROCESSING_AREVA }; static void RCOsc_postprocessing_revai(RCOsc *self) { POST_PROCESSING_REVAI }; static void RCOsc_postprocessing_revaa(RCOsc *self) { POST_PROCESSING_REVAA }; static void RCOsc_postprocessing_revareva(RCOsc *self) { POST_PROCESSING_REVAREVA }; static void RCOsc_setProcMode(RCOsc *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = RCOsc_readframes_ii; break; case 1: self->proc_func_ptr = RCOsc_readframes_ai; break; case 10: self->proc_func_ptr = RCOsc_readframes_ia; break; case 11: self->proc_func_ptr = RCOsc_readframes_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = RCOsc_postprocessing_ii; break; case 1: self->muladd_func_ptr = RCOsc_postprocessing_ai; break; case 2: self->muladd_func_ptr = RCOsc_postprocessing_revai; break; case 10: self->muladd_func_ptr = RCOsc_postprocessing_ia; break; case 11: self->muladd_func_ptr = RCOsc_postprocessing_aa; break; case 12: self->muladd_func_ptr = RCOsc_postprocessing_revaa; break; case 20: self->muladd_func_ptr = RCOsc_postprocessing_ireva; break; case 21: self->muladd_func_ptr = RCOsc_postprocessing_areva; break; case 22: self->muladd_func_ptr = RCOsc_postprocessing_revareva; break; } } static void RCOsc_compute_next_data_frame(RCOsc *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int RCOsc_traverse(RCOsc *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->sharp); Py_VISIT(self->sharp_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); return 0; } static int RCOsc_clear(RCOsc *self) { pyo_CLEAR Py_CLEAR(self->sharp); Py_CLEAR(self->sharp_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); return 0; } static void RCOsc_dealloc(RCOsc* self) { pyo_DEALLOC RCOsc_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * RCOsc_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *freqtmp=NULL, *sharptmp=NULL, *multmp=NULL, *addtmp=NULL; RCOsc *self; self = (RCOsc *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(100); self->sharp = PyFloat_FromDouble(0.25); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->pointerPos = 0.; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, RCOsc_compute_next_data_frame); self->mode_func_ptr = RCOsc_setProcMode; static char *kwlist[] = {"freq", "sharp", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &sharptmp, &multmp, &addtmp)) Py_RETURN_NONE; if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (sharptmp) { PyObject_CallMethod((PyObject *)self, "setSharp", "O", sharptmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * RCOsc_getServer(RCOsc* self) { GET_SERVER }; static PyObject * RCOsc_getStream(RCOsc* self) { GET_STREAM }; static PyObject * RCOsc_setMul(RCOsc *self, PyObject *arg) { SET_MUL }; static PyObject * RCOsc_setAdd(RCOsc *self, PyObject *arg) { SET_ADD }; static PyObject * RCOsc_setSub(RCOsc *self, PyObject *arg) { SET_SUB }; static PyObject * RCOsc_setDiv(RCOsc *self, PyObject *arg) { SET_DIV }; static PyObject * RCOsc_play(RCOsc *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * RCOsc_out(RCOsc *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * RCOsc_stop(RCOsc *self) { STOP }; static PyObject * RCOsc_multiply(RCOsc *self, PyObject *arg) { MULTIPLY }; static PyObject * RCOsc_inplace_multiply(RCOsc *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * RCOsc_add(RCOsc *self, PyObject *arg) { ADD }; static PyObject * RCOsc_inplace_add(RCOsc *self, PyObject *arg) { INPLACE_ADD }; static PyObject * RCOsc_sub(RCOsc *self, PyObject *arg) { SUB }; static PyObject * RCOsc_inplace_sub(RCOsc *self, PyObject *arg) { INPLACE_SUB }; static PyObject * RCOsc_div(RCOsc *self, PyObject *arg) { DIV }; static PyObject * RCOsc_inplace_div(RCOsc *self, PyObject *arg) { INPLACE_DIV }; static PyObject * RCOsc_setFreq(RCOsc *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * RCOsc_setSharp(RCOsc *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->sharp); if (isNumber == 1) { self->sharp = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->sharp = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->sharp, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->sharp_stream); self->sharp_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * RCOsc_reset(RCOsc *self) { self->pointerPos = 0.0; Py_INCREF(Py_None); return Py_None; } static PyMemberDef RCOsc_members[] = { {"server", T_OBJECT_EX, offsetof(RCOsc, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(RCOsc, stream), 0, "Stream object."}, {"freq", T_OBJECT_EX, offsetof(RCOsc, freq), 0, "Frequency in cycle per second."}, {"sharp", T_OBJECT_EX, offsetof(RCOsc, sharp), 0, "RCOscillator sharp."}, {"mul", T_OBJECT_EX, offsetof(RCOsc, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(RCOsc, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef RCOsc_methods[] = { {"getServer", (PyCFunction)RCOsc_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)RCOsc_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)RCOsc_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)RCOsc_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)RCOsc_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)RCOsc_setFreq, METH_O, "Sets oscillator frequency in cycle per second."}, {"setSharp", (PyCFunction)RCOsc_setSharp, METH_O, "Sets oscillator sharp."}, {"reset", (PyCFunction)RCOsc_reset, METH_NOARGS, "Resets pointer position to 0."}, {"setMul", (PyCFunction)RCOsc_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)RCOsc_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)RCOsc_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)RCOsc_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods RCOsc_as_number = { (binaryfunc)RCOsc_add, /*nb_add*/ (binaryfunc)RCOsc_sub, /*nb_subtract*/ (binaryfunc)RCOsc_multiply, /*nb_multiply*/ (binaryfunc)RCOsc_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)RCOsc_inplace_add, /*inplace_add*/ (binaryfunc)RCOsc_inplace_sub, /*inplace_subtract*/ (binaryfunc)RCOsc_inplace_multiply, /*inplace_multiply*/ (binaryfunc)RCOsc_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject RCOscType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.RCOsc_base", /*tp_name*/ sizeof(RCOsc), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)RCOsc_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &RCOsc_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "RCOsc objects. Waveform simulation of of a RC circuit.", /* tp_doc */ (traverseproc)RCOsc_traverse, /* tp_traverse */ (inquiry)RCOsc_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ RCOsc_methods, /* tp_methods */ RCOsc_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ RCOsc_new, /* tp_new */ }; /**************/ /* TableScale object */ /**************/ typedef struct { pyo_audio_HEAD PyObject *table; PyObject *outtable; int modebuffer[2]; } TableScale; static void TableScale_readframes_ii(TableScale *self) { int i, num; MYFLT mul, add; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *outlist = TableStream_getData(self->outtable); int osize = TableStream_getSize(self->outtable); mul = PyFloat_AS_DOUBLE(self->mul); add = PyFloat_AS_DOUBLE(self->add); num = size < osize ? size : osize; for (i=0; itable); int size = TableStream_getSize(self->table); MYFLT *outlist = TableStream_getData(self->outtable); int osize = TableStream_getSize(self->outtable); MYFLT *mul = Stream_getData((Stream *)self->mul_stream); add = PyFloat_AS_DOUBLE(self->add); num = size < osize ? size : osize; for (i=0; itable); int size = TableStream_getSize(self->table); MYFLT *outlist = TableStream_getData(self->outtable); int osize = TableStream_getSize(self->outtable); mul = PyFloat_AS_DOUBLE(self->mul); MYFLT *add = Stream_getData((Stream *)self->add_stream); num = size < osize ? size : osize; for (i=0; itable); int size = TableStream_getSize(self->table); MYFLT *outlist = TableStream_getData(self->outtable); int osize = TableStream_getSize(self->outtable); MYFLT *mul = Stream_getData((Stream *)self->mul_stream); MYFLT *add = Stream_getData((Stream *)self->add_stream); num = size < osize ? size : osize; for (i=0; imodebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->proc_func_ptr = TableScale_readframes_ii; break; case 1: self->proc_func_ptr = TableScale_readframes_ai; break; case 10: self->proc_func_ptr = TableScale_readframes_ia; break; case 11: self->proc_func_ptr = TableScale_readframes_aa; break; } } static void TableScale_compute_next_data_frame(TableScale *self) { (*self->proc_func_ptr)(self); } static int TableScale_traverse(TableScale *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->outtable); return 0; } static int TableScale_clear(TableScale *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->outtable); return 0; } static void TableScale_dealloc(TableScale* self) { pyo_DEALLOC TableScale_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TableScale_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *tabletmp, *outtabletmp, *multmp=NULL, *addtmp=NULL; TableScale *self; self = (TableScale *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TableScale_compute_next_data_frame); self->mode_func_ptr = TableScale_setProcMode; static char *kwlist[] = {"table", "outtable", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &tabletmp, &outtabletmp, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableScale must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if ( PyObject_HasAttrString((PyObject *)outtabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"outtable\" argument of TableScale must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->outtable); self->outtable = PyObject_CallMethod((PyObject *)outtabletmp, "getTableStream", ""); if (addtmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TableScale_getServer(TableScale* self) { GET_SERVER }; static PyObject * TableScale_getStream(TableScale* self) { GET_STREAM }; static PyObject * TableScale_setMul(TableScale *self, PyObject *arg) { SET_MUL }; static PyObject * TableScale_setAdd(TableScale *self, PyObject *arg) { SET_ADD }; static PyObject * TableScale_setSub(TableScale *self, PyObject *arg) { SET_SUB }; static PyObject * TableScale_setDiv(TableScale *self, PyObject *arg) { SET_DIV }; static PyObject * TableScale_play(TableScale *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TableScale_out(TableScale *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TableScale_stop(TableScale *self) { STOP }; static PyObject * TableScale_multiply(TableScale *self, PyObject *arg) { MULTIPLY }; static PyObject * TableScale_inplace_multiply(TableScale *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TableScale_add(TableScale *self, PyObject *arg) { ADD }; static PyObject * TableScale_inplace_add(TableScale *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TableScale_sub(TableScale *self, PyObject *arg) { SUB }; static PyObject * TableScale_inplace_sub(TableScale *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TableScale_div(TableScale *self, PyObject *arg) { DIV }; static PyObject * TableScale_inplace_div(TableScale *self, PyObject *arg) { INPLACE_DIV }; static PyObject * TableScale_getTable(TableScale* self) { Py_INCREF(self->table); return self->table; }; static PyObject * TableScale_setTable(TableScale *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * TableScale_getOuttable(TableScale* self) { Py_INCREF(self->outtable); return self->outtable; }; static PyObject * TableScale_setOuttable(TableScale *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->outtable); self->outtable = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyMemberDef TableScale_members[] = { {"server", T_OBJECT_EX, offsetof(TableScale, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TableScale, stream), 0, "Stream object."}, {"table", T_OBJECT_EX, offsetof(TableScale, table), 0, "Waveform table."}, {"outtable", T_OBJECT_EX, offsetof(TableScale, outtable), 0, "Output table."}, {"mul", T_OBJECT_EX, offsetof(TableScale, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TableScale, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TableScale_methods[] = { {"getTable", (PyCFunction)TableScale_getTable, METH_NOARGS, "Returns waveform table object."}, {"getOuttable", (PyCFunction)TableScale_getOuttable, METH_NOARGS, "Returns output table object."}, {"getServer", (PyCFunction)TableScale_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TableScale_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TableScale_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TableScale_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TableScale_stop, METH_NOARGS, "Stops computing."}, {"setTable", (PyCFunction)TableScale_setTable, METH_O, "Sets oscillator table."}, {"setOuttable", (PyCFunction)TableScale_setOuttable, METH_O, "Sets output table."}, {"setMul", (PyCFunction)TableScale_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TableScale_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TableScale_setSub, METH_O, "Sets oscillator inverse add factor."}, {"setDiv", (PyCFunction)TableScale_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TableScale_as_number = { (binaryfunc)TableScale_add, /*nb_add*/ (binaryfunc)TableScale_sub, /*nb_subtract*/ (binaryfunc)TableScale_multiply, /*nb_multiply*/ (binaryfunc)TableScale_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TableScale_inplace_add, /*inplace_add*/ (binaryfunc)TableScale_inplace_sub, /*inplace_subtract*/ (binaryfunc)TableScale_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TableScale_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TableScaleType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TableScale_base", /*tp_name*/ sizeof(TableScale), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TableScale_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TableScale_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TableScale objects. Scale a PyoTable and save the result in another table.", /* tp_doc */ (traverseproc)TableScale_traverse, /* tp_traverse */ (inquiry)TableScale_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TableScale_methods, /* tp_methods */ TableScale_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TableScale_new, /* tp_new */ };pyo/src/objects/randommodule.c0000644000175000017500000056703212652732202015745 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include #include "structmember.h" #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD PyObject *min; PyObject *max; PyObject *freq; Stream *min_stream; Stream *max_stream; Stream *freq_stream; MYFLT value; MYFLT oldValue; MYFLT diff; MYFLT time; int modebuffer[5]; // need at least 2 slots for mul & add } Randi; static void Randi_generate_iii(Randi *self) { int i; MYFLT inc; MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT ma = PyFloat_AS_DOUBLE(self->max); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); MYFLT range = ma - mi; inc = fr / self->sr; for (i=0; ibufsize; i++) { self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->oldValue = self->value; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; self->diff = self->value - self->oldValue; } self->data[i] = self->oldValue + self->diff * self->time; } } static void Randi_generate_aii(Randi *self) { int i; MYFLT inc, range; MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT ma = PyFloat_AS_DOUBLE(self->max); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { range = ma - mi[i]; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->oldValue = self->value; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i]; self->diff = self->value - self->oldValue; } self->data[i] = self->oldValue + self->diff * self->time; } } static void Randi_generate_iai(Randi *self) { int i; MYFLT inc, range; MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT *ma = Stream_getData((Stream *)self->max_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { range = ma[i] - mi; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->oldValue = self->value; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; self->diff = self->value - self->oldValue; } self->data[i] = self->oldValue + self->diff * self->time; } } static void Randi_generate_aai(Randi *self) { int i; MYFLT inc, range; MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT *ma = Stream_getData((Stream *)self->max_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { range = ma[i] - mi[i]; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->oldValue = self->value; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i]; self->diff = self->value - self->oldValue; } self->data[i] = self->oldValue + self->diff * self->time; } } static void Randi_generate_iia(Randi *self) { int i; MYFLT inc; MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT ma = PyFloat_AS_DOUBLE(self->max); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT range = ma - mi; for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->oldValue = self->value; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; self->diff = self->value - self->oldValue; } self->data[i] = self->oldValue + self->diff * self->time; } } static void Randi_generate_aia(Randi *self) { int i; MYFLT inc, range; MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT ma = PyFloat_AS_DOUBLE(self->max); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; range = ma - mi[i]; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->oldValue = self->value; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i]; self->diff = self->value - self->oldValue; } self->data[i] = self->oldValue + self->diff * self->time; } } static void Randi_generate_iaa(Randi *self) { int i; MYFLT inc, range; MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT *ma = Stream_getData((Stream *)self->max_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; range = ma[i] - mi; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->oldValue = self->value; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; self->diff = self->value - self->oldValue; } self->data[i] = self->oldValue + self->diff * self->time; } } static void Randi_generate_aaa(Randi *self) { int i; MYFLT inc, range; MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT *ma = Stream_getData((Stream *)self->max_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; range = ma[i] - mi[i]; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->oldValue = self->value; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i]; self->diff = self->value - self->oldValue; } self->data[i] = self->oldValue + self->diff * self->time; } } static void Randi_postprocessing_ii(Randi *self) { POST_PROCESSING_II }; static void Randi_postprocessing_ai(Randi *self) { POST_PROCESSING_AI }; static void Randi_postprocessing_ia(Randi *self) { POST_PROCESSING_IA }; static void Randi_postprocessing_aa(Randi *self) { POST_PROCESSING_AA }; static void Randi_postprocessing_ireva(Randi *self) { POST_PROCESSING_IREVA }; static void Randi_postprocessing_areva(Randi *self) { POST_PROCESSING_AREVA }; static void Randi_postprocessing_revai(Randi *self) { POST_PROCESSING_REVAI }; static void Randi_postprocessing_revaa(Randi *self) { POST_PROCESSING_REVAA }; static void Randi_postprocessing_revareva(Randi *self) { POST_PROCESSING_REVAREVA }; static void Randi_setProcMode(Randi *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Randi_generate_iii; break; case 1: self->proc_func_ptr = Randi_generate_aii; break; case 10: self->proc_func_ptr = Randi_generate_iai; break; case 11: self->proc_func_ptr = Randi_generate_aai; break; case 100: self->proc_func_ptr = Randi_generate_iia; break; case 101: self->proc_func_ptr = Randi_generate_aia; break; case 110: self->proc_func_ptr = Randi_generate_iaa; break; case 111: self->proc_func_ptr = Randi_generate_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Randi_postprocessing_ii; break; case 1: self->muladd_func_ptr = Randi_postprocessing_ai; break; case 2: self->muladd_func_ptr = Randi_postprocessing_revai; break; case 10: self->muladd_func_ptr = Randi_postprocessing_ia; break; case 11: self->muladd_func_ptr = Randi_postprocessing_aa; break; case 12: self->muladd_func_ptr = Randi_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Randi_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Randi_postprocessing_areva; break; case 22: self->muladd_func_ptr = Randi_postprocessing_revareva; break; } } static void Randi_compute_next_data_frame(Randi *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Randi_traverse(Randi *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->min); Py_VISIT(self->min_stream); Py_VISIT(self->max); Py_VISIT(self->max_stream); return 0; } static int Randi_clear(Randi *self) { pyo_CLEAR Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->min); Py_CLEAR(self->min_stream); Py_CLEAR(self->max); Py_CLEAR(self->max_stream); return 0; } static void Randi_dealloc(Randi* self) { pyo_DEALLOC Randi_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Randi_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT mi, ma; PyObject *mintmp=NULL, *maxtmp=NULL, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL; Randi *self; self = (Randi *)type->tp_alloc(type, 0); self->min = PyFloat_FromDouble(0.); self->max = PyFloat_FromDouble(1.); self->freq = PyFloat_FromDouble(1.); self->value = self->oldValue = self->diff = 0.0; self->time = 1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Randi_compute_next_data_frame); self->mode_func_ptr = Randi_setProcMode; static char *kwlist[] = {"min", "max", "freq", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &mintmp, &maxtmp, &freqtmp, &multmp, &addtmp)) Py_RETURN_NONE; if (mintmp) { PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp); } if (maxtmp) { PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp); } if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Server_generateSeed((Server *)self->server, RANDI_ID); if (self->modebuffer[2] == 0) mi = PyFloat_AS_DOUBLE(self->min); else mi = Stream_getData((Stream *)self->min_stream)[0]; if (self->modebuffer[3] == 0) ma = PyFloat_AS_DOUBLE(self->max); else ma = Stream_getData((Stream *)self->max_stream)[0]; self->value = self->oldValue = (mi + ma) * 0.5; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Randi_getServer(Randi* self) { GET_SERVER }; static PyObject * Randi_getStream(Randi* self) { GET_STREAM }; static PyObject * Randi_setMul(Randi *self, PyObject *arg) { SET_MUL }; static PyObject * Randi_setAdd(Randi *self, PyObject *arg) { SET_ADD }; static PyObject * Randi_setSub(Randi *self, PyObject *arg) { SET_SUB }; static PyObject * Randi_setDiv(Randi *self, PyObject *arg) { SET_DIV }; static PyObject * Randi_play(Randi *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Randi_out(Randi *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Randi_stop(Randi *self) { STOP }; static PyObject * Randi_multiply(Randi *self, PyObject *arg) { MULTIPLY }; static PyObject * Randi_inplace_multiply(Randi *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Randi_add(Randi *self, PyObject *arg) { ADD }; static PyObject * Randi_inplace_add(Randi *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Randi_sub(Randi *self, PyObject *arg) { SUB }; static PyObject * Randi_inplace_sub(Randi *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Randi_div(Randi *self, PyObject *arg) { DIV }; static PyObject * Randi_inplace_div(Randi *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Randi_setMin(Randi *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->min); if (isNumber == 1) { self->min = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->min = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->min, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->min_stream); self->min_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Randi_setMax(Randi *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->max); if (isNumber == 1) { self->max = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->max = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->max_stream); self->max_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Randi_setFreq(Randi *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Randi_members[] = { {"server", T_OBJECT_EX, offsetof(Randi, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Randi, stream), 0, "Stream object."}, {"min", T_OBJECT_EX, offsetof(Randi, min), 0, "Minimum possible value."}, {"max", T_OBJECT_EX, offsetof(Randi, max), 0, "Maximum possible value."}, {"freq", T_OBJECT_EX, offsetof(Randi, freq), 0, "Polling frequency."}, {"mul", T_OBJECT_EX, offsetof(Randi, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Randi, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Randi_methods[] = { {"getServer", (PyCFunction)Randi_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Randi_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Randi_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Randi_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Randi_stop, METH_NOARGS, "Stops computing."}, {"setMin", (PyCFunction)Randi_setMin, METH_O, "Sets minimum possible value."}, {"setMax", (PyCFunction)Randi_setMax, METH_O, "Sets maximum possible value."}, {"setFreq", (PyCFunction)Randi_setFreq, METH_O, "Sets polling frequency."}, {"setMul", (PyCFunction)Randi_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Randi_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Randi_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Randi_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Randi_as_number = { (binaryfunc)Randi_add, /*nb_add*/ (binaryfunc)Randi_sub, /*nb_subtract*/ (binaryfunc)Randi_multiply, /*nb_multiply*/ (binaryfunc)Randi_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Randi_inplace_add, /*inplace_add*/ (binaryfunc)Randi_inplace_sub, /*inplace_subtract*/ (binaryfunc)Randi_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Randi_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject RandiType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Randi_base", /*tp_name*/ sizeof(Randi), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Randi_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Randi_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Randi objects. Periodically generates a new random value with interpolation.", /* tp_doc */ (traverseproc)Randi_traverse, /* tp_traverse */ (inquiry)Randi_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Randi_methods, /* tp_methods */ Randi_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Randi_new, /* tp_new */ }; /****************/ /**** Randh *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *min; PyObject *max; PyObject *freq; Stream *min_stream; Stream *max_stream; Stream *freq_stream; MYFLT value; MYFLT time; int modebuffer[5]; // need at least 2 slots for mul & add } Randh; static void Randh_generate_iii(Randh *self) { int i; MYFLT inc; MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT ma = PyFloat_AS_DOUBLE(self->max); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); MYFLT range = ma - mi; inc = fr / self->sr; for (i=0; ibufsize; i++) { self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; } self->data[i] = self->value; } } static void Randh_generate_aii(Randh *self) { int i; MYFLT inc, range; MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT ma = PyFloat_AS_DOUBLE(self->max); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { range = ma - mi[i]; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i]; } self->data[i] = self->value; } } static void Randh_generate_iai(Randh *self) { int i; MYFLT inc, range; MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT *ma = Stream_getData((Stream *)self->max_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { range = ma[i] - mi; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; } self->data[i] = self->value; } } static void Randh_generate_aai(Randh *self) { int i; MYFLT inc, range; MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT *ma = Stream_getData((Stream *)self->max_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { range = ma[i] - mi[i]; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i]; } self->data[i] = self->value; } } static void Randh_generate_iia(Randh *self) { int i; MYFLT inc; MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT ma = PyFloat_AS_DOUBLE(self->max); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); MYFLT range = ma - mi; for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; } self->data[i] = self->value; } } static void Randh_generate_aia(Randh *self) { int i; MYFLT inc, range; MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT ma = PyFloat_AS_DOUBLE(self->max); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; range = ma - mi[i]; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i]; } self->data[i] = self->value; } } static void Randh_generate_iaa(Randh *self) { int i; MYFLT inc, range; MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT *ma = Stream_getData((Stream *)self->max_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; range = ma[i] - mi; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; } self->data[i] = self->value; } } static void Randh_generate_aaa(Randh *self) { int i; MYFLT inc, range; MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT *ma = Stream_getData((Stream *)self->max_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; range = ma[i] - mi[i]; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i]; } self->data[i] = self->value; } } static void Randh_postprocessing_ii(Randh *self) { POST_PROCESSING_II }; static void Randh_postprocessing_ai(Randh *self) { POST_PROCESSING_AI }; static void Randh_postprocessing_ia(Randh *self) { POST_PROCESSING_IA }; static void Randh_postprocessing_aa(Randh *self) { POST_PROCESSING_AA }; static void Randh_postprocessing_ireva(Randh *self) { POST_PROCESSING_IREVA }; static void Randh_postprocessing_areva(Randh *self) { POST_PROCESSING_AREVA }; static void Randh_postprocessing_revai(Randh *self) { POST_PROCESSING_REVAI }; static void Randh_postprocessing_revaa(Randh *self) { POST_PROCESSING_REVAA }; static void Randh_postprocessing_revareva(Randh *self) { POST_PROCESSING_REVAREVA }; static void Randh_setProcMode(Randh *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Randh_generate_iii; break; case 1: self->proc_func_ptr = Randh_generate_aii; break; case 10: self->proc_func_ptr = Randh_generate_iai; break; case 11: self->proc_func_ptr = Randh_generate_aai; break; case 100: self->proc_func_ptr = Randh_generate_iia; break; case 101: self->proc_func_ptr = Randh_generate_aia; break; case 110: self->proc_func_ptr = Randh_generate_iaa; break; case 111: self->proc_func_ptr = Randh_generate_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Randh_postprocessing_ii; break; case 1: self->muladd_func_ptr = Randh_postprocessing_ai; break; case 2: self->muladd_func_ptr = Randh_postprocessing_revai; break; case 10: self->muladd_func_ptr = Randh_postprocessing_ia; break; case 11: self->muladd_func_ptr = Randh_postprocessing_aa; break; case 12: self->muladd_func_ptr = Randh_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Randh_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Randh_postprocessing_areva; break; case 22: self->muladd_func_ptr = Randh_postprocessing_revareva; break; } } static void Randh_compute_next_data_frame(Randh *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Randh_traverse(Randh *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->min); Py_VISIT(self->min_stream); Py_VISIT(self->max); Py_VISIT(self->max_stream); return 0; } static int Randh_clear(Randh *self) { pyo_CLEAR Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->min); Py_CLEAR(self->min_stream); Py_CLEAR(self->max); Py_CLEAR(self->max_stream); return 0; } static void Randh_dealloc(Randh* self) { pyo_DEALLOC Randh_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Randh_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT mi, ma; PyObject *mintmp=NULL, *maxtmp=NULL, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL; Randh *self; self = (Randh *)type->tp_alloc(type, 0); self->min = PyFloat_FromDouble(0.); self->max = PyFloat_FromDouble(1.); self->freq = PyFloat_FromDouble(1.); self->value = 0.0; self->time = 1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Randh_compute_next_data_frame); self->mode_func_ptr = Randh_setProcMode; static char *kwlist[] = {"min", "max", "freq", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &mintmp, &maxtmp, &freqtmp, &multmp, &addtmp)) Py_RETURN_NONE; if (mintmp) { PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp); } if (maxtmp) { PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp); } if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Server_generateSeed((Server *)self->server, RANDH_ID); if (self->modebuffer[2] == 0) mi = PyFloat_AS_DOUBLE(self->min); else mi = Stream_getData((Stream *)self->min_stream)[0]; if (self->modebuffer[3] == 0) ma = PyFloat_AS_DOUBLE(self->max); else ma = Stream_getData((Stream *)self->max_stream)[0]; self->value = (mi + ma) * 0.5; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Randh_getServer(Randh* self) { GET_SERVER }; static PyObject * Randh_getStream(Randh* self) { GET_STREAM }; static PyObject * Randh_setMul(Randh *self, PyObject *arg) { SET_MUL }; static PyObject * Randh_setAdd(Randh *self, PyObject *arg) { SET_ADD }; static PyObject * Randh_setSub(Randh *self, PyObject *arg) { SET_SUB }; static PyObject * Randh_setDiv(Randh *self, PyObject *arg) { SET_DIV }; static PyObject * Randh_play(Randh *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Randh_out(Randh *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Randh_stop(Randh *self) { STOP }; static PyObject * Randh_multiply(Randh *self, PyObject *arg) { MULTIPLY }; static PyObject * Randh_inplace_multiply(Randh *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Randh_add(Randh *self, PyObject *arg) { ADD }; static PyObject * Randh_inplace_add(Randh *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Randh_sub(Randh *self, PyObject *arg) { SUB }; static PyObject * Randh_inplace_sub(Randh *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Randh_div(Randh *self, PyObject *arg) { DIV }; static PyObject * Randh_inplace_div(Randh *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Randh_setMin(Randh *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->min); if (isNumber == 1) { self->min = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->min = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->min, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->min_stream); self->min_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Randh_setMax(Randh *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->max); if (isNumber == 1) { self->max = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->max = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->max_stream); self->max_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Randh_setFreq(Randh *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Randh_members[] = { {"server", T_OBJECT_EX, offsetof(Randh, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Randh, stream), 0, "Stream object."}, {"min", T_OBJECT_EX, offsetof(Randh, min), 0, "Minimum possible value."}, {"max", T_OBJECT_EX, offsetof(Randh, max), 0, "Maximum possible value."}, {"freq", T_OBJECT_EX, offsetof(Randh, freq), 0, "Polling frequency."}, {"mul", T_OBJECT_EX, offsetof(Randh, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Randh, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Randh_methods[] = { {"getServer", (PyCFunction)Randh_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Randh_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Randh_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Randh_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Randh_stop, METH_NOARGS, "Stops computing."}, {"setMin", (PyCFunction)Randh_setMin, METH_O, "Sets minimum possible value."}, {"setMax", (PyCFunction)Randh_setMax, METH_O, "Sets maximum possible value."}, {"setFreq", (PyCFunction)Randh_setFreq, METH_O, "Sets polling frequency."}, {"setMul", (PyCFunction)Randh_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Randh_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Randh_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Randh_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Randh_as_number = { (binaryfunc)Randh_add, /*nb_add*/ (binaryfunc)Randh_sub, /*nb_subtract*/ (binaryfunc)Randh_multiply, /*nb_multiply*/ (binaryfunc)Randh_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Randh_inplace_add, /*inplace_add*/ (binaryfunc)Randh_inplace_sub, /*inplace_subtract*/ (binaryfunc)Randh_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Randh_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject RandhType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Randh_base", /*tp_name*/ sizeof(Randh), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Randh_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Randh_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Randh objects. Periodically generates a new random value.", /* tp_doc */ (traverseproc)Randh_traverse, /* tp_traverse */ (inquiry)Randh_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Randh_methods, /* tp_methods */ Randh_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Randh_new, /* tp_new */ }; /****************/ /**** Choice *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *freq; Stream *freq_stream; int chSize; MYFLT *choice; MYFLT value; MYFLT time; int modebuffer[3]; // need at least 2 slots for mul & add } Choice; static void Choice_generate_i(Choice *self) { int i; MYFLT inc; MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = self->choice[(int)((rand()/((MYFLT)(RAND_MAX))) * self->chSize)]; } self->data[i] = self->value; } } static void Choice_generate_a(Choice *self) { int i; MYFLT inc; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = self->choice[(int)((rand()/((MYFLT)(RAND_MAX))) * self->chSize)]; } self->data[i] = self->value; } } static void Choice_postprocessing_ii(Choice *self) { POST_PROCESSING_II }; static void Choice_postprocessing_ai(Choice *self) { POST_PROCESSING_AI }; static void Choice_postprocessing_ia(Choice *self) { POST_PROCESSING_IA }; static void Choice_postprocessing_aa(Choice *self) { POST_PROCESSING_AA }; static void Choice_postprocessing_ireva(Choice *self) { POST_PROCESSING_IREVA }; static void Choice_postprocessing_areva(Choice *self) { POST_PROCESSING_AREVA }; static void Choice_postprocessing_revai(Choice *self) { POST_PROCESSING_REVAI }; static void Choice_postprocessing_revaa(Choice *self) { POST_PROCESSING_REVAA }; static void Choice_postprocessing_revareva(Choice *self) { POST_PROCESSING_REVAREVA }; static void Choice_setProcMode(Choice *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Choice_generate_i; break; case 1: self->proc_func_ptr = Choice_generate_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Choice_postprocessing_ii; break; case 1: self->muladd_func_ptr = Choice_postprocessing_ai; break; case 2: self->muladd_func_ptr = Choice_postprocessing_revai; break; case 10: self->muladd_func_ptr = Choice_postprocessing_ia; break; case 11: self->muladd_func_ptr = Choice_postprocessing_aa; break; case 12: self->muladd_func_ptr = Choice_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Choice_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Choice_postprocessing_areva; break; case 22: self->muladd_func_ptr = Choice_postprocessing_revareva; break; } } static void Choice_compute_next_data_frame(Choice *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Choice_traverse(Choice *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->freq); Py_VISIT(self->freq_stream); return 0; } static int Choice_clear(Choice *self) { pyo_CLEAR Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); return 0; } static void Choice_dealloc(Choice* self) { pyo_DEALLOC free(self->choice); Choice_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Choice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *choicetmp=NULL, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL; Choice *self; self = (Choice *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1.); self->value = 0.0; self->time = 1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Choice_compute_next_data_frame); self->mode_func_ptr = Choice_setProcMode; static char *kwlist[] = {"choice", "freq", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &choicetmp, &freqtmp, &multmp, &addtmp)) Py_RETURN_NONE; if (choicetmp) { PyObject_CallMethod((PyObject *)self, "setChoice", "O", choicetmp); } if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Server_generateSeed((Server *)self->server, CHOICE_ID); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Choice_getServer(Choice* self) { GET_SERVER }; static PyObject * Choice_getStream(Choice* self) { GET_STREAM }; static PyObject * Choice_setMul(Choice *self, PyObject *arg) { SET_MUL }; static PyObject * Choice_setAdd(Choice *self, PyObject *arg) { SET_ADD }; static PyObject * Choice_setSub(Choice *self, PyObject *arg) { SET_SUB }; static PyObject * Choice_setDiv(Choice *self, PyObject *arg) { SET_DIV }; static PyObject * Choice_play(Choice *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Choice_out(Choice *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Choice_stop(Choice *self) { STOP }; static PyObject * Choice_multiply(Choice *self, PyObject *arg) { MULTIPLY }; static PyObject * Choice_inplace_multiply(Choice *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Choice_add(Choice *self, PyObject *arg) { ADD }; static PyObject * Choice_inplace_add(Choice *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Choice_sub(Choice *self, PyObject *arg) { SUB }; static PyObject * Choice_inplace_sub(Choice *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Choice_div(Choice *self, PyObject *arg) { DIV }; static PyObject * Choice_inplace_div(Choice *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Choice_setChoice(Choice *self, PyObject *arg) { int i; PyObject *tmp; if (! PyList_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The choice attribute must be a list."); Py_INCREF(Py_None); return Py_None; } tmp = arg; self->chSize = PyList_Size(tmp); self->choice = (MYFLT *)realloc(self->choice, self->chSize * sizeof(MYFLT)); for (i=0; ichSize; i++) { self->choice[i] = PyFloat_AsDouble(PyList_GET_ITEM(tmp, i)); } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Choice_setFreq(Choice *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Choice_members[] = { {"server", T_OBJECT_EX, offsetof(Choice, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Choice, stream), 0, "Stream object."}, {"freq", T_OBJECT_EX, offsetof(Choice, freq), 0, "Polling frequency."}, {"mul", T_OBJECT_EX, offsetof(Choice, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Choice, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Choice_methods[] = { {"getServer", (PyCFunction)Choice_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Choice_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Choice_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Choice_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Choice_stop, METH_NOARGS, "Stops computing."}, {"setChoice", (PyCFunction)Choice_setChoice, METH_O, "Sets list of possible floats."}, {"setFreq", (PyCFunction)Choice_setFreq, METH_O, "Sets polling frequency."}, {"setMul", (PyCFunction)Choice_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Choice_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Choice_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Choice_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Choice_as_number = { (binaryfunc)Choice_add, /*nb_add*/ (binaryfunc)Choice_sub, /*nb_subtract*/ (binaryfunc)Choice_multiply, /*nb_multiply*/ (binaryfunc)Choice_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Choice_inplace_add, /*inplace_add*/ (binaryfunc)Choice_inplace_sub, /*inplace_subtract*/ (binaryfunc)Choice_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Choice_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ChoiceType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Choice_base", /*tp_name*/ sizeof(Choice), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Choice_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Choice_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Choice objects. Periodically generates a new random value from a list.", /* tp_doc */ (traverseproc)Choice_traverse, /* tp_traverse */ (inquiry)Choice_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Choice_methods, /* tp_methods */ Choice_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Choice_new, /* tp_new */ }; /****************/ /**** RandInt ***/ /****************/ typedef struct { pyo_audio_HEAD PyObject *max; PyObject *freq; Stream *max_stream; Stream *freq_stream; MYFLT value; MYFLT time; int modebuffer[4]; // need at least 2 slots for mul & add } RandInt; static void RandInt_generate_ii(RandInt *self) { int i; MYFLT inc; MYFLT ma = PyFloat_AS_DOUBLE(self->max); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma)); } self->data[i] = self->value; } } static void RandInt_generate_ai(RandInt *self) { int i; MYFLT inc; MYFLT *ma = Stream_getData((Stream *)self->max_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma[i])); } self->data[i] = self->value; } } static void RandInt_generate_ia(RandInt *self) { int i; MYFLT inc; MYFLT ma = PyFloat_AS_DOUBLE(self->max); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma)); } self->data[i] = self->value; } } static void RandInt_generate_aa(RandInt *self) { int i; MYFLT inc; MYFLT *ma = Stream_getData((Stream *)self->max_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma[i])); } self->data[i] = self->value; } } static void RandInt_postprocessing_ii(RandInt *self) { POST_PROCESSING_II }; static void RandInt_postprocessing_ai(RandInt *self) { POST_PROCESSING_AI }; static void RandInt_postprocessing_ia(RandInt *self) { POST_PROCESSING_IA }; static void RandInt_postprocessing_aa(RandInt *self) { POST_PROCESSING_AA }; static void RandInt_postprocessing_ireva(RandInt *self) { POST_PROCESSING_IREVA }; static void RandInt_postprocessing_areva(RandInt *self) { POST_PROCESSING_AREVA }; static void RandInt_postprocessing_revai(RandInt *self) { POST_PROCESSING_REVAI }; static void RandInt_postprocessing_revaa(RandInt *self) { POST_PROCESSING_REVAA }; static void RandInt_postprocessing_revareva(RandInt *self) { POST_PROCESSING_REVAREVA }; static void RandInt_setProcMode(RandInt *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = RandInt_generate_ii; break; case 1: self->proc_func_ptr = RandInt_generate_ai; break; case 10: self->proc_func_ptr = RandInt_generate_ia; break; case 11: self->proc_func_ptr = RandInt_generate_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = RandInt_postprocessing_ii; break; case 1: self->muladd_func_ptr = RandInt_postprocessing_ai; break; case 2: self->muladd_func_ptr = RandInt_postprocessing_revai; break; case 10: self->muladd_func_ptr = RandInt_postprocessing_ia; break; case 11: self->muladd_func_ptr = RandInt_postprocessing_aa; break; case 12: self->muladd_func_ptr = RandInt_postprocessing_revaa; break; case 20: self->muladd_func_ptr = RandInt_postprocessing_ireva; break; case 21: self->muladd_func_ptr = RandInt_postprocessing_areva; break; case 22: self->muladd_func_ptr = RandInt_postprocessing_revareva; break; } } static void RandInt_compute_next_data_frame(RandInt *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int RandInt_traverse(RandInt *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->max); Py_VISIT(self->max_stream); return 0; } static int RandInt_clear(RandInt *self) { pyo_CLEAR Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->max); Py_CLEAR(self->max_stream); return 0; } static void RandInt_dealloc(RandInt* self) { pyo_DEALLOC RandInt_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * RandInt_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maxtmp=NULL, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL; RandInt *self; self = (RandInt *)type->tp_alloc(type, 0); self->max = PyFloat_FromDouble(100.); self->freq = PyFloat_FromDouble(1.); self->value = 0.0; self->time = 1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, RandInt_compute_next_data_frame); self->mode_func_ptr = RandInt_setProcMode; static char *kwlist[] = {"max", "freq", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &maxtmp, &freqtmp, &multmp, &addtmp)) Py_RETURN_NONE; if (maxtmp) { PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp); } if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Server_generateSeed((Server *)self->server, RANDINT_ID); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * RandInt_getServer(RandInt* self) { GET_SERVER }; static PyObject * RandInt_getStream(RandInt* self) { GET_STREAM }; static PyObject * RandInt_setMul(RandInt *self, PyObject *arg) { SET_MUL }; static PyObject * RandInt_setAdd(RandInt *self, PyObject *arg) { SET_ADD }; static PyObject * RandInt_setSub(RandInt *self, PyObject *arg) { SET_SUB }; static PyObject * RandInt_setDiv(RandInt *self, PyObject *arg) { SET_DIV }; static PyObject * RandInt_play(RandInt *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * RandInt_out(RandInt *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * RandInt_stop(RandInt *self) { STOP }; static PyObject * RandInt_multiply(RandInt *self, PyObject *arg) { MULTIPLY }; static PyObject * RandInt_inplace_multiply(RandInt *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * RandInt_add(RandInt *self, PyObject *arg) { ADD }; static PyObject * RandInt_inplace_add(RandInt *self, PyObject *arg) { INPLACE_ADD }; static PyObject * RandInt_sub(RandInt *self, PyObject *arg) { SUB }; static PyObject * RandInt_inplace_sub(RandInt *self, PyObject *arg) { INPLACE_SUB }; static PyObject * RandInt_div(RandInt *self, PyObject *arg) { DIV }; static PyObject * RandInt_inplace_div(RandInt *self, PyObject *arg) { INPLACE_DIV }; static PyObject * RandInt_setMax(RandInt *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->max); if (isNumber == 1) { self->max = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->max = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->max_stream); self->max_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * RandInt_setFreq(RandInt *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef RandInt_members[] = { {"server", T_OBJECT_EX, offsetof(RandInt, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(RandInt, stream), 0, "Stream object."}, {"max", T_OBJECT_EX, offsetof(RandInt, max), 0, "Maximum possible value."}, {"freq", T_OBJECT_EX, offsetof(RandInt, freq), 0, "Polling frequency."}, {"mul", T_OBJECT_EX, offsetof(RandInt, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(RandInt, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef RandInt_methods[] = { {"getServer", (PyCFunction)RandInt_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)RandInt_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)RandInt_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)RandInt_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)RandInt_stop, METH_NOARGS, "Stops computing."}, {"setMax", (PyCFunction)RandInt_setMax, METH_O, "Sets maximum possible value."}, {"setFreq", (PyCFunction)RandInt_setFreq, METH_O, "Sets polling frequency."}, {"setMul", (PyCFunction)RandInt_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)RandInt_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)RandInt_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)RandInt_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods RandInt_as_number = { (binaryfunc)RandInt_add, /*nb_add*/ (binaryfunc)RandInt_sub, /*nb_subtract*/ (binaryfunc)RandInt_multiply, /*nb_multiply*/ (binaryfunc)RandInt_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)RandInt_inplace_add, /*inplace_add*/ (binaryfunc)RandInt_inplace_sub, /*inplace_subtract*/ (binaryfunc)RandInt_inplace_multiply, /*inplace_multiply*/ (binaryfunc)RandInt_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject RandIntType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.RandInt_base", /*tp_name*/ sizeof(RandInt), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)RandInt_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &RandInt_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "RandInt objects. Periodically generates a new integer random value.", /* tp_doc */ (traverseproc)RandInt_traverse, /* tp_traverse */ (inquiry)RandInt_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ RandInt_methods, /* tp_methods */ RandInt_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ RandInt_new, /* tp_new */ }; /*****************/ /**** RandDur ****/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *min; PyObject *max; Stream *min_stream; Stream *max_stream; MYFLT value; MYFLT time; MYFLT inc; int modebuffer[4]; // need at least 2 slots for mul & add } RandDur; static void RandDur_generate_ii(RandDur *self) { int i; MYFLT range; MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT ma = PyFloat_AS_DOUBLE(self->max); for (i=0; ibufsize; i++) { self->time += self->inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; if (mi < 0.0) mi = 0.0; range = ma - mi; if (range < 0.0) range = 0.0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; self->inc = (1.0 / self->value) / self->sr; } self->data[i] = self->value; } } static void RandDur_generate_ai(RandDur *self) { int i; MYFLT range, mi; MYFLT *min = Stream_getData((Stream *)self->min_stream); MYFLT ma = PyFloat_AS_DOUBLE(self->max); for (i=0; ibufsize; i++) { self->time += self->inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; mi = min[i]; if (mi < 0.0) mi = 0.0; range = ma - mi; if (range < 0.0) range = 0.0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; self->inc = (1.0 / self->value) / self->sr; } self->data[i] = self->value; } } static void RandDur_generate_ia(RandDur *self) { int i; MYFLT range; MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT *ma = Stream_getData((Stream *)self->max_stream); for (i=0; ibufsize; i++) { self->time += self->inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; if (mi < 0.0) mi = 0.0; range = ma[i] - mi; if (range < 0.0) range = 0.0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; self->inc = (1.0 / self->value) / self->sr; } self->data[i] = self->value; } } static void RandDur_generate_aa(RandDur *self) { int i; MYFLT range, mi; MYFLT *min = Stream_getData((Stream *)self->min_stream); MYFLT *ma = Stream_getData((Stream *)self->max_stream); for (i=0; ibufsize; i++) { self->time += self->inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; mi = min[i]; if (mi < 0.0) mi = 0.0; range = ma[i] - mi; if (range < 0.0) range = 0.0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; self->inc = (1.0 / self->value) / self->sr; } self->data[i] = self->value; } } static void RandDur_postprocessing_ii(RandDur *self) { POST_PROCESSING_II }; static void RandDur_postprocessing_ai(RandDur *self) { POST_PROCESSING_AI }; static void RandDur_postprocessing_ia(RandDur *self) { POST_PROCESSING_IA }; static void RandDur_postprocessing_aa(RandDur *self) { POST_PROCESSING_AA }; static void RandDur_postprocessing_ireva(RandDur *self) { POST_PROCESSING_IREVA }; static void RandDur_postprocessing_areva(RandDur *self) { POST_PROCESSING_AREVA }; static void RandDur_postprocessing_revai(RandDur *self) { POST_PROCESSING_REVAI }; static void RandDur_postprocessing_revaa(RandDur *self) { POST_PROCESSING_REVAA }; static void RandDur_postprocessing_revareva(RandDur *self) { POST_PROCESSING_REVAREVA }; static void RandDur_setProcMode(RandDur *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = RandDur_generate_ii; break; case 1: self->proc_func_ptr = RandDur_generate_ai; break; case 10: self->proc_func_ptr = RandDur_generate_ia; break; case 11: self->proc_func_ptr = RandDur_generate_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = RandDur_postprocessing_ii; break; case 1: self->muladd_func_ptr = RandDur_postprocessing_ai; break; case 2: self->muladd_func_ptr = RandDur_postprocessing_revai; break; case 10: self->muladd_func_ptr = RandDur_postprocessing_ia; break; case 11: self->muladd_func_ptr = RandDur_postprocessing_aa; break; case 12: self->muladd_func_ptr = RandDur_postprocessing_revaa; break; case 20: self->muladd_func_ptr = RandDur_postprocessing_ireva; break; case 21: self->muladd_func_ptr = RandDur_postprocessing_areva; break; case 22: self->muladd_func_ptr = RandDur_postprocessing_revareva; break; } } static void RandDur_compute_next_data_frame(RandDur *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int RandDur_traverse(RandDur *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->min); Py_VISIT(self->min_stream); Py_VISIT(self->max); Py_VISIT(self->max_stream); return 0; } static int RandDur_clear(RandDur *self) { pyo_CLEAR Py_CLEAR(self->min); Py_CLEAR(self->min_stream); Py_CLEAR(self->max); Py_CLEAR(self->max_stream); return 0; } static void RandDur_dealloc(RandDur* self) { pyo_DEALLOC RandDur_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * RandDur_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT mi, ma; PyObject *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL; RandDur *self; self = (RandDur *)type->tp_alloc(type, 0); self->min = PyFloat_FromDouble(0.01); self->max = PyFloat_FromDouble(1.); self->value = self->inc = 0.0; self->time = 1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, RandDur_compute_next_data_frame); self->mode_func_ptr = RandDur_setProcMode; static char *kwlist[] = {"min", "max", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &mintmp, &maxtmp, &multmp, &addtmp)) Py_RETURN_NONE; if (mintmp) { PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp); } if (maxtmp) { PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Server_generateSeed((Server *)self->server, RANDDUR_ID); if (self->modebuffer[2] == 0) mi = PyFloat_AS_DOUBLE(self->min); else mi = Stream_getData((Stream *)self->min_stream)[0]; if (self->modebuffer[3] == 0) ma = PyFloat_AS_DOUBLE(self->max); else ma = Stream_getData((Stream *)self->max_stream)[0]; self->value = (mi + ma) * 0.5; if (self->value == 0.0) self->inc = 0.0; else self->inc = (1.0 / self->value) / self->sr; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * RandDur_getServer(RandDur* self) { GET_SERVER }; static PyObject * RandDur_getStream(RandDur* self) { GET_STREAM }; static PyObject * RandDur_setMul(RandDur *self, PyObject *arg) { SET_MUL }; static PyObject * RandDur_setAdd(RandDur *self, PyObject *arg) { SET_ADD }; static PyObject * RandDur_setSub(RandDur *self, PyObject *arg) { SET_SUB }; static PyObject * RandDur_setDiv(RandDur *self, PyObject *arg) { SET_DIV }; static PyObject * RandDur_play(RandDur *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * RandDur_out(RandDur *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * RandDur_stop(RandDur *self) { STOP }; static PyObject * RandDur_multiply(RandDur *self, PyObject *arg) { MULTIPLY }; static PyObject * RandDur_inplace_multiply(RandDur *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * RandDur_add(RandDur *self, PyObject *arg) { ADD }; static PyObject * RandDur_inplace_add(RandDur *self, PyObject *arg) { INPLACE_ADD }; static PyObject * RandDur_sub(RandDur *self, PyObject *arg) { SUB }; static PyObject * RandDur_inplace_sub(RandDur *self, PyObject *arg) { INPLACE_SUB }; static PyObject * RandDur_div(RandDur *self, PyObject *arg) { DIV }; static PyObject * RandDur_inplace_div(RandDur *self, PyObject *arg) { INPLACE_DIV }; static PyObject * RandDur_setMin(RandDur *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->min); if (isNumber == 1) { self->min = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->min = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->min, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->min_stream); self->min_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * RandDur_setMax(RandDur *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->max); if (isNumber == 1) { self->max = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->max = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->max_stream); self->max_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef RandDur_members[] = { {"server", T_OBJECT_EX, offsetof(RandDur, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(RandDur, stream), 0, "Stream object."}, {"min", T_OBJECT_EX, offsetof(RandDur, min), 0, "Minimum possible value."}, {"max", T_OBJECT_EX, offsetof(RandDur, max), 0, "Maximum possible value."}, {"mul", T_OBJECT_EX, offsetof(RandDur, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(RandDur, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef RandDur_methods[] = { {"getServer", (PyCFunction)RandDur_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)RandDur_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)RandDur_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)RandDur_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)RandDur_stop, METH_NOARGS, "Stops computing."}, {"setMin", (PyCFunction)RandDur_setMin, METH_O, "Sets minimum possible value."}, {"setMax", (PyCFunction)RandDur_setMax, METH_O, "Sets maximum possible value."}, {"setMul", (PyCFunction)RandDur_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)RandDur_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)RandDur_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)RandDur_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods RandDur_as_number = { (binaryfunc)RandDur_add, /*nb_add*/ (binaryfunc)RandDur_sub, /*nb_subtract*/ (binaryfunc)RandDur_multiply, /*nb_multiply*/ (binaryfunc)RandDur_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)RandDur_inplace_add, /*inplace_add*/ (binaryfunc)RandDur_inplace_sub, /*inplace_subtract*/ (binaryfunc)RandDur_inplace_multiply, /*inplace_multiply*/ (binaryfunc)RandDur_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject RandDurType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.RandDur_base", /*tp_name*/ sizeof(RandDur), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)RandDur_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &RandDur_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "RandDur objects. Recursive time varying generation of random values.", /* tp_doc */ (traverseproc)RandDur_traverse, /* tp_traverse */ (inquiry)RandDur_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ RandDur_methods, /* tp_methods */ RandDur_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ RandDur_new, /* tp_new */ }; /****************/ /**** Xnoise *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *x1; PyObject *x2; PyObject *freq; Stream *x1_stream; Stream *x2_stream; Stream *freq_stream; MYFLT (*type_func_ptr)(); MYFLT xx1; MYFLT xx2; int type; MYFLT value; MYFLT time; MYFLT lastPoissonX1; int poisson_tab; MYFLT poisson_buffer[2000]; MYFLT walkerValue; MYFLT loop_buffer[15]; int loopChoice; int loopCountPlay; int loopTime; int loopCountRec; int loopLen; int loopStop; int modebuffer[5]; // need at least 2 slots for mul & add } Xnoise; // no parameter static MYFLT Xnoise_uniform(Xnoise *self) { return RANDOM_UNIFORM; } static MYFLT Xnoise_linear_min(Xnoise *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; if (a < b) return a; else return b; } static MYFLT Xnoise_linear_max(Xnoise *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; if (a > b) return a; else return b; } static MYFLT Xnoise_triangle(Xnoise *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; return ((a + b) * 0.5); } // x1 = slope static MYFLT Xnoise_expon_min(Xnoise *self) { if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT val = -MYLOG(RANDOM_UNIFORM) / self->xx1; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } static MYFLT Xnoise_expon_max(Xnoise *self) { if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT val = 1.0 - (-MYLOG(RANDOM_UNIFORM) / self->xx1); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = bandwidth static MYFLT Xnoise_biexpon(Xnoise *self) { MYFLT polar, val; if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT sum = RANDOM_UNIFORM * 2.0; if (sum > 1.0) { polar = -1; sum = 2.0 - sum; } else polar = 1; val = 0.5 * (polar * MYLOG(sum) / self->xx1) + 0.5; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } static MYFLT Xnoise_cauchy(Xnoise *self) { MYFLT rnd, val, dir; do { rnd = RANDOM_UNIFORM; } while (rnd == 0.5); if (rand() < (RAND_MAX / 2)) dir = -1; else dir = 1; val = 0.5 * (MYTAN(rnd) * self->xx1 * dir) + 0.5; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = locator, x2 = shape static MYFLT Xnoise_weibull(Xnoise *self) { MYFLT rnd, val; if (self->xx2 <= 0.0) self->xx2 = 0.00001; rnd = 1.0 / (1.0 - RANDOM_UNIFORM); val = self->xx1 * MYPOW(MYLOG(rnd), (1.0 / self->xx2)); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = locator, x2 = bandwidth static MYFLT Xnoise_gaussian(Xnoise *self) { MYFLT rnd, val; rnd = (RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM); val = (self->xx2 * (rnd - 3.0) * 0.33 + self->xx1); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = gravity center, x2 = compress/expand static MYFLT Xnoise_poisson(Xnoise *self) { int i, j, factorial; long tot; MYFLT val; if (self->xx1 < 0.1) self->xx1 = 0.1; if (self->xx2 < 0.1) self->xx2 = 0.1; if (self->xx1 != self->lastPoissonX1) { self->lastPoissonX1 = self->xx1; self->poisson_tab = 0; factorial = 1; for (i=1; i<12; i++) { factorial *= i; tot = (long)(1000.0 * (MYPOW(2.7182818, -self->xx1) * MYPOW(self->xx1, i) / factorial)); for (j=0; jpoisson_buffer[self->poisson_tab] = i; self->poisson_tab++; } } } val = self->poisson_buffer[rand() % self->poisson_tab] / 12.0 * self->xx2; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = max value, x2 = max step static MYFLT Xnoise_walker(Xnoise *self) { int modulo, dir; if (self->xx2 < 0.002) self->xx2 = 0.002; modulo = (int)(self->xx2 * 1000.0); dir = rand() % 2; if (dir == 0) self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001); else self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001); if (self->walkerValue > self->xx1) self->walkerValue = self->xx1; if (self->walkerValue < 0.0) self->walkerValue = 0.0; return self->walkerValue; } // x1 = max value, x2 = max step static MYFLT Xnoise_loopseg(Xnoise *self) { int modulo, dir; if (self->loopChoice == 0) { self->loopCountPlay = self->loopTime = 0; if (self->xx2 < 0.002) self->xx2 = 0.002; modulo = (int)(self->xx2 * 1000.0); dir = rand() % 2; if (dir == 0) self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001); else self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001); if (self->walkerValue > self->xx1) self->walkerValue = self->xx1; if (self->walkerValue < 0.0) self->walkerValue = 0.0; self->loop_buffer[self->loopCountRec++] = self->walkerValue; if (self->loopCountRec < self->loopLen) self->loopChoice = 0; else { self->loopChoice = 1; self->loopStop = (rand() % 4) + 1; } } else { self->loopCountRec = 0; self->walkerValue = self->loop_buffer[self->loopCountPlay++]; if (self->loopCountPlay < self->loopLen) self->loopChoice = 1; else { self->loopCountPlay = 0; self->loopTime++; } if (self->loopTime == self->loopStop) { self->loopChoice = 0; self->loopLen = (rand() % 10) + 3; } } return self->walkerValue; } static void Xnoise_generate_iii(Xnoise *self) { int i; MYFLT inc; self->xx1 = PyFloat_AS_DOUBLE(self->x1); self->xx2 = PyFloat_AS_DOUBLE(self->x2); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = (*self->type_func_ptr)(self); } self->data[i] = self->value; } } static void Xnoise_generate_aii(Xnoise *self) { int i; MYFLT inc; MYFLT *x1 = Stream_getData((Stream *)self->x1_stream); self->xx2 = PyFloat_AS_DOUBLE(self->x2); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->xx1 = x1[i]; self->value = (*self->type_func_ptr)(self); } self->data[i] = self->value; } } static void Xnoise_generate_iai(Xnoise *self) { int i; MYFLT inc; self->xx1 = PyFloat_AS_DOUBLE(self->x1); MYFLT *x2 = Stream_getData((Stream *)self->x2_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->xx2 = x2[i]; self->value = (*self->type_func_ptr)(self); } self->data[i] = self->value; } } static void Xnoise_generate_aai(Xnoise *self) { int i; MYFLT inc; MYFLT *x1 = Stream_getData((Stream *)self->x1_stream); MYFLT *x2 = Stream_getData((Stream *)self->x2_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->xx1 = x1[i]; self->xx2 = x2[i]; self->value = (*self->type_func_ptr)(self); } self->data[i] = self->value; } } static void Xnoise_generate_iia(Xnoise *self) { int i; MYFLT inc; self->xx1 = PyFloat_AS_DOUBLE(self->x1); self->xx2 = PyFloat_AS_DOUBLE(self->x2); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = (*self->type_func_ptr)(self); } self->data[i] = self->value; } } static void Xnoise_generate_aia(Xnoise *self) { int i; MYFLT inc; MYFLT *x1 = Stream_getData((Stream *)self->x1_stream); self->xx2 = PyFloat_AS_DOUBLE(self->x2); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->xx1 = x1[i]; self->value = (*self->type_func_ptr)(self); } self->data[i] = self->value; } } static void Xnoise_generate_iaa(Xnoise *self) { int i; MYFLT inc; self->xx1 = PyFloat_AS_DOUBLE(self->x1); MYFLT *x2 = Stream_getData((Stream *)self->x2_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->xx2 = x2[i]; self->value = (*self->type_func_ptr)(self); } self->data[i] = self->value; } } static void Xnoise_generate_aaa(Xnoise *self) { int i; MYFLT inc; MYFLT *x1 = Stream_getData((Stream *)self->x1_stream); MYFLT *x2 = Stream_getData((Stream *)self->x2_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->xx1 = x1[i]; self->xx2 = x2[i]; self->value = (*self->type_func_ptr)(self); } self->data[i] = self->value; } } static void Xnoise_postprocessing_ii(Xnoise *self) { POST_PROCESSING_II }; static void Xnoise_postprocessing_ai(Xnoise *self) { POST_PROCESSING_AI }; static void Xnoise_postprocessing_ia(Xnoise *self) { POST_PROCESSING_IA }; static void Xnoise_postprocessing_aa(Xnoise *self) { POST_PROCESSING_AA }; static void Xnoise_postprocessing_ireva(Xnoise *self) { POST_PROCESSING_IREVA }; static void Xnoise_postprocessing_areva(Xnoise *self) { POST_PROCESSING_AREVA }; static void Xnoise_postprocessing_revai(Xnoise *self) { POST_PROCESSING_REVAI }; static void Xnoise_postprocessing_revaa(Xnoise *self) { POST_PROCESSING_REVAA }; static void Xnoise_postprocessing_revareva(Xnoise *self) { POST_PROCESSING_REVAREVA }; static void Xnoise_setRandomType(Xnoise *self) { switch (self->type) { case 0: self->type_func_ptr = Xnoise_uniform; break; case 1: self->type_func_ptr = Xnoise_linear_min; break; case 2: self->type_func_ptr = Xnoise_linear_max; break; case 3: self->type_func_ptr = Xnoise_triangle; break; case 4: self->type_func_ptr = Xnoise_expon_min; break; case 5: self->type_func_ptr = Xnoise_expon_max; break; case 6: self->type_func_ptr = Xnoise_biexpon; break; case 7: self->type_func_ptr = Xnoise_cauchy; break; case 8: self->type_func_ptr = Xnoise_weibull; break; case 9: self->type_func_ptr = Xnoise_gaussian; break; case 10: self->type_func_ptr = Xnoise_poisson; break; case 11: self->type_func_ptr = Xnoise_walker; break; case 12: self->type_func_ptr = Xnoise_loopseg; break; } } static void Xnoise_setProcMode(Xnoise *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Xnoise_generate_iii; break; case 1: self->proc_func_ptr = Xnoise_generate_aii; break; case 10: self->proc_func_ptr = Xnoise_generate_iai; break; case 11: self->proc_func_ptr = Xnoise_generate_aai; break; case 100: self->proc_func_ptr = Xnoise_generate_iia; break; case 101: self->proc_func_ptr = Xnoise_generate_aia; break; case 110: self->proc_func_ptr = Xnoise_generate_iaa; break; case 111: self->proc_func_ptr = Xnoise_generate_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Xnoise_postprocessing_ii; break; case 1: self->muladd_func_ptr = Xnoise_postprocessing_ai; break; case 2: self->muladd_func_ptr = Xnoise_postprocessing_revai; break; case 10: self->muladd_func_ptr = Xnoise_postprocessing_ia; break; case 11: self->muladd_func_ptr = Xnoise_postprocessing_aa; break; case 12: self->muladd_func_ptr = Xnoise_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Xnoise_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Xnoise_postprocessing_areva; break; case 22: self->muladd_func_ptr = Xnoise_postprocessing_revareva; break; } } static void Xnoise_compute_next_data_frame(Xnoise *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Xnoise_traverse(Xnoise *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->x1); Py_VISIT(self->x1_stream); Py_VISIT(self->x2); Py_VISIT(self->x2_stream); return 0; } static int Xnoise_clear(Xnoise *self) { pyo_CLEAR Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->x1); Py_CLEAR(self->x1_stream); Py_CLEAR(self->x2); Py_CLEAR(self->x2_stream); return 0; } static void Xnoise_dealloc(Xnoise* self) { pyo_DEALLOC Xnoise_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Xnoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *freqtmp=NULL, *x1tmp=NULL, *x2tmp=NULL, *multmp=NULL, *addtmp=NULL; Xnoise *self; self = (Xnoise *)type->tp_alloc(type, 0); self->x1 = PyFloat_FromDouble(0.5); self->x2 = PyFloat_FromDouble(0.5); self->freq = PyFloat_FromDouble(1.); self->xx1 = self->xx2 = self->walkerValue = 0.5; self->value = 0.0; self->time = 1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; INIT_OBJECT_COMMON Server_generateSeed((Server *)self->server, XNOISE_ID); self->poisson_tab = 0; self->lastPoissonX1 = -99.0; for (i=0; i<2000; i++) { self->poisson_buffer[i] = 0.0; } for (i=0; i<15; i++) { self->loop_buffer[i] = 0.0; } self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0; self->loopLen = (rand() % 10) + 3; Stream_setFunctionPtr(self->stream, Xnoise_compute_next_data_frame); self->mode_func_ptr = Xnoise_setProcMode; static char *kwlist[] = {"type", "freq", "x1", "x2", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iOOOOO", kwlist, &self->type, &freqtmp, &x1tmp, &x2tmp, &multmp, &addtmp)) Py_RETURN_NONE; if (x1tmp) { PyObject_CallMethod((PyObject *)self, "setX1", "O", x1tmp); } if (x2tmp) { PyObject_CallMethod((PyObject *)self, "setX2", "O", x2tmp); } if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Xnoise_setRandomType(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Xnoise_getServer(Xnoise* self) { GET_SERVER }; static PyObject * Xnoise_getStream(Xnoise* self) { GET_STREAM }; static PyObject * Xnoise_setMul(Xnoise *self, PyObject *arg) { SET_MUL }; static PyObject * Xnoise_setAdd(Xnoise *self, PyObject *arg) { SET_ADD }; static PyObject * Xnoise_setSub(Xnoise *self, PyObject *arg) { SET_SUB }; static PyObject * Xnoise_setDiv(Xnoise *self, PyObject *arg) { SET_DIV }; static PyObject * Xnoise_play(Xnoise *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Xnoise_out(Xnoise *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Xnoise_stop(Xnoise *self) { STOP }; static PyObject * Xnoise_multiply(Xnoise *self, PyObject *arg) { MULTIPLY }; static PyObject * Xnoise_inplace_multiply(Xnoise *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Xnoise_add(Xnoise *self, PyObject *arg) { ADD }; static PyObject * Xnoise_inplace_add(Xnoise *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Xnoise_sub(Xnoise *self, PyObject *arg) { SUB }; static PyObject * Xnoise_inplace_sub(Xnoise *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Xnoise_div(Xnoise *self, PyObject *arg) { DIV }; static PyObject * Xnoise_inplace_div(Xnoise *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Xnoise_setType(Xnoise *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyInt_Check(arg); if (isNumber == 1) { self->type = PyInt_AsLong(arg); Xnoise_setRandomType(self); } Py_INCREF(Py_None); return Py_None; } static PyObject * Xnoise_setX1(Xnoise *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->x1); if (isNumber == 1) { self->x1 = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->x1 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->x1, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->x1_stream); self->x1_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Xnoise_setX2(Xnoise *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->x2); if (isNumber == 1) { self->x2 = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->x2 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->x2, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->x2_stream); self->x2_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Xnoise_setFreq(Xnoise *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Xnoise_members[] = { {"server", T_OBJECT_EX, offsetof(Xnoise, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Xnoise, stream), 0, "Stream object."}, {"x1", T_OBJECT_EX, offsetof(Xnoise, x1), 0, "first param."}, {"x2", T_OBJECT_EX, offsetof(Xnoise, x2), 0, "second param."}, {"freq", T_OBJECT_EX, offsetof(Xnoise, freq), 0, "Polling frequency."}, {"mul", T_OBJECT_EX, offsetof(Xnoise, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Xnoise, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Xnoise_methods[] = { {"getServer", (PyCFunction)Xnoise_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Xnoise_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Xnoise_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Xnoise_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Xnoise_stop, METH_NOARGS, "Stops computing."}, {"setType", (PyCFunction)Xnoise_setType, METH_O, "Sets distribution type."}, {"setX1", (PyCFunction)Xnoise_setX1, METH_O, "Sets first param."}, {"setX2", (PyCFunction)Xnoise_setX2, METH_O, "Sets second param."}, {"setFreq", (PyCFunction)Xnoise_setFreq, METH_O, "Sets polling frequency."}, {"setMul", (PyCFunction)Xnoise_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Xnoise_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Xnoise_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Xnoise_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Xnoise_as_number = { (binaryfunc)Xnoise_add, /*nb_add*/ (binaryfunc)Xnoise_sub, /*nb_subtract*/ (binaryfunc)Xnoise_multiply, /*nb_multiply*/ (binaryfunc)Xnoise_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Xnoise_inplace_add, /*inplace_add*/ (binaryfunc)Xnoise_inplace_sub, /*inplace_subtract*/ (binaryfunc)Xnoise_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Xnoise_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject XnoiseType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Xnoise_base", /*tp_name*/ sizeof(Xnoise), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Xnoise_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Xnoise_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Xnoise objects. Periodically generates a new random value.", /* tp_doc */ (traverseproc)Xnoise_traverse, /* tp_traverse */ (inquiry)Xnoise_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Xnoise_methods, /* tp_methods */ Xnoise_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Xnoise_new, /* tp_new */ }; /****************/ /**** XnoiseMidi *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *x1; PyObject *x2; PyObject *freq; Stream *x1_stream; Stream *x2_stream; Stream *freq_stream; MYFLT (*type_func_ptr)(); int scale; // 0 = Midi, 1 = frequency, 2 = transpo MYFLT xx1; MYFLT xx2; int range_min; int range_max; int centralkey; int type; MYFLT value; MYFLT time; MYFLT lastPoissonX1; int poisson_tab; MYFLT poisson_buffer[2000]; MYFLT walkerValue; MYFLT loop_buffer[15]; int loopChoice; int loopCountPlay; int loopTime; int loopCountRec; int loopLen; int loopStop; int modebuffer[5]; // need at least 2 slots for mul & add } XnoiseMidi; static MYFLT XnoiseMidi_convert(XnoiseMidi *self) { int midival; MYFLT val; midival = (int)((self->value * (self->range_max-self->range_min)) + self->range_min); if (midival < 0) midival = 0; else if (midival > 127) midival = 127; if (self->scale == 0) val = (MYFLT)midival; else if (self->scale == 1) val = 8.1757989156437 * MYPOW(1.0594630943593, midival); else if (self->scale == 2) val = MYPOW(1.0594630943593, midival - self->centralkey); else val = midival; return val; } // no parameter static MYFLT XnoiseMidi_uniform(XnoiseMidi *self) { return RANDOM_UNIFORM; } static MYFLT XnoiseMidi_linear_min(XnoiseMidi *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; if (a < b) return a; else return b; } static MYFLT XnoiseMidi_linear_max(XnoiseMidi *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; if (a > b) return a; else return b; } static MYFLT XnoiseMidi_triangle(XnoiseMidi *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; return ((a + b) * 0.5); } // x1 = slope static MYFLT XnoiseMidi_expon_min(XnoiseMidi *self) { if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT val = -MYLOG(RANDOM_UNIFORM) / self->xx1; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } static MYFLT XnoiseMidi_expon_max(XnoiseMidi *self) { if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT val = 1.0 - (-MYLOG(RANDOM_UNIFORM) / self->xx1); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = bandwidth static MYFLT XnoiseMidi_biexpon(XnoiseMidi *self) { MYFLT polar, val; if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT sum = RANDOM_UNIFORM * 2.0; if (sum > 1.0) { polar = -1; sum = 2.0 - sum; } else polar = 1; val = 0.5 * (polar * MYLOG(sum) / self->xx1) + 0.5; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } static MYFLT XnoiseMidi_cauchy(XnoiseMidi *self) { MYFLT rnd, val, dir; do { rnd = RANDOM_UNIFORM; } while (rnd == 0.5); if (rand() < (RAND_MAX / 2)) dir = -1; else dir = 1; val = 0.5 * (MYTAN(rnd) * self->xx1 * dir) + 0.5; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = locator, x2 = shape static MYFLT XnoiseMidi_weibull(XnoiseMidi *self) { MYFLT rnd, val; if (self->xx2 <= 0.0) self->xx2 = 0.00001; rnd = 1.0 / (1.0 - RANDOM_UNIFORM); val = self->xx1 * MYPOW(MYLOG(rnd), (1.0 / self->xx2)); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = locator, x2 = bandwidth static MYFLT XnoiseMidi_gaussian(XnoiseMidi *self) { MYFLT rnd, val; rnd = (RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM); val = (self->xx2 * (rnd - 3.0) * 0.33 + self->xx1); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = gravity center, x2 = compress/expand static MYFLT XnoiseMidi_poisson(XnoiseMidi *self) { int i, j, factorial; long tot; MYFLT val; if (self->xx1 < 0.1) self->xx1 = 0.1; if (self->xx2 < 0.1) self->xx2 = 0.1; if (self->xx1 != self->lastPoissonX1) { self->lastPoissonX1 = self->xx1; self->poisson_tab = 0; factorial = 1; for (i=1; i<12; i++) { factorial *= i; tot = (long)(1000.0 * (MYPOW(2.7182818, -self->xx1) * MYPOW(self->xx1, i) / factorial)); for (j=0; jpoisson_buffer[self->poisson_tab] = i; self->poisson_tab++; } } } val = self->poisson_buffer[rand() % self->poisson_tab] / 12.0 * self->xx2; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = max value, x2 = max step static MYFLT XnoiseMidi_walker(XnoiseMidi *self) { int modulo, dir; if (self->xx2 < 0.002) self->xx2 = 0.002; modulo = (int)(self->xx2 * 1000.0); dir = rand() % 2; if (dir == 0) self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001); else self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001); if (self->walkerValue > self->xx1) self->walkerValue = self->xx1; if (self->walkerValue < 0.0) self->walkerValue = 0.0; return self->walkerValue; } // x1 = max value, x2 = max step static MYFLT XnoiseMidi_loopseg(XnoiseMidi *self) { int modulo, dir; if (self->loopChoice == 0) { self->loopCountPlay = self->loopTime = 0; if (self->xx2 < 0.002) self->xx2 = 0.002; modulo = (int)(self->xx2 * 1000.0); dir = rand() % 2; if (dir == 0) self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001); else self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001); if (self->walkerValue > self->xx1) self->walkerValue = self->xx1; if (self->walkerValue < 0.0) self->walkerValue = 0.0; self->loop_buffer[self->loopCountRec++] = self->walkerValue; if (self->loopCountRec < self->loopLen) self->loopChoice = 0; else { self->loopChoice = 1; self->loopStop = (rand() % 4) + 1; } } else { self->loopCountRec = 0; self->walkerValue = self->loop_buffer[self->loopCountPlay++]; if (self->loopCountPlay < self->loopLen) self->loopChoice = 1; else { self->loopCountPlay = 0; self->loopTime++; } if (self->loopTime == self->loopStop) { self->loopChoice = 0; self->loopLen = (rand() % 10) + 3; } } return self->walkerValue; } static void XnoiseMidi_generate_iii(XnoiseMidi *self) { int i; MYFLT inc; self->xx1 = PyFloat_AS_DOUBLE(self->x1); self->xx2 = PyFloat_AS_DOUBLE(self->x2); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = (*self->type_func_ptr)(self); self->value = XnoiseMidi_convert(self); } self->data[i] = self->value; } } static void XnoiseMidi_generate_aii(XnoiseMidi *self) { int i; MYFLT inc; MYFLT *x1 = Stream_getData((Stream *)self->x1_stream); self->xx2 = PyFloat_AS_DOUBLE(self->x2); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->xx1 = x1[i]; self->value = (*self->type_func_ptr)(self); self->value = XnoiseMidi_convert(self); } self->data[i] = self->value; } } static void XnoiseMidi_generate_iai(XnoiseMidi *self) { int i; MYFLT inc; self->xx1 = PyFloat_AS_DOUBLE(self->x1); MYFLT *x2 = Stream_getData((Stream *)self->x2_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->xx2 = x2[i]; self->value = (*self->type_func_ptr)(self); self->value = XnoiseMidi_convert(self); } self->data[i] = self->value; } } static void XnoiseMidi_generate_aai(XnoiseMidi *self) { int i; MYFLT inc; MYFLT *x1 = Stream_getData((Stream *)self->x1_stream); MYFLT *x2 = Stream_getData((Stream *)self->x2_stream); MYFLT fr = PyFloat_AS_DOUBLE(self->freq); inc = fr / self->sr; for (i=0; ibufsize; i++) { self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->xx1 = x1[i]; self->xx2 = x2[i]; self->value = (*self->type_func_ptr)(self); self->value = XnoiseMidi_convert(self); } self->data[i] = self->value; } } static void XnoiseMidi_generate_iia(XnoiseMidi *self) { int i; MYFLT inc; self->xx1 = PyFloat_AS_DOUBLE(self->x1); self->xx2 = PyFloat_AS_DOUBLE(self->x2); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = (*self->type_func_ptr)(self); self->value = XnoiseMidi_convert(self); } self->data[i] = self->value; } } static void XnoiseMidi_generate_aia(XnoiseMidi *self) { int i; MYFLT inc; MYFLT *x1 = Stream_getData((Stream *)self->x1_stream); self->xx2 = PyFloat_AS_DOUBLE(self->x2); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->xx1 = x1[i]; self->value = (*self->type_func_ptr)(self); self->value = XnoiseMidi_convert(self); } self->data[i] = self->value; } } static void XnoiseMidi_generate_iaa(XnoiseMidi *self) { int i; MYFLT inc; self->xx1 = PyFloat_AS_DOUBLE(self->x1); MYFLT *x2 = Stream_getData((Stream *)self->x2_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->xx2 = x2[i]; self->value = (*self->type_func_ptr)(self); self->value = XnoiseMidi_convert(self); } self->data[i] = self->value; } } static void XnoiseMidi_generate_aaa(XnoiseMidi *self) { int i; MYFLT inc; MYFLT *x1 = Stream_getData((Stream *)self->x1_stream); MYFLT *x2 = Stream_getData((Stream *)self->x2_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->xx1 = x1[i]; self->xx2 = x2[i]; self->value = (*self->type_func_ptr)(self); self->value = XnoiseMidi_convert(self); } self->data[i] = self->value; } } static void XnoiseMidi_postprocessing_ii(XnoiseMidi *self) { POST_PROCESSING_II }; static void XnoiseMidi_postprocessing_ai(XnoiseMidi *self) { POST_PROCESSING_AI }; static void XnoiseMidi_postprocessing_ia(XnoiseMidi *self) { POST_PROCESSING_IA }; static void XnoiseMidi_postprocessing_aa(XnoiseMidi *self) { POST_PROCESSING_AA }; static void XnoiseMidi_postprocessing_ireva(XnoiseMidi *self) { POST_PROCESSING_IREVA }; static void XnoiseMidi_postprocessing_areva(XnoiseMidi *self) { POST_PROCESSING_AREVA }; static void XnoiseMidi_postprocessing_revai(XnoiseMidi *self) { POST_PROCESSING_REVAI }; static void XnoiseMidi_postprocessing_revaa(XnoiseMidi *self) { POST_PROCESSING_REVAA }; static void XnoiseMidi_postprocessing_revareva(XnoiseMidi *self) { POST_PROCESSING_REVAREVA }; static void XnoiseMidi_setRandomType(XnoiseMidi *self) { switch (self->type) { case 0: self->type_func_ptr = XnoiseMidi_uniform; break; case 1: self->type_func_ptr = XnoiseMidi_linear_min; break; case 2: self->type_func_ptr = XnoiseMidi_linear_max; break; case 3: self->type_func_ptr = XnoiseMidi_triangle; break; case 4: self->type_func_ptr = XnoiseMidi_expon_min; break; case 5: self->type_func_ptr = XnoiseMidi_expon_max; break; case 6: self->type_func_ptr = XnoiseMidi_biexpon; break; case 7: self->type_func_ptr = XnoiseMidi_cauchy; break; case 8: self->type_func_ptr = XnoiseMidi_weibull; break; case 9: self->type_func_ptr = XnoiseMidi_gaussian; break; case 10: self->type_func_ptr = XnoiseMidi_poisson; break; case 11: self->type_func_ptr = XnoiseMidi_walker; break; case 12: self->type_func_ptr = XnoiseMidi_loopseg; break; } } static void XnoiseMidi_setProcMode(XnoiseMidi *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = XnoiseMidi_generate_iii; break; case 1: self->proc_func_ptr = XnoiseMidi_generate_aii; break; case 10: self->proc_func_ptr = XnoiseMidi_generate_iai; break; case 11: self->proc_func_ptr = XnoiseMidi_generate_aai; break; case 100: self->proc_func_ptr = XnoiseMidi_generate_iia; break; case 101: self->proc_func_ptr = XnoiseMidi_generate_aia; break; case 110: self->proc_func_ptr = XnoiseMidi_generate_iaa; break; case 111: self->proc_func_ptr = XnoiseMidi_generate_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = XnoiseMidi_postprocessing_ii; break; case 1: self->muladd_func_ptr = XnoiseMidi_postprocessing_ai; break; case 2: self->muladd_func_ptr = XnoiseMidi_postprocessing_revai; break; case 10: self->muladd_func_ptr = XnoiseMidi_postprocessing_ia; break; case 11: self->muladd_func_ptr = XnoiseMidi_postprocessing_aa; break; case 12: self->muladd_func_ptr = XnoiseMidi_postprocessing_revaa; break; case 20: self->muladd_func_ptr = XnoiseMidi_postprocessing_ireva; break; case 21: self->muladd_func_ptr = XnoiseMidi_postprocessing_areva; break; case 22: self->muladd_func_ptr = XnoiseMidi_postprocessing_revareva; break; } } static void XnoiseMidi_compute_next_data_frame(XnoiseMidi *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int XnoiseMidi_traverse(XnoiseMidi *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->x1); Py_VISIT(self->x1_stream); Py_VISIT(self->x2); Py_VISIT(self->x2_stream); return 0; } static int XnoiseMidi_clear(XnoiseMidi *self) { pyo_CLEAR Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->x1); Py_CLEAR(self->x1_stream); Py_CLEAR(self->x2); Py_CLEAR(self->x2_stream); return 0; } static void XnoiseMidi_dealloc(XnoiseMidi* self) { pyo_DEALLOC XnoiseMidi_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * XnoiseMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *freqtmp=NULL, *x1tmp=NULL, *x2tmp=NULL, *rangetmp=NULL, *multmp=NULL, *addtmp=NULL; XnoiseMidi *self; self = (XnoiseMidi *)type->tp_alloc(type, 0); self->x1 = PyFloat_FromDouble(0.5); self->x2 = PyFloat_FromDouble(0.5); self->freq = PyFloat_FromDouble(1.); self->xx1 = self->xx2 = self->walkerValue = 0.5; self->value = 0.0; self->time = 1.0; self->scale = 0; self->range_min = 0; self->range_max = 127; self->centralkey = 64; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; INIT_OBJECT_COMMON Server_generateSeed((Server *)self->server, XNOISEMIDI_ID); self->poisson_tab = 0; self->lastPoissonX1 = -99.0; for (i=0; i<2000; i++) { self->poisson_buffer[i] = 0.0; } for (i=0; i<15; i++) { self->loop_buffer[i] = 0.0; } self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0; self->loopLen = (rand() % 10) + 3; Stream_setFunctionPtr(self->stream, XnoiseMidi_compute_next_data_frame); self->mode_func_ptr = XnoiseMidi_setProcMode; static char *kwlist[] = {"type", "freq", "x1", "x2", "scale", "range", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iOOOiOOO", kwlist, &self->type, &freqtmp, &x1tmp, &x2tmp, &self->scale, &rangetmp, &multmp, &addtmp)) Py_RETURN_NONE; if (x1tmp) { PyObject_CallMethod((PyObject *)self, "setX1", "O", x1tmp); } if (x2tmp) { PyObject_CallMethod((PyObject *)self, "setX2", "O", x2tmp); } if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (rangetmp) { PyObject_CallMethod((PyObject *)self, "setRange", "O", rangetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); XnoiseMidi_setRandomType(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * XnoiseMidi_getServer(XnoiseMidi* self) { GET_SERVER }; static PyObject * XnoiseMidi_getStream(XnoiseMidi* self) { GET_STREAM }; static PyObject * XnoiseMidi_setMul(XnoiseMidi *self, PyObject *arg) { SET_MUL }; static PyObject * XnoiseMidi_setAdd(XnoiseMidi *self, PyObject *arg) { SET_ADD }; static PyObject * XnoiseMidi_setSub(XnoiseMidi *self, PyObject *arg) { SET_SUB }; static PyObject * XnoiseMidi_setDiv(XnoiseMidi *self, PyObject *arg) { SET_DIV }; static PyObject * XnoiseMidi_play(XnoiseMidi *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * XnoiseMidi_out(XnoiseMidi *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * XnoiseMidi_stop(XnoiseMidi *self) { STOP }; static PyObject * XnoiseMidi_multiply(XnoiseMidi *self, PyObject *arg) { MULTIPLY }; static PyObject * XnoiseMidi_inplace_multiply(XnoiseMidi *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * XnoiseMidi_add(XnoiseMidi *self, PyObject *arg) { ADD }; static PyObject * XnoiseMidi_inplace_add(XnoiseMidi *self, PyObject *arg) { INPLACE_ADD }; static PyObject * XnoiseMidi_sub(XnoiseMidi *self, PyObject *arg) { SUB }; static PyObject * XnoiseMidi_inplace_sub(XnoiseMidi *self, PyObject *arg) { INPLACE_SUB }; static PyObject * XnoiseMidi_div(XnoiseMidi *self, PyObject *arg) { DIV }; static PyObject * XnoiseMidi_inplace_div(XnoiseMidi *self, PyObject *arg) { INPLACE_DIV }; static PyObject * XnoiseMidi_setType(XnoiseMidi *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyInt_Check(arg); if (isNumber == 1) { self->type = PyInt_AsLong(arg); XnoiseMidi_setRandomType(self); } Py_INCREF(Py_None); return Py_None; } static PyObject * XnoiseMidi_setScale(XnoiseMidi *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isNumber = PyInt_Check(arg); if (isNumber == 1) { tmp = PyInt_AsLong(arg); if (tmp >= 0 && tmp <= 2) self->scale = tmp; else printf("scale attribute must be an integer {0, 1, 2}\n"); } Py_INCREF(Py_None); return Py_None; } static PyObject * XnoiseMidi_setRange(XnoiseMidi *self, PyObject *args) { if (args == NULL) { Py_INCREF(Py_None); return Py_None; } int isTuple = PyTuple_Check(args); if (isTuple == 1) { self->range_min = PyInt_AsLong(PyTuple_GET_ITEM(args, 0)); self->range_max = PyInt_AsLong(PyTuple_GET_ITEM(args, 1)); self->centralkey = (int)((self->range_max + self->range_min) / 2); } Py_INCREF(Py_None); return Py_None; } static PyObject * XnoiseMidi_setX1(XnoiseMidi *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->x1); if (isNumber == 1) { self->x1 = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->x1 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->x1, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->x1_stream); self->x1_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * XnoiseMidi_setX2(XnoiseMidi *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->x2); if (isNumber == 1) { self->x2 = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->x2 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->x2, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->x2_stream); self->x2_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * XnoiseMidi_setFreq(XnoiseMidi *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef XnoiseMidi_members[] = { {"server", T_OBJECT_EX, offsetof(XnoiseMidi, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(XnoiseMidi, stream), 0, "Stream object."}, {"x1", T_OBJECT_EX, offsetof(XnoiseMidi, x1), 0, "first param."}, {"x2", T_OBJECT_EX, offsetof(XnoiseMidi, x2), 0, "second param."}, {"freq", T_OBJECT_EX, offsetof(XnoiseMidi, freq), 0, "Polling frequency."}, {"mul", T_OBJECT_EX, offsetof(XnoiseMidi, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(XnoiseMidi, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef XnoiseMidi_methods[] = { {"getServer", (PyCFunction)XnoiseMidi_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)XnoiseMidi_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)XnoiseMidi_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)XnoiseMidi_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)XnoiseMidi_stop, METH_NOARGS, "Stops computing."}, {"setType", (PyCFunction)XnoiseMidi_setType, METH_O, "Sets distribution type."}, {"setScale", (PyCFunction)XnoiseMidi_setScale, METH_O, "Sets output scale."}, {"setRange", (PyCFunction)XnoiseMidi_setRange, METH_VARARGS, "Sets range in midi notes (min, max)."}, {"setX1", (PyCFunction)XnoiseMidi_setX1, METH_O, "Sets first param."}, {"setX2", (PyCFunction)XnoiseMidi_setX2, METH_O, "Sets second param."}, {"setFreq", (PyCFunction)XnoiseMidi_setFreq, METH_O, "Sets polling frequency."}, {"setMul", (PyCFunction)XnoiseMidi_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)XnoiseMidi_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)XnoiseMidi_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)XnoiseMidi_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods XnoiseMidi_as_number = { (binaryfunc)XnoiseMidi_add, /*nb_add*/ (binaryfunc)XnoiseMidi_sub, /*nb_subtract*/ (binaryfunc)XnoiseMidi_multiply, /*nb_multiply*/ (binaryfunc)XnoiseMidi_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)XnoiseMidi_inplace_add, /*inplace_add*/ (binaryfunc)XnoiseMidi_inplace_sub, /*inplace_subtract*/ (binaryfunc)XnoiseMidi_inplace_multiply, /*inplace_multiply*/ (binaryfunc)XnoiseMidi_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject XnoiseMidiType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.XnoiseMidi_base", /*tp_name*/ sizeof(XnoiseMidi), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)XnoiseMidi_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &XnoiseMidi_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "XnoiseMidi objects. Periodically generates a new random value.", /* tp_doc */ (traverseproc)XnoiseMidi_traverse, /* tp_traverse */ (inquiry)XnoiseMidi_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ XnoiseMidi_methods, /* tp_methods */ XnoiseMidi_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ XnoiseMidi_new, /* tp_new */ }; /****************/ /**** XnoiseDur *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *x1; PyObject *x2; PyObject *min; PyObject *max; Stream *x1_stream; Stream *x2_stream; Stream *min_stream; Stream *max_stream; MYFLT (*type_func_ptr)(); MYFLT xx1; MYFLT xx2; int type; MYFLT value; MYFLT time; MYFLT inc; MYFLT lastPoissonX1; int poisson_tab; MYFLT poisson_buffer[2000]; MYFLT walkerValue; MYFLT loop_buffer[15]; int loopChoice; int loopCountPlay; int loopTime; int loopCountRec; int loopLen; int loopStop; int modebuffer[6]; // need at least 2 slots for mul & add } XnoiseDur; // no parameter static MYFLT XnoiseDur_uniform(XnoiseDur *self) { return RANDOM_UNIFORM; } static MYFLT XnoiseDur_linear_min(XnoiseDur *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; if (a < b) return a; else return b; } static MYFLT XnoiseDur_linear_max(XnoiseDur *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; if (a > b) return a; else return b; } static MYFLT XnoiseDur_triangle(XnoiseDur *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; return ((a + b) * 0.5); } // x1 = slope static MYFLT XnoiseDur_expon_min(XnoiseDur *self) { if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT val = -MYLOG(RANDOM_UNIFORM) / self->xx1; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } static MYFLT XnoiseDur_expon_max(XnoiseDur *self) { if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT val = 1.0 - (-MYLOG(RANDOM_UNIFORM) / self->xx1); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = bandwidth static MYFLT XnoiseDur_biexpon(XnoiseDur *self) { MYFLT polar, val; if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT sum = RANDOM_UNIFORM * 2.0; if (sum > 1.0) { polar = -1; sum = 2.0 - sum; } else polar = 1; val = 0.5 * (polar * MYLOG(sum) / self->xx1) + 0.5; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } static MYFLT XnoiseDur_cauchy(XnoiseDur *self) { MYFLT rnd, val, dir; do { rnd = RANDOM_UNIFORM; } while (rnd == 0.5); if (rand() < (RAND_MAX / 2)) dir = -1; else dir = 1; val = 0.5 * (MYTAN(rnd) * self->xx1 * dir) + 0.5; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = locator, x2 = shape static MYFLT XnoiseDur_weibull(XnoiseDur *self) { MYFLT rnd, val; if (self->xx2 <= 0.0) self->xx2 = 0.00001; rnd = 1.0 / (1.0 - RANDOM_UNIFORM); val = self->xx1 * MYPOW(MYLOG(rnd), (1.0 / self->xx2)); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = locator, x2 = bandwidth static MYFLT XnoiseDur_gaussian(XnoiseDur *self) { MYFLT rnd, val; rnd = (RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM); val = (self->xx2 * (rnd - 3.0) * 0.33 + self->xx1); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = gravity center, x2 = compress/expand static MYFLT XnoiseDur_poisson(XnoiseDur *self) { int i, j, factorial; long tot; MYFLT val; if (self->xx1 < 0.1) self->xx1 = 0.1; if (self->xx2 < 0.1) self->xx2 = 0.1; if (self->xx1 != self->lastPoissonX1) { self->lastPoissonX1 = self->xx1; self->poisson_tab = 0; factorial = 1; for (i=1; i<12; i++) { factorial *= i; tot = (long)(1000.0 * (MYPOW(2.7182818, -self->xx1) * MYPOW(self->xx1, i) / factorial)); for (j=0; jpoisson_buffer[self->poisson_tab] = i; self->poisson_tab++; } } } val = self->poisson_buffer[rand() % self->poisson_tab] / 12.0 * self->xx2; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = max value, x2 = max step static MYFLT XnoiseDur_walker(XnoiseDur *self) { int modulo, dir; if (self->xx2 < 0.002) self->xx2 = 0.002; modulo = (int)(self->xx2 * 1000.0); dir = rand() % 2; if (dir == 0) self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001); else self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001); if (self->walkerValue > self->xx1) self->walkerValue = self->xx1; if (self->walkerValue < 0.0) self->walkerValue = 0.0; return self->walkerValue; } // x1 = max value, x2 = max step static MYFLT XnoiseDur_loopseg(XnoiseDur *self) { int modulo, dir; if (self->loopChoice == 0) { self->loopCountPlay = self->loopTime = 0; if (self->xx2 < 0.002) self->xx2 = 0.002; modulo = (int)(self->xx2 * 1000.0); dir = rand() % 2; if (dir == 0) self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001); else self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001); if (self->walkerValue > self->xx1) self->walkerValue = self->xx1; if (self->walkerValue < 0.0) self->walkerValue = 0.0; self->loop_buffer[self->loopCountRec++] = self->walkerValue; if (self->loopCountRec < self->loopLen) self->loopChoice = 0; else { self->loopChoice = 1; self->loopStop = (rand() % 4) + 1; } } else { self->loopCountRec = 0; self->walkerValue = self->loop_buffer[self->loopCountPlay++]; if (self->loopCountPlay < self->loopLen) self->loopChoice = 1; else { self->loopCountPlay = 0; self->loopTime++; } if (self->loopTime == self->loopStop) { self->loopChoice = 0; self->loopLen = (rand() % 10) + 3; } } return self->walkerValue; } static void XnoiseDur_generate(XnoiseDur *self) { int i; MYFLT min, max; for (i=0; ibufsize; i++) { self->time += self->inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; if (self->modebuffer[2] == 0) self->xx1 = PyFloat_AS_DOUBLE(self->x1); else self->xx1 = Stream_getData((Stream *)self->x1_stream)[i]; if (self->modebuffer[3] == 0) self->xx2 = PyFloat_AS_DOUBLE(self->x2); else self->xx2 = Stream_getData((Stream *)self->x2_stream)[i]; if (self->modebuffer[4] == 0) min = PyFloat_AS_DOUBLE(self->min); else min = Stream_getData((Stream *)self->min_stream)[i]; if (self->modebuffer[5] == 0) max = PyFloat_AS_DOUBLE(self->max); else max = Stream_getData((Stream *)self->max_stream)[i]; if (min > max) max = min; self->value = (*self->type_func_ptr)(self) * (max - min) + min; if (self->value == 0.0) self->inc = 0.0; else self->inc = (1.0 / self->value) / self->sr; } self->data[i] = self->value; } } static void XnoiseDur_postprocessing_ii(XnoiseDur *self) { POST_PROCESSING_II }; static void XnoiseDur_postprocessing_ai(XnoiseDur *self) { POST_PROCESSING_AI }; static void XnoiseDur_postprocessing_ia(XnoiseDur *self) { POST_PROCESSING_IA }; static void XnoiseDur_postprocessing_aa(XnoiseDur *self) { POST_PROCESSING_AA }; static void XnoiseDur_postprocessing_ireva(XnoiseDur *self) { POST_PROCESSING_IREVA }; static void XnoiseDur_postprocessing_areva(XnoiseDur *self) { POST_PROCESSING_AREVA }; static void XnoiseDur_postprocessing_revai(XnoiseDur *self) { POST_PROCESSING_REVAI }; static void XnoiseDur_postprocessing_revaa(XnoiseDur *self) { POST_PROCESSING_REVAA }; static void XnoiseDur_postprocessing_revareva(XnoiseDur *self) { POST_PROCESSING_REVAREVA }; static void XnoiseDur_setRandomType(XnoiseDur *self) { switch (self->type) { case 0: self->type_func_ptr = XnoiseDur_uniform; break; case 1: self->type_func_ptr = XnoiseDur_linear_min; break; case 2: self->type_func_ptr = XnoiseDur_linear_max; break; case 3: self->type_func_ptr = XnoiseDur_triangle; break; case 4: self->type_func_ptr = XnoiseDur_expon_min; break; case 5: self->type_func_ptr = XnoiseDur_expon_max; break; case 6: self->type_func_ptr = XnoiseDur_biexpon; break; case 7: self->type_func_ptr = XnoiseDur_cauchy; break; case 8: self->type_func_ptr = XnoiseDur_weibull; break; case 9: self->type_func_ptr = XnoiseDur_gaussian; break; case 10: self->type_func_ptr = XnoiseDur_poisson; break; case 11: self->type_func_ptr = XnoiseDur_walker; break; case 12: self->type_func_ptr = XnoiseDur_loopseg; break; } } static void XnoiseDur_setProcMode(XnoiseDur *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = XnoiseDur_generate; switch (muladdmode) { case 0: self->muladd_func_ptr = XnoiseDur_postprocessing_ii; break; case 1: self->muladd_func_ptr = XnoiseDur_postprocessing_ai; break; case 2: self->muladd_func_ptr = XnoiseDur_postprocessing_revai; break; case 10: self->muladd_func_ptr = XnoiseDur_postprocessing_ia; break; case 11: self->muladd_func_ptr = XnoiseDur_postprocessing_aa; break; case 12: self->muladd_func_ptr = XnoiseDur_postprocessing_revaa; break; case 20: self->muladd_func_ptr = XnoiseDur_postprocessing_ireva; break; case 21: self->muladd_func_ptr = XnoiseDur_postprocessing_areva; break; case 22: self->muladd_func_ptr = XnoiseDur_postprocessing_revareva; break; } } static void XnoiseDur_compute_next_data_frame(XnoiseDur *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int XnoiseDur_traverse(XnoiseDur *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->min); Py_VISIT(self->min_stream); Py_VISIT(self->max); Py_VISIT(self->max_stream); Py_VISIT(self->x1); Py_VISIT(self->x1_stream); Py_VISIT(self->x2); Py_VISIT(self->x2_stream); return 0; } static int XnoiseDur_clear(XnoiseDur *self) { pyo_CLEAR Py_CLEAR(self->min); Py_CLEAR(self->min_stream); Py_CLEAR(self->max); Py_CLEAR(self->max_stream); Py_CLEAR(self->x1); Py_CLEAR(self->x1_stream); Py_CLEAR(self->x2); Py_CLEAR(self->x2_stream); return 0; } static void XnoiseDur_dealloc(XnoiseDur* self) { pyo_DEALLOC XnoiseDur_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * XnoiseDur_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT mi, ma; PyObject *mintmp=NULL, *maxtmp=NULL, *x1tmp=NULL, *x2tmp=NULL, *multmp=NULL, *addtmp=NULL; XnoiseDur *self; self = (XnoiseDur *)type->tp_alloc(type, 0); self->x1 = PyFloat_FromDouble(0.5); self->x2 = PyFloat_FromDouble(0.5); self->min = PyFloat_FromDouble(0.0); self->max = PyFloat_FromDouble(1.0); self->xx1 = self->xx2 = self->walkerValue = 0.5; self->time = 1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->modebuffer[5] = 0; INIT_OBJECT_COMMON Server_generateSeed((Server *)self->server, XNOISEDUR_ID); self->poisson_tab = 0; self->lastPoissonX1 = -99.0; for (i=0; i<2000; i++) { self->poisson_buffer[i] = 0.0; } for (i=0; i<15; i++) { self->loop_buffer[i] = 0.0; } self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0; self->loopLen = (rand() % 10) + 3; Stream_setFunctionPtr(self->stream, XnoiseDur_compute_next_data_frame); self->mode_func_ptr = XnoiseDur_setProcMode; static char *kwlist[] = {"type", "min", "max", "x1", "x2", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iOOOOOO", kwlist, &self->type, &mintmp, &maxtmp, &x1tmp, &x2tmp, &multmp, &addtmp)) Py_RETURN_NONE; if (x1tmp) { PyObject_CallMethod((PyObject *)self, "setX1", "O", x1tmp); } if (x2tmp) { PyObject_CallMethod((PyObject *)self, "setX2", "O", x2tmp); } if (mintmp) { PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp); } if (maxtmp) { PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (self->modebuffer[2] == 0) mi = PyFloat_AS_DOUBLE(self->min); else mi = Stream_getData((Stream *)self->min_stream)[0]; if (self->modebuffer[3] == 0) ma = PyFloat_AS_DOUBLE(self->max); else ma = Stream_getData((Stream *)self->max_stream)[0]; self->value = (mi + ma) * 0.5; if (self->value == 0.0) self->inc = 0.0; else self->inc = (1.0 / self->value) / self->sr; XnoiseDur_setRandomType(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * XnoiseDur_getServer(XnoiseDur* self) { GET_SERVER }; static PyObject * XnoiseDur_getStream(XnoiseDur* self) { GET_STREAM }; static PyObject * XnoiseDur_setMul(XnoiseDur *self, PyObject *arg) { SET_MUL }; static PyObject * XnoiseDur_setAdd(XnoiseDur *self, PyObject *arg) { SET_ADD }; static PyObject * XnoiseDur_setSub(XnoiseDur *self, PyObject *arg) { SET_SUB }; static PyObject * XnoiseDur_setDiv(XnoiseDur *self, PyObject *arg) { SET_DIV }; static PyObject * XnoiseDur_play(XnoiseDur *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * XnoiseDur_out(XnoiseDur *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * XnoiseDur_stop(XnoiseDur *self) { STOP }; static PyObject * XnoiseDur_multiply(XnoiseDur *self, PyObject *arg) { MULTIPLY }; static PyObject * XnoiseDur_inplace_multiply(XnoiseDur *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * XnoiseDur_add(XnoiseDur *self, PyObject *arg) { ADD }; static PyObject * XnoiseDur_inplace_add(XnoiseDur *self, PyObject *arg) { INPLACE_ADD }; static PyObject * XnoiseDur_sub(XnoiseDur *self, PyObject *arg) { SUB }; static PyObject * XnoiseDur_inplace_sub(XnoiseDur *self, PyObject *arg) { INPLACE_SUB }; static PyObject * XnoiseDur_div(XnoiseDur *self, PyObject *arg) { DIV }; static PyObject * XnoiseDur_inplace_div(XnoiseDur *self, PyObject *arg) { INPLACE_DIV }; static PyObject * XnoiseDur_setType(XnoiseDur *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyInt_Check(arg); if (isNumber == 1) { self->type = PyInt_AsLong(arg); XnoiseDur_setRandomType(self); } Py_INCREF(Py_None); return Py_None; } static PyObject * XnoiseDur_setX1(XnoiseDur *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->x1); if (isNumber == 1) { self->x1 = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->x1 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->x1, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->x1_stream); self->x1_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * XnoiseDur_setX2(XnoiseDur *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->x2); if (isNumber == 1) { self->x2 = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->x2 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->x2, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->x2_stream); self->x2_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * XnoiseDur_setMin(XnoiseDur *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->min); if (isNumber == 1) { self->min = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->min = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->min, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->min_stream); self->min_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * XnoiseDur_setMax(XnoiseDur *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->max); if (isNumber == 1) { self->max = PyNumber_Float(tmp); self->modebuffer[5] = 0; } else { self->max = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->max_stream); self->max_stream = (Stream *)streamtmp; self->modebuffer[5] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef XnoiseDur_members[] = { {"server", T_OBJECT_EX, offsetof(XnoiseDur, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(XnoiseDur, stream), 0, "Stream object."}, {"x1", T_OBJECT_EX, offsetof(XnoiseDur, x1), 0, "first param."}, {"x2", T_OBJECT_EX, offsetof(XnoiseDur, x2), 0, "second param."}, {"min", T_OBJECT_EX, offsetof(XnoiseDur, min), 0, "Minimum value."}, {"max", T_OBJECT_EX, offsetof(XnoiseDur, max), 0, "Maximum value."}, {"mul", T_OBJECT_EX, offsetof(XnoiseDur, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(XnoiseDur, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef XnoiseDur_methods[] = { {"getServer", (PyCFunction)XnoiseDur_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)XnoiseDur_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)XnoiseDur_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)XnoiseDur_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)XnoiseDur_stop, METH_NOARGS, "Stops computing."}, {"setType", (PyCFunction)XnoiseDur_setType, METH_O, "Sets distribution type."}, {"setX1", (PyCFunction)XnoiseDur_setX1, METH_O, "Sets first param."}, {"setX2", (PyCFunction)XnoiseDur_setX2, METH_O, "Sets second param."}, {"setMin", (PyCFunction)XnoiseDur_setMin, METH_O, "Sets minimum value."}, {"setMax", (PyCFunction)XnoiseDur_setMax, METH_O, "Sets maximum value."}, {"setMul", (PyCFunction)XnoiseDur_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)XnoiseDur_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)XnoiseDur_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)XnoiseDur_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods XnoiseDur_as_number = { (binaryfunc)XnoiseDur_add, /*nb_add*/ (binaryfunc)XnoiseDur_sub, /*nb_subtract*/ (binaryfunc)XnoiseDur_multiply, /*nb_multiply*/ (binaryfunc)XnoiseDur_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)XnoiseDur_inplace_add, /*inplace_add*/ (binaryfunc)XnoiseDur_inplace_sub, /*inplace_subtract*/ (binaryfunc)XnoiseDur_inplace_multiply, /*inplace_multiply*/ (binaryfunc)XnoiseDur_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject XnoiseDurType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.XnoiseDur_base", /*tp_name*/ sizeof(XnoiseDur), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)XnoiseDur_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &XnoiseDur_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "XnoiseDur objects. Generates a random value and uses this value as time base for the next generation.", /* tp_doc */ (traverseproc)XnoiseDur_traverse, /* tp_traverse */ (inquiry)XnoiseDur_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ XnoiseDur_methods, /* tp_methods */ XnoiseDur_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ XnoiseDur_new, /* tp_new */ }; /****************/ /****** Urn *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *freq; Stream *freq_stream; int *list; int max; int length; int lastvalue; MYFLT value; MYFLT time; MYFLT *trigsBuffer; TriggerStream *trig_stream; int modebuffer[3]; // need at least 2 slots for mul & add } Urn; static void Urn_reset(Urn *self) { int i; self->lastvalue = (int)self->value; self->length = self->max; self->list = (int *)realloc(self->list, self->max * sizeof(int)); for (i=0; imax; i++) { self->list[i] = i; } } static int Urn_choose(Urn *self) { int x = 0; int value = 0; int i, pick; pick = rand() % self->length; while (pick == self->lastvalue) pick = rand() % self->length; for (i=0; ilength; i++) { if (i != pick) self->list[x++] = self->list[i]; else value = self->list[i]; } self->length = x; self->lastvalue = -1; return value; } static void Urn_generate_i(Urn *self) { int i; MYFLT fr = PyFloat_AS_DOUBLE(self->freq); MYFLT inc = fr / self->sr; for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = (MYFLT)Urn_choose(self); if (self->length == 0) { self->trigsBuffer[i] = 1.0; Urn_reset(self); } } self->data[i] = self->value; } } static void Urn_generate_a(Urn *self) { int i; MYFLT inc; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; inc = fr[i] / self->sr; self->time += inc; if (self->time < 0.0) self->time += 1.0; else if (self->time >= 1.0) { self->time -= 1.0; self->value = (MYFLT)Urn_choose(self); if (self->length == 0) { self->trigsBuffer[i] = 1.0; Urn_reset(self); } } self->data[i] = self->value; } } static void Urn_postprocessing_ii(Urn *self) { POST_PROCESSING_II }; static void Urn_postprocessing_ai(Urn *self) { POST_PROCESSING_AI }; static void Urn_postprocessing_ia(Urn *self) { POST_PROCESSING_IA }; static void Urn_postprocessing_aa(Urn *self) { POST_PROCESSING_AA }; static void Urn_postprocessing_ireva(Urn *self) { POST_PROCESSING_IREVA }; static void Urn_postprocessing_areva(Urn *self) { POST_PROCESSING_AREVA }; static void Urn_postprocessing_revai(Urn *self) { POST_PROCESSING_REVAI }; static void Urn_postprocessing_revaa(Urn *self) { POST_PROCESSING_REVAA }; static void Urn_postprocessing_revareva(Urn *self) { POST_PROCESSING_REVAREVA }; static void Urn_setProcMode(Urn *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Urn_generate_i; break; case 1: self->proc_func_ptr = Urn_generate_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Urn_postprocessing_ii; break; case 1: self->muladd_func_ptr = Urn_postprocessing_ai; break; case 2: self->muladd_func_ptr = Urn_postprocessing_revai; break; case 10: self->muladd_func_ptr = Urn_postprocessing_ia; break; case 11: self->muladd_func_ptr = Urn_postprocessing_aa; break; case 12: self->muladd_func_ptr = Urn_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Urn_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Urn_postprocessing_areva; break; case 22: self->muladd_func_ptr = Urn_postprocessing_revareva; break; } } static void Urn_compute_next_data_frame(Urn *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Urn_traverse(Urn *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->trig_stream); return 0; } static int Urn_clear(Urn *self) { pyo_CLEAR Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->trig_stream); return 0; } static void Urn_dealloc(Urn* self) { pyo_DEALLOC free(self->list); free(self->trigsBuffer); Urn_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Urn_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *freqtmp=NULL, *multmp=NULL, *addtmp=NULL; Urn *self; self = (Urn *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(1.); self->max = 100; self->length = 0; self->lastvalue = -1; self->value = 0.0; self->time = 1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Urn_compute_next_data_frame); self->mode_func_ptr = Urn_setProcMode; static char *kwlist[] = {"max", "freq", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iOOO", kwlist, &self->max, &freqtmp, &multmp, &addtmp)) Py_RETURN_NONE; if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); Urn_reset(self); Server_generateSeed((Server *)self->server, URN_ID); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Urn_getServer(Urn* self) { GET_SERVER }; static PyObject * Urn_getStream(Urn* self) { GET_STREAM }; static PyObject * Urn_getTriggerStream(Urn* self) { GET_TRIGGER_STREAM }; static PyObject * Urn_setMul(Urn *self, PyObject *arg) { SET_MUL }; static PyObject * Urn_setAdd(Urn *self, PyObject *arg) { SET_ADD }; static PyObject * Urn_setSub(Urn *self, PyObject *arg) { SET_SUB }; static PyObject * Urn_setDiv(Urn *self, PyObject *arg) { SET_DIV }; static PyObject * Urn_play(Urn *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Urn_out(Urn *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Urn_stop(Urn *self) { STOP }; static PyObject * Urn_multiply(Urn *self, PyObject *arg) { MULTIPLY }; static PyObject * Urn_inplace_multiply(Urn *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Urn_add(Urn *self, PyObject *arg) { ADD }; static PyObject * Urn_inplace_add(Urn *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Urn_sub(Urn *self, PyObject *arg) { SUB }; static PyObject * Urn_inplace_sub(Urn *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Urn_div(Urn *self, PyObject *arg) { DIV }; static PyObject * Urn_inplace_div(Urn *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Urn_setMax(Urn *self, PyObject *arg) { if (PyNumber_Check(arg) == 1) self->max = PyInt_AsLong(arg); Urn_reset(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Urn_setFreq(Urn *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Urn_members[] = { {"server", T_OBJECT_EX, offsetof(Urn, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Urn, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(Urn, trig_stream), 0, "Trigger Stream object."}, {"freq", T_OBJECT_EX, offsetof(Urn, freq), 0, "Polling frequency."}, {"mul", T_OBJECT_EX, offsetof(Urn, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Urn, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Urn_methods[] = { {"getServer", (PyCFunction)Urn_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Urn_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)Urn_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"play", (PyCFunction)Urn_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Urn_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Urn_stop, METH_NOARGS, "Stops computing."}, {"setMax", (PyCFunction)Urn_setMax, METH_O, "Sets maximum possible value."}, {"setFreq", (PyCFunction)Urn_setFreq, METH_O, "Sets polling frequency."}, {"setMul", (PyCFunction)Urn_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Urn_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Urn_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Urn_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Urn_as_number = { (binaryfunc)Urn_add, /*nb_add*/ (binaryfunc)Urn_sub, /*nb_subtract*/ (binaryfunc)Urn_multiply, /*nb_multiply*/ (binaryfunc)Urn_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Urn_inplace_add, /*inplace_add*/ (binaryfunc)Urn_inplace_sub, /*inplace_subtract*/ (binaryfunc)Urn_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Urn_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject UrnType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Urn_base", /*tp_name*/ sizeof(Urn), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Urn_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Urn_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Urn objects. Periodically generates a new integer random value without repetition.", /* tp_doc */ (traverseproc)Urn_traverse, /* tp_traverse */ (inquiry)Urn_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Urn_methods, /* tp_methods */ Urn_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Urn_new, /* tp_new */ };pyo/src/objects/bandsplitmodule.c0000644000175000017500000013541612652732202016442 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *q; Stream *q_stream; int bands; MYFLT min_freq; MYFLT max_freq; int init; MYFLT halfSr; MYFLT TwoPiOnSr; MYFLT *band_freqs; // sample memories MYFLT *x1; MYFLT *x2; MYFLT *y1; MYFLT *y2; // coefficients MYFLT *b0; MYFLT *b2; MYFLT *a0; MYFLT *a1; MYFLT *a2; MYFLT *buffer_streams; int modebuffer[1]; } BandSplitter; static void BandSplitter_compute_variables(BandSplitter *self, MYFLT q) { int i; MYFLT freq; for (i=0; ibands; i++) { freq = self->band_freqs[i]; if (freq <= 1) freq = 1; else if (freq >= self->halfSr) freq = self->halfSr; MYFLT w0 = self->TwoPiOnSr * freq; MYFLT c = MYCOS(w0); MYFLT alpha = MYSIN(w0) / (2 * q); self->b0[i] = alpha; self->b2[i] = -alpha; self->a0[i] = 1 + alpha; self->a1[i] = -2 * c; self->a2[i] = 1 - alpha; } } static void BandSplitter_setFrequencies(BandSplitter *self) { int i; MYFLT frac = 1. / self->bands; for (i=0; ibands; i++) { self->band_freqs[i] = MYPOW(MYPOW(self->max_freq/self->min_freq, frac), i) * self->min_freq; } } static void BandSplitter_filters_i(BandSplitter *self) { MYFLT val; int j, i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { for (j=0; jbands; j++) { self->x1[j] = self->x2[j] = self->y1[j] = self->y2[j] = in[0]; } self->init = 0; } for (j=0; jbands; j++) { for (i=0; ibufsize; i++) { val = ( (self->b0[j] * in[i]) + (self->b2[j] * self->x2[j]) - (self->a1[j] * self->y1[j]) - (self->a2[j] * self->y2[j]) ) / self->a0[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; self->x2[j] = self->x1[j]; self->x1[j] = in[i]; self->buffer_streams[i + j * self->bufsize] = val; } } } static void BandSplitter_filters_a(BandSplitter *self) { MYFLT val; int j, i; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->init == 1) { for (j=0; jbands; j++) { self->x1[j] = self->x2[j] = self->y1[j] = self->y2[j] = in[0]; } self->init = 0; } MYFLT *q = Stream_getData((Stream *)self->q_stream); for (i=0; ibufsize; i++) { BandSplitter_compute_variables((BandSplitter *)self, q[i]); for (j=0; jbands; j++) { val = ( (self->b0[j] * in[i]) + (self->b2[j] * self->x2[j]) - (self->a1[j] * self->y1[j]) - (self->a2[j] * self->y2[j]) ) / self->a0[j]; self->y2[j] = self->y1[j]; self->y1[j] = val; self->x2[j] = self->x1[j]; self->x1[j] = in[i]; self->buffer_streams[i + j * self->bufsize] = val; } } } MYFLT * BandSplitter_getSamplesBuffer(BandSplitter *self) { return (MYFLT *)self->buffer_streams; } static void BandSplitter_setProcMode(BandSplitter *self) { int procmode; procmode = self->modebuffer[0]; switch (procmode) { case 0: self->proc_func_ptr = BandSplitter_filters_i; break; case 1: self->proc_func_ptr = BandSplitter_filters_a; break; } } static void BandSplitter_compute_next_data_frame(BandSplitter *self) { (*self->proc_func_ptr)(self); } static int BandSplitter_traverse(BandSplitter *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->q); Py_VISIT(self->q_stream); return 0; } static int BandSplitter_clear(BandSplitter *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->q); Py_CLEAR(self->q_stream); return 0; } static void BandSplitter_dealloc(BandSplitter* self) { pyo_DEALLOC free(self->band_freqs); free(self->x1); free(self->x2); free(self->y1); free(self->y2); free(self->b0); free(self->b2); free(self->a0); free(self->a1); free(self->a2); free(self->buffer_streams); BandSplitter_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * BandSplitter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *qtmp=NULL; BandSplitter *self; self = (BandSplitter *)type->tp_alloc(type, 0); self->bands = 4; self->q = PyFloat_FromDouble(1.); self->init = 1; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, BandSplitter_compute_next_data_frame); self->mode_func_ptr = BandSplitter_setProcMode; self->halfSr = self->sr / 2.; self->TwoPiOnSr = TWOPI / self->sr; static char *kwlist[] = {"input", "bands", "min", "max", "q", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_IFFO, kwlist, &inputtmp, &self->bands, &self->min_freq, &self->max_freq, &qtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->band_freqs = (MYFLT *)realloc(self->band_freqs, self->bands * sizeof(MYFLT)); self->x1 = (MYFLT *)realloc(self->x1, self->bands * sizeof(MYFLT)); self->x2 = (MYFLT *)realloc(self->x2, self->bands * sizeof(MYFLT)); self->y1 = (MYFLT *)realloc(self->y1, self->bands * sizeof(MYFLT)); self->y2 = (MYFLT *)realloc(self->y2, self->bands * sizeof(MYFLT)); self->b0 = (MYFLT *)realloc(self->b0, self->bands * sizeof(MYFLT)); self->b2 = (MYFLT *)realloc(self->b2, self->bands * sizeof(MYFLT)); self->a0 = (MYFLT *)realloc(self->a0, self->bands * sizeof(MYFLT)); self->a1 = (MYFLT *)realloc(self->a1, self->bands * sizeof(MYFLT)); self->a2 = (MYFLT *)realloc(self->a2, self->bands * sizeof(MYFLT)); self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->bands * self->bufsize * sizeof(MYFLT)); BandSplitter_setFrequencies((BandSplitter *)self); if (qtmp) { PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp); } else { BandSplitter_compute_variables((BandSplitter *)self, PyFloat_AS_DOUBLE(self->q)); } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * BandSplitter_setQ(BandSplitter *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->q); if (isNumber == 1) { self->q = PyNumber_Float(tmp); self->modebuffer[0] = 0; BandSplitter_compute_variables((BandSplitter *)self, PyFloat_AS_DOUBLE(self->q)); } else { self->q = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->q, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->q_stream); self->q_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * BandSplitter_getServer(BandSplitter* self) { GET_SERVER }; static PyObject * BandSplitter_getStream(BandSplitter* self) { GET_STREAM }; static PyObject * BandSplitter_play(BandSplitter *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * BandSplitter_stop(BandSplitter *self) { STOP }; static PyMemberDef BandSplitter_members[] = { {"server", T_OBJECT_EX, offsetof(BandSplitter, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(BandSplitter, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(BandSplitter, input), 0, "Input sound object."}, {"q", T_OBJECT_EX, offsetof(BandSplitter, q), 0, "Filters Q."}, {NULL} /* Sentinel */ }; static PyMethodDef BandSplitter_methods[] = { {"getServer", (PyCFunction)BandSplitter_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)BandSplitter_getStream, METH_NOARGS, "Returns stream object."}, {"setQ", (PyCFunction)BandSplitter_setQ, METH_O, "Sets the filters Q."}, {"play", (PyCFunction)BandSplitter_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)BandSplitter_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject BandSplitterType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.BandSplitter_base", /*tp_name*/ sizeof(BandSplitter), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)BandSplitter_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "BandSplitter objects. Split audio stream in multiple frequency bands.", /* tp_doc */ (traverseproc)BandSplitter_traverse, /* tp_traverse */ (inquiry)BandSplitter_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ BandSplitter_methods, /* tp_methods */ BandSplitter_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ BandSplitter_new, /* tp_new */ }; /************************************************************************************************/ /* BandSplit streamer object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD BandSplitter *mainSplitter; int modebuffer[2]; int chnl; } BandSplit; static void BandSplit_postprocessing_ii(BandSplit *self) { POST_PROCESSING_II }; static void BandSplit_postprocessing_ai(BandSplit *self) { POST_PROCESSING_AI }; static void BandSplit_postprocessing_ia(BandSplit *self) { POST_PROCESSING_IA }; static void BandSplit_postprocessing_aa(BandSplit *self) { POST_PROCESSING_AA }; static void BandSplit_postprocessing_ireva(BandSplit *self) { POST_PROCESSING_IREVA }; static void BandSplit_postprocessing_areva(BandSplit *self) { POST_PROCESSING_AREVA }; static void BandSplit_postprocessing_revai(BandSplit *self) { POST_PROCESSING_REVAI }; static void BandSplit_postprocessing_revaa(BandSplit *self) { POST_PROCESSING_REVAA }; static void BandSplit_postprocessing_revareva(BandSplit *self) { POST_PROCESSING_REVAREVA }; static void BandSplit_setProcMode(BandSplit *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = BandSplit_postprocessing_ii; break; case 1: self->muladd_func_ptr = BandSplit_postprocessing_ai; break; case 2: self->muladd_func_ptr = BandSplit_postprocessing_revai; break; case 10: self->muladd_func_ptr = BandSplit_postprocessing_ia; break; case 11: self->muladd_func_ptr = BandSplit_postprocessing_aa; break; case 12: self->muladd_func_ptr = BandSplit_postprocessing_revaa; break; case 20: self->muladd_func_ptr = BandSplit_postprocessing_ireva; break; case 21: self->muladd_func_ptr = BandSplit_postprocessing_areva; break; case 22: self->muladd_func_ptr = BandSplit_postprocessing_revareva; break; } } static void BandSplit_compute_next_data_frame(BandSplit *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = BandSplitter_getSamplesBuffer((BandSplitter *)self->mainSplitter); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int BandSplit_traverse(BandSplit *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainSplitter); return 0; } static int BandSplit_clear(BandSplit *self) { pyo_CLEAR Py_CLEAR(self->mainSplitter); return 0; } static void BandSplit_dealloc(BandSplit* self) { pyo_DEALLOC BandSplit_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * BandSplit_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; BandSplit *self; self = (BandSplit *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, BandSplit_compute_next_data_frame); self->mode_func_ptr = BandSplit_setProcMode; static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainSplitter); Py_INCREF(maintmp); self->mainSplitter = (BandSplitter *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * BandSplit_getServer(BandSplit* self) { GET_SERVER }; static PyObject * BandSplit_getStream(BandSplit* self) { GET_STREAM }; static PyObject * BandSplit_setMul(BandSplit *self, PyObject *arg) { SET_MUL }; static PyObject * BandSplit_setAdd(BandSplit *self, PyObject *arg) { SET_ADD }; static PyObject * BandSplit_setSub(BandSplit *self, PyObject *arg) { SET_SUB }; static PyObject * BandSplit_setDiv(BandSplit *self, PyObject *arg) { SET_DIV }; static PyObject * BandSplit_play(BandSplit *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * BandSplit_out(BandSplit *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * BandSplit_stop(BandSplit *self) { STOP }; static PyObject * BandSplit_multiply(BandSplit *self, PyObject *arg) { MULTIPLY }; static PyObject * BandSplit_inplace_multiply(BandSplit *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * BandSplit_add(BandSplit *self, PyObject *arg) { ADD }; static PyObject * BandSplit_inplace_add(BandSplit *self, PyObject *arg) { INPLACE_ADD }; static PyObject * BandSplit_sub(BandSplit *self, PyObject *arg) { SUB }; static PyObject * BandSplit_inplace_sub(BandSplit *self, PyObject *arg) { INPLACE_SUB }; static PyObject * BandSplit_div(BandSplit *self, PyObject *arg) { DIV }; static PyObject * BandSplit_inplace_div(BandSplit *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef BandSplit_members[] = { {"server", T_OBJECT_EX, offsetof(BandSplit, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(BandSplit, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(BandSplit, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(BandSplit, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef BandSplit_methods[] = { {"getServer", (PyCFunction)BandSplit_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)BandSplit_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)BandSplit_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)BandSplit_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)BandSplit_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)BandSplit_setMul, METH_O, "Sets BandSplit mul factor."}, {"setAdd", (PyCFunction)BandSplit_setAdd, METH_O, "Sets BandSplit add factor."}, {"setSub", (PyCFunction)BandSplit_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)BandSplit_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods BandSplit_as_number = { (binaryfunc)BandSplit_add, /*nb_add*/ (binaryfunc)BandSplit_sub, /*nb_subtract*/ (binaryfunc)BandSplit_multiply, /*nb_multiply*/ (binaryfunc)BandSplit_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)BandSplit_inplace_add, /*inplace_add*/ (binaryfunc)BandSplit_inplace_sub, /*inplace_subtract*/ (binaryfunc)BandSplit_inplace_multiply, /*inplace_multiply*/ (binaryfunc)BandSplit_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject BandSplitType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.BandSplit_base", /*tp_name*/ sizeof(BandSplit), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)BandSplit_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &BandSplit_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "BandSplit objects. Reads one band from a BandSplitter process.", /* tp_doc */ (traverseproc)BandSplit_traverse, /* tp_traverse */ (inquiry)BandSplit_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ BandSplit_methods, /* tp_methods */ BandSplit_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ BandSplit_new, /* tp_new */ }; /*****************/ /* FourBand main */ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq1; Stream *freq1_stream; PyObject *freq2; Stream *freq2_stream; PyObject *freq3; Stream *freq3_stream; double last_freq1; double last_freq2; double last_freq3; // sample memories double x1[6]; double x2[6]; double x3[6]; double x4[6]; double y1[6]; double y2[6]; double y3[6]; double y4[6]; // coefficients double b1[3]; double b2[3]; double b3[3]; double b4[3]; double la0[3]; double la1[3]; double la2[3]; double ha0[3]; double ha1[3]; double ha2[3]; MYFLT *buffer_streams; int modebuffer[3]; } FourBandMain; static void FourBandMain_compute_variables(FourBandMain *self, double freq, int band) { double wc = TWOPI * freq; double wc2 = wc * wc; double wc3 = wc2 * wc; double wc4 = wc2 * wc2; double k = wc / tan(PI * freq / self->sr); double k2 = k * k; double k3 = k2 * k; double k4 = k2 * k2; double sqrt2 = sqrt(2.0); double sq_tmp1 = sqrt2 * wc3 * k; double sq_tmp2 = sqrt2 * wc * k3; double a_tmp = 4.0 * wc2 * k2 + 2.0 * sq_tmp1 + k4 + 2.0 * sq_tmp2 + wc4; double wc4_a_tmp = wc4 / a_tmp; double k4_a_tmp = k4 / a_tmp; /* common */ self->b1[band] = (4.0 * (wc4 + sq_tmp1 - k4 - sq_tmp2)) / a_tmp; self->b2[band] = (6.0 * wc4 - 8.0 * wc2 * k2 + 6.0 * k4) / a_tmp; self->b3[band] = (4.0 * (wc4 - sq_tmp1 + sq_tmp2 - k4)) / a_tmp; self->b4[band] = (k4 - 2.0 * sq_tmp1 + wc4 - 2.0 * sq_tmp2 + 4.0 * wc2 * k2) / a_tmp; /* lowpass */ self->la0[band] = wc4_a_tmp; self->la1[band] = 4.0 * wc4_a_tmp; self->la2[band] = 6.0 * wc4_a_tmp; /* highpass */ self->ha0[band] = k4_a_tmp; self->ha1[band] = -4.0 * k4_a_tmp; self->ha2[band] = 6.0 * k4_a_tmp; } static void FourBandMain_filters(FourBandMain *self) { double val, inval, tmp, f1, f2, f3; int i, j, j1, ind, ind1; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->modebuffer[0] == 0) f1 = PyFloat_AS_DOUBLE(self->freq1); else f1 = (double)Stream_getData((Stream *)self->freq1_stream)[0]; if (self->modebuffer[1] == 0) f2 = PyFloat_AS_DOUBLE(self->freq2); else f2 = (double)Stream_getData((Stream *)self->freq2_stream)[0]; if (self->modebuffer[2] == 0) f3 = PyFloat_AS_DOUBLE(self->freq3); else f3 = (double)Stream_getData((Stream *)self->freq3_stream)[0]; if (f1 != self->last_freq1) { self->last_freq1 = f1; FourBandMain_compute_variables(self, f1, 0); } if (f2 != self->last_freq2) { self->last_freq2 = f2; FourBandMain_compute_variables(self, f2, 1); } if (f3 != self->last_freq3) { self->last_freq3 = f3; FourBandMain_compute_variables(self, f3, 2); } for (i=0; ibufsize; i++) { inval = (double)in[i]; /* First band */ val = self->la0[0] * inval + self->la1[0] * self->x1[0] + self->la2[0] * self->x2[0] + self->la1[0] * self->x3[0] + self->la0[0] * self->x4[0] - self->b1[0] * self->y1[0] - self->b2[0] * self->y2[0] - self->b3[0] * self->y3[0] - self->b4[0] * self->y4[0]; self->y4[0] = self->y3[0]; self->y3[0] = self->y2[0]; self->y2[0] = self->y1[0]; self->y1[0] = val; self->x4[0] = self->x3[0]; self->x3[0] = self->x2[0]; self->x2[0] = self->x1[0]; self->x1[0] = inval; self->buffer_streams[i] = (MYFLT)val; /* Second and third bands */ for (j=0; j<2; j++) { j1 = j + 1; ind = j * 2 + 1; ind1 = ind + 1; tmp = self->ha0[j] * inval + self->ha1[j] * self->x1[ind] + self->ha2[j] * self->x2[ind] + self->ha1[j] * self->x3[ind] + self->ha0[j] * self->x4[ind] - self->b1[j] * self->y1[ind] - self->b2[j] * self->y2[ind] - self->b3[j] * self->y3[ind] - self->b4[j] * self->y4[ind]; self->y4[ind] = self->y3[ind]; self->y3[ind] = self->y2[ind]; self->y2[ind] = self->y1[ind]; self->y1[ind] = tmp; self->x4[ind] = self->x3[ind]; self->x3[ind] = self->x2[ind]; self->x2[ind] = self->x1[ind]; self->x1[ind] = inval; val = self->la0[j1] * tmp + self->la1[j1] * self->x1[ind1] + self->la2[j1] * self->x2[ind1] + self->la1[j1] * self->x3[ind1] + self->la0[j1] * self->x4[ind1] - self->b1[j1] * self->y1[ind1] - self->b2[j1] * self->y2[ind1] - self->b3[j1] * self->y3[ind1] - self->b4[j1] * self->y4[ind1]; self->y4[ind1] = self->y3[ind1]; self->y3[ind1] = self->y2[ind1]; self->y2[ind1] = self->y1[ind1]; self->y1[ind1] = val; self->x4[ind1] = self->x3[ind1]; self->x3[ind1] = self->x2[ind1]; self->x2[ind1] = self->x1[ind1]; self->x1[ind1] = tmp; self->buffer_streams[i + j1 * self->bufsize] = (MYFLT)val; } val = self->ha0[2] * inval + self->ha1[2] * self->x1[5] + self->ha2[2] * self->x2[5] + self->ha1[2] * self->x3[5] + self->ha0[2] * self->x4[5] - self->b1[2] * self->y1[5] - self->b2[2] * self->y2[5] - self->b3[2] * self->y3[5] - self->b4[2] * self->y4[5]; self->y4[5] = self->y3[5]; self->y3[5] = self->y2[5]; self->y2[5] = self->y1[5]; self->y1[5] = val; self->x4[5] = self->x3[5]; self->x3[5] = self->x2[5]; self->x2[5] = self->x1[5]; self->x1[5] = inval; self->buffer_streams[i + 3 * self->bufsize] = (MYFLT)val; } } MYFLT * FourBandMain_getSamplesBuffer(FourBandMain *self) { return (MYFLT *)self->buffer_streams; } static void FourBandMain_setProcMode(FourBandMain *self) { self->proc_func_ptr = FourBandMain_filters; } static void FourBandMain_compute_next_data_frame(FourBandMain *self) { (*self->proc_func_ptr)(self); } static int FourBandMain_traverse(FourBandMain *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq1); Py_VISIT(self->freq1_stream); Py_VISIT(self->freq2); Py_VISIT(self->freq2_stream); Py_VISIT(self->freq3); Py_VISIT(self->freq3_stream); return 0; } static int FourBandMain_clear(FourBandMain *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq1); Py_CLEAR(self->freq1_stream); Py_CLEAR(self->freq2); Py_CLEAR(self->freq2_stream); Py_CLEAR(self->freq3); Py_CLEAR(self->freq3_stream); return 0; } static void FourBandMain_dealloc(FourBandMain* self) { pyo_DEALLOC free(self->buffer_streams); FourBandMain_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * FourBandMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freq1tmp=NULL, *freq2tmp=NULL, *freq3tmp=NULL; FourBandMain *self; self = (FourBandMain *)type->tp_alloc(type, 0); self->freq1 = PyFloat_FromDouble(150); self->freq2 = PyFloat_FromDouble(500); self->freq3 = PyFloat_FromDouble(2000); self->last_freq1 = self->last_freq2 = self->last_freq3 = -1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, FourBandMain_compute_next_data_frame); self->mode_func_ptr = FourBandMain_setProcMode; static char *kwlist[] = {"input", "freq1", "freq2", "freq3", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &freq1tmp, &freq2tmp, &freq3tmp)) Py_RETURN_NONE; INIT_INPUT_STREAM PyObject_CallMethod(self->server, "addStream", "O", self->stream); for (i=0; i<6; i++) { self->x1[i] = self->x2[i] = self->x3[i] = self->x4[i] = self->y1[i] = self->y2[i] = self->y3[i] = self->y4[i] = 0.0; } self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, 4 * self->bufsize * sizeof(MYFLT)); for (i=0; i<(4 * self->bufsize); i++) { self->buffer_streams[i] = 0.0; } if (freq1tmp) { PyObject_CallMethod((PyObject *)self, "setFreq1", "O", freq1tmp); } if (freq2tmp) { PyObject_CallMethod((PyObject *)self, "setFreq2", "O", freq2tmp); } if (freq3tmp) { PyObject_CallMethod((PyObject *)self, "setFreq3", "O", freq3tmp); } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * FourBandMain_setFreq1(FourBandMain *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq1); if (isNumber == 1) { self->freq1 = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->freq1 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq1, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq1_stream); self->freq1_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * FourBandMain_setFreq2(FourBandMain *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq2); if (isNumber == 1) { self->freq2 = PyNumber_Float(tmp); self->modebuffer[1] = 0; } else { self->freq2 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq2, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq2_stream); self->freq2_stream = (Stream *)streamtmp; self->modebuffer[1] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * FourBandMain_setFreq3(FourBandMain *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq3); if (isNumber == 1) { self->freq3 = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq3 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq3, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq3_stream); self->freq3_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * FourBandMain_getServer(FourBandMain* self) { GET_SERVER }; static PyObject * FourBandMain_getStream(FourBandMain* self) { GET_STREAM }; static PyObject * FourBandMain_play(FourBandMain *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * FourBandMain_stop(FourBandMain *self) { STOP }; static PyMemberDef FourBandMain_members[] = { {"server", T_OBJECT_EX, offsetof(FourBandMain, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(FourBandMain, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(FourBandMain, input), 0, "Input sound object."}, {"freq1", T_OBJECT_EX, offsetof(FourBandMain, freq1), 0, "First cutoff frequency."}, {"freq2", T_OBJECT_EX, offsetof(FourBandMain, freq2), 0, "Second cutoff frequency."}, {"freq3", T_OBJECT_EX, offsetof(FourBandMain, freq3), 0, "Third cutoff frequency."}, {NULL} /* Sentinel */ }; static PyMethodDef FourBandMain_methods[] = { {"getServer", (PyCFunction)FourBandMain_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)FourBandMain_getStream, METH_NOARGS, "Returns stream object."}, {"setFreq1", (PyCFunction)FourBandMain_setFreq1, METH_O, "Sets the first cutoff frequency."}, {"setFreq2", (PyCFunction)FourBandMain_setFreq2, METH_O, "Sets the second cutoff frequency."}, {"setFreq3", (PyCFunction)FourBandMain_setFreq3, METH_O, "Sets the third cutoff frequency."}, {"play", (PyCFunction)FourBandMain_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)FourBandMain_stop, METH_NOARGS, "Stops computing."}, {NULL} /* Sentinel */ }; PyTypeObject FourBandMainType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.FourBandMain_base", /*tp_name*/ sizeof(FourBandMain), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)FourBandMain_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "FourBandMain objects. Split audio stream in four flat frequency and phase bands.", /* tp_doc */ (traverseproc)FourBandMain_traverse, /* tp_traverse */ (inquiry)FourBandMain_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ FourBandMain_methods, /* tp_methods */ FourBandMain_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ FourBandMain_new, /* tp_new */ }; /************************************************************************************************/ /* FourBand streamer object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD FourBandMain *mainSplitter; int modebuffer[2]; int chnl; } FourBand; static void FourBand_postprocessing_ii(FourBand *self) { POST_PROCESSING_II }; static void FourBand_postprocessing_ai(FourBand *self) { POST_PROCESSING_AI }; static void FourBand_postprocessing_ia(FourBand *self) { POST_PROCESSING_IA }; static void FourBand_postprocessing_aa(FourBand *self) { POST_PROCESSING_AA }; static void FourBand_postprocessing_ireva(FourBand *self) { POST_PROCESSING_IREVA }; static void FourBand_postprocessing_areva(FourBand *self) { POST_PROCESSING_AREVA }; static void FourBand_postprocessing_revai(FourBand *self) { POST_PROCESSING_REVAI }; static void FourBand_postprocessing_revaa(FourBand *self) { POST_PROCESSING_REVAA }; static void FourBand_postprocessing_revareva(FourBand *self) { POST_PROCESSING_REVAREVA }; static void FourBand_setProcMode(FourBand *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = FourBand_postprocessing_ii; break; case 1: self->muladd_func_ptr = FourBand_postprocessing_ai; break; case 2: self->muladd_func_ptr = FourBand_postprocessing_revai; break; case 10: self->muladd_func_ptr = FourBand_postprocessing_ia; break; case 11: self->muladd_func_ptr = FourBand_postprocessing_aa; break; case 12: self->muladd_func_ptr = FourBand_postprocessing_revaa; break; case 20: self->muladd_func_ptr = FourBand_postprocessing_ireva; break; case 21: self->muladd_func_ptr = FourBand_postprocessing_areva; break; case 22: self->muladd_func_ptr = FourBand_postprocessing_revareva; break; } } static void FourBand_compute_next_data_frame(FourBand *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = FourBandMain_getSamplesBuffer((FourBandMain *)self->mainSplitter); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int FourBand_traverse(FourBand *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainSplitter); return 0; } static int FourBand_clear(FourBand *self) { pyo_CLEAR Py_CLEAR(self->mainSplitter); return 0; } static void FourBand_dealloc(FourBand* self) { pyo_DEALLOC FourBand_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * FourBand_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; FourBand *self; self = (FourBand *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, FourBand_compute_next_data_frame); self->mode_func_ptr = FourBand_setProcMode; static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainSplitter); Py_INCREF(maintmp); self->mainSplitter = (FourBandMain *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * FourBand_getServer(FourBand* self) { GET_SERVER }; static PyObject * FourBand_getStream(FourBand* self) { GET_STREAM }; static PyObject * FourBand_setMul(FourBand *self, PyObject *arg) { SET_MUL }; static PyObject * FourBand_setAdd(FourBand *self, PyObject *arg) { SET_ADD }; static PyObject * FourBand_setSub(FourBand *self, PyObject *arg) { SET_SUB }; static PyObject * FourBand_setDiv(FourBand *self, PyObject *arg) { SET_DIV }; static PyObject * FourBand_play(FourBand *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * FourBand_out(FourBand *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * FourBand_stop(FourBand *self) { STOP }; static PyObject * FourBand_multiply(FourBand *self, PyObject *arg) { MULTIPLY }; static PyObject * FourBand_inplace_multiply(FourBand *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * FourBand_add(FourBand *self, PyObject *arg) { ADD }; static PyObject * FourBand_inplace_add(FourBand *self, PyObject *arg) { INPLACE_ADD }; static PyObject * FourBand_sub(FourBand *self, PyObject *arg) { SUB }; static PyObject * FourBand_inplace_sub(FourBand *self, PyObject *arg) { INPLACE_SUB }; static PyObject * FourBand_div(FourBand *self, PyObject *arg) { DIV }; static PyObject * FourBand_inplace_div(FourBand *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef FourBand_members[] = { {"server", T_OBJECT_EX, offsetof(FourBand, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(FourBand, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(FourBand, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(FourBand, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef FourBand_methods[] = { {"getServer", (PyCFunction)FourBand_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)FourBand_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)FourBand_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)FourBand_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)FourBand_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)FourBand_setMul, METH_O, "Sets FourBand mul factor."}, {"setAdd", (PyCFunction)FourBand_setAdd, METH_O, "Sets FourBand add factor."}, {"setSub", (PyCFunction)FourBand_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)FourBand_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods FourBand_as_number = { (binaryfunc)FourBand_add, /*nb_add*/ (binaryfunc)FourBand_sub, /*nb_subtract*/ (binaryfunc)FourBand_multiply, /*nb_multiply*/ (binaryfunc)FourBand_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)FourBand_inplace_add, /*inplace_add*/ (binaryfunc)FourBand_inplace_sub, /*inplace_subtract*/ (binaryfunc)FourBand_inplace_multiply, /*inplace_multiply*/ (binaryfunc)FourBand_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject FourBandType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.FourBand_base", /*tp_name*/ sizeof(FourBand), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)FourBand_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &FourBand_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "FourBand objects. Reads one band from a FourBandMain process.", /* tp_doc */ (traverseproc)FourBand_traverse, /* tp_traverse */ (inquiry)FourBand_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ FourBand_methods, /* tp_methods */ FourBand_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ FourBand_new, /* tp_new */ };pyo/src/objects/analysismodule.c0000644000175000017500000033434312652732202016305 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "interpolation.h" #include "fft.h" #include "wind.h" /************/ /* Follower */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *freq; Stream *freq_stream; int modebuffer[3]; // need at least 2 slots for mul & add MYFLT follow; MYFLT last_freq; MYFLT factor; } Follower; static void Follower_filters_i(Follower *self) { MYFLT absin, freq; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); freq = PyFloat_AS_DOUBLE(self->freq); if (freq != self->last_freq) { if (freq < 0) freq = 0.0; self->factor = MYEXP(-TWOPI * freq / self->sr); self->last_freq = freq; } for (i=0; ibufsize; i++) { absin = in[i]; if (absin < 0.0) absin = -absin; self->follow = self->data[i] = absin + self->factor * (self->follow - absin); } } static void Follower_filters_a(Follower *self) { MYFLT freq, absin; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { freq = fr[i]; if (freq != self->last_freq) { if (freq < 0) freq = 0.0; self->factor = MYEXP(-TWOPI * freq / self->sr); self->last_freq = freq; } absin = in[i]; if (absin < 0.0) absin = -absin; self->follow = self->data[i] = absin + self->factor * (self->follow - absin); } } static void Follower_postprocessing_ii(Follower *self) { POST_PROCESSING_II }; static void Follower_postprocessing_ai(Follower *self) { POST_PROCESSING_AI }; static void Follower_postprocessing_ia(Follower *self) { POST_PROCESSING_IA }; static void Follower_postprocessing_aa(Follower *self) { POST_PROCESSING_AA }; static void Follower_postprocessing_ireva(Follower *self) { POST_PROCESSING_IREVA }; static void Follower_postprocessing_areva(Follower *self) { POST_PROCESSING_AREVA }; static void Follower_postprocessing_revai(Follower *self) { POST_PROCESSING_REVAI }; static void Follower_postprocessing_revaa(Follower *self) { POST_PROCESSING_REVAA }; static void Follower_postprocessing_revareva(Follower *self) { POST_PROCESSING_REVAREVA }; static void Follower_setProcMode(Follower *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Follower_filters_i; break; case 1: self->proc_func_ptr = Follower_filters_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Follower_postprocessing_ii; break; case 1: self->muladd_func_ptr = Follower_postprocessing_ai; break; case 2: self->muladd_func_ptr = Follower_postprocessing_revai; break; case 10: self->muladd_func_ptr = Follower_postprocessing_ia; break; case 11: self->muladd_func_ptr = Follower_postprocessing_aa; break; case 12: self->muladd_func_ptr = Follower_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Follower_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Follower_postprocessing_areva; break; case 22: self->muladd_func_ptr = Follower_postprocessing_revareva; break; } } static void Follower_compute_next_data_frame(Follower *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Follower_traverse(Follower *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); return 0; } static int Follower_clear(Follower *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); return 0; } static void Follower_dealloc(Follower* self) { pyo_DEALLOC Follower_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Follower_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL; Follower *self; self = (Follower *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(20); self->follow = 0.0; self->last_freq = -1.0; self->factor = 0.99; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Follower_compute_next_data_frame); self->mode_func_ptr = Follower_setProcMode; static char *kwlist[] = {"input", "freq", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &freqtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Follower_getServer(Follower* self) { GET_SERVER }; static PyObject * Follower_getStream(Follower* self) { GET_STREAM }; static PyObject * Follower_setMul(Follower *self, PyObject *arg) { SET_MUL }; static PyObject * Follower_setAdd(Follower *self, PyObject *arg) { SET_ADD }; static PyObject * Follower_setSub(Follower *self, PyObject *arg) { SET_SUB }; static PyObject * Follower_setDiv(Follower *self, PyObject *arg) { SET_DIV }; static PyObject * Follower_play(Follower *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Follower_stop(Follower *self) { STOP }; static PyObject * Follower_multiply(Follower *self, PyObject *arg) { MULTIPLY }; static PyObject * Follower_inplace_multiply(Follower *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Follower_add(Follower *self, PyObject *arg) { ADD }; static PyObject * Follower_inplace_add(Follower *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Follower_sub(Follower *self, PyObject *arg) { SUB }; static PyObject * Follower_inplace_sub(Follower *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Follower_div(Follower *self, PyObject *arg) { DIV }; static PyObject * Follower_inplace_div(Follower *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Follower_setFreq(Follower *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Follower_members[] = { {"server", T_OBJECT_EX, offsetof(Follower, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Follower, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Follower, input), 0, "Input sound object."}, {"freq", T_OBJECT_EX, offsetof(Follower, freq), 0, "Cutoff frequency in cycle per second."}, {"mul", T_OBJECT_EX, offsetof(Follower, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Follower, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Follower_methods[] = { {"getServer", (PyCFunction)Follower_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Follower_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Follower_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Follower_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Follower_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setMul", (PyCFunction)Follower_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Follower_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Follower_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Follower_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Follower_as_number = { (binaryfunc)Follower_add, /*nb_add*/ (binaryfunc)Follower_sub, /*nb_subtract*/ (binaryfunc)Follower_multiply, /*nb_multiply*/ (binaryfunc)Follower_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Follower_inplace_add, /*inplace_add*/ (binaryfunc)Follower_inplace_sub, /*inplace_subtract*/ (binaryfunc)Follower_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Follower_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject FollowerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Follower_base", /*tp_name*/ sizeof(Follower), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Follower_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Follower_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Follower objects. Envelope follower.", /* tp_doc */ (traverseproc)Follower_traverse, /* tp_traverse */ (inquiry)Follower_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Follower_methods, /* tp_methods */ Follower_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Follower_new, /* tp_new */ }; /************/ /* Follower2 */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *risetime; Stream *risetime_stream; PyObject *falltime; Stream *falltime_stream; int modebuffer[4]; // need at least 2 slots for mul & add MYFLT follow; MYFLT last_risetime; MYFLT last_falltime; MYFLT risefactor; MYFLT fallfactor; } Follower2; static void Follower2_filters_ii(Follower2 *self) { MYFLT absin, risetime, falltime; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); risetime = PyFloat_AS_DOUBLE(self->risetime); if (risetime <= 0.0) risetime = 0.000001; falltime = PyFloat_AS_DOUBLE(self->falltime); if (falltime <= 0.0) falltime = 0.000001; if (risetime != self->last_risetime) { self->risefactor = MYEXP(-TWOPI * (1.0 / risetime) / self->sr); self->last_risetime = risetime; } if (falltime != self->last_falltime) { self->fallfactor = MYEXP(-TWOPI * (1.0 / falltime) / self->sr); self->last_falltime = falltime; } for (i=0; ibufsize; i++) { absin = in[i]; if (absin < 0.0) absin = -absin; if (self->follow < absin) self->follow = self->data[i] = absin + self->risefactor * (self->follow - absin); else self->follow = self->data[i] = absin + self->fallfactor * (self->follow - absin); } } static void Follower2_filters_ai(Follower2 *self) { MYFLT absin, risetime, falltime; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *rise = Stream_getData((Stream *)self->risetime_stream); falltime = PyFloat_AS_DOUBLE(self->falltime); if (falltime <= 0.0) falltime = 0.000001; if (falltime != self->last_falltime) { self->fallfactor = MYEXP(-TWOPI * (1.0 / falltime) / self->sr); self->last_falltime = falltime; } for (i=0; ibufsize; i++) { risetime = rise[i]; if (risetime <= 0.0) risetime = 0.000001; if (risetime != self->last_risetime) { self->risefactor = MYEXP(-TWOPI * (1.0 / risetime) / self->sr); self->last_risetime = risetime; } absin = in[i]; if (absin < 0.0) absin = -absin; if (self->follow < absin) self->follow = self->data[i] = absin + self->risefactor * (self->follow - absin); else self->follow = self->data[i] = absin + self->fallfactor * (self->follow - absin); } } static void Follower2_filters_ia(Follower2 *self) { MYFLT absin, risetime, falltime; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); risetime = PyFloat_AS_DOUBLE(self->risetime); if (risetime <= 0.0) risetime = 0.000001; MYFLT *fall = Stream_getData((Stream *)self->falltime_stream); if (risetime != self->last_risetime) { self->risefactor = MYEXP(-TWOPI * (1.0 / risetime) / self->sr); self->last_risetime = risetime; } for (i=0; ibufsize; i++) { falltime = fall[i]; if (falltime <= 0.0) falltime = 0.000001; if (falltime != self->last_falltime) { self->fallfactor = MYEXP(-TWOPI * (1.0 / falltime) / self->sr); self->last_falltime = falltime; } absin = in[i]; if (absin < 0.0) absin = -absin; if (self->follow < absin) self->follow = self->data[i] = absin + self->risefactor * (self->follow - absin); else self->follow = self->data[i] = absin + self->fallfactor * (self->follow - absin); } } static void Follower2_filters_aa(Follower2 *self) { MYFLT absin, risetime, falltime; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *rise = Stream_getData((Stream *)self->risetime_stream); MYFLT *fall = Stream_getData((Stream *)self->falltime_stream); for (i=0; ibufsize; i++) { risetime = rise[i]; if (risetime <= 0.0) risetime = 0.000001; if (risetime != self->last_risetime) { self->risefactor = MYEXP(-TWOPI * (1.0 / risetime) / self->sr); self->last_risetime = risetime; } falltime = fall[i]; if (falltime <= 0.0) falltime = 0.000001; if (falltime != self->last_falltime) { self->fallfactor = MYEXP(-TWOPI * (1.0 / falltime) / self->sr); self->last_falltime = falltime; } absin = in[i]; if (absin < 0.0) absin = -absin; if (self->follow < absin) self->follow = self->data[i] = absin + self->risefactor * (self->follow - absin); else self->follow = self->data[i] = absin + self->fallfactor * (self->follow - absin); } } static void Follower2_postprocessing_ii(Follower2 *self) { POST_PROCESSING_II }; static void Follower2_postprocessing_ai(Follower2 *self) { POST_PROCESSING_AI }; static void Follower2_postprocessing_ia(Follower2 *self) { POST_PROCESSING_IA }; static void Follower2_postprocessing_aa(Follower2 *self) { POST_PROCESSING_AA }; static void Follower2_postprocessing_ireva(Follower2 *self) { POST_PROCESSING_IREVA }; static void Follower2_postprocessing_areva(Follower2 *self) { POST_PROCESSING_AREVA }; static void Follower2_postprocessing_revai(Follower2 *self) { POST_PROCESSING_REVAI }; static void Follower2_postprocessing_revaa(Follower2 *self) { POST_PROCESSING_REVAA }; static void Follower2_postprocessing_revareva(Follower2 *self) { POST_PROCESSING_REVAREVA }; static void Follower2_setProcMode(Follower2 *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Follower2_filters_ii; break; case 1: self->proc_func_ptr = Follower2_filters_ai; break; case 10: self->proc_func_ptr = Follower2_filters_ia; break; case 11: self->proc_func_ptr = Follower2_filters_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Follower2_postprocessing_ii; break; case 1: self->muladd_func_ptr = Follower2_postprocessing_ai; break; case 2: self->muladd_func_ptr = Follower2_postprocessing_revai; break; case 10: self->muladd_func_ptr = Follower2_postprocessing_ia; break; case 11: self->muladd_func_ptr = Follower2_postprocessing_aa; break; case 12: self->muladd_func_ptr = Follower2_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Follower2_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Follower2_postprocessing_areva; break; case 22: self->muladd_func_ptr = Follower2_postprocessing_revareva; break; } } static void Follower2_compute_next_data_frame(Follower2 *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Follower2_traverse(Follower2 *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->risetime); Py_VISIT(self->risetime_stream); Py_VISIT(self->falltime); Py_VISIT(self->falltime_stream); return 0; } static int Follower2_clear(Follower2 *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->risetime); Py_CLEAR(self->risetime_stream); Py_CLEAR(self->falltime); Py_CLEAR(self->falltime_stream); return 0; } static void Follower2_dealloc(Follower2* self) { pyo_DEALLOC Follower2_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Follower2_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *risetimetmp=NULL, *falltimetmp=NULL, *multmp=NULL, *addtmp=NULL; Follower2 *self; self = (Follower2 *)type->tp_alloc(type, 0); self->risetime = PyFloat_FromDouble(0.01); self->falltime = PyFloat_FromDouble(0.1); self->follow = 0.0; self->last_risetime = -1.0; self->last_falltime = -1.0; self->risefactor = self->fallfactor = 0.99; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Follower2_compute_next_data_frame); self->mode_func_ptr = Follower2_setProcMode; static char *kwlist[] = {"input", "risetime", "falltime", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &risetimetmp, &falltimetmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (risetimetmp) { PyObject_CallMethod((PyObject *)self, "setRisetime", "O", risetimetmp); } if (falltimetmp) { PyObject_CallMethod((PyObject *)self, "setFalltime", "O", falltimetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Follower2_getServer(Follower2* self) { GET_SERVER }; static PyObject * Follower2_getStream(Follower2* self) { GET_STREAM }; static PyObject * Follower2_setMul(Follower2 *self, PyObject *arg) { SET_MUL }; static PyObject * Follower2_setAdd(Follower2 *self, PyObject *arg) { SET_ADD }; static PyObject * Follower2_setSub(Follower2 *self, PyObject *arg) { SET_SUB }; static PyObject * Follower2_setDiv(Follower2 *self, PyObject *arg) { SET_DIV }; static PyObject * Follower2_play(Follower2 *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Follower2_stop(Follower2 *self) { STOP }; static PyObject * Follower2_multiply(Follower2 *self, PyObject *arg) { MULTIPLY }; static PyObject * Follower2_inplace_multiply(Follower2 *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Follower2_add(Follower2 *self, PyObject *arg) { ADD }; static PyObject * Follower2_inplace_add(Follower2 *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Follower2_sub(Follower2 *self, PyObject *arg) { SUB }; static PyObject * Follower2_inplace_sub(Follower2 *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Follower2_div(Follower2 *self, PyObject *arg) { DIV }; static PyObject * Follower2_inplace_div(Follower2 *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Follower2_setRisetime(Follower2 *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->risetime); if (isNumber == 1) { self->risetime = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->risetime = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->risetime, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->risetime_stream); self->risetime_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Follower2_setFalltime(Follower2 *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->falltime); if (isNumber == 1) { self->falltime = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->falltime = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->falltime, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->falltime_stream); self->falltime_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Follower2_members[] = { {"server", T_OBJECT_EX, offsetof(Follower2, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Follower2, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Follower2, input), 0, "Input sound object."}, {"risetime", T_OBJECT_EX, offsetof(Follower2, risetime), 0, "Risetime in second."}, {"falltime", T_OBJECT_EX, offsetof(Follower2, falltime), 0, "Falltime in second."}, {"mul", T_OBJECT_EX, offsetof(Follower2, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Follower2, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Follower2_methods[] = { {"getServer", (PyCFunction)Follower2_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Follower2_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Follower2_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Follower2_stop, METH_NOARGS, "Stops computing."}, {"setRisetime", (PyCFunction)Follower2_setRisetime, METH_O, "Sets filter risetime in second."}, {"setFalltime", (PyCFunction)Follower2_setFalltime, METH_O, "Sets filter falltime in second."}, {"setMul", (PyCFunction)Follower2_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Follower2_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Follower2_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Follower2_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Follower2_as_number = { (binaryfunc)Follower2_add, /*nb_add*/ (binaryfunc)Follower2_sub, /*nb_subtract*/ (binaryfunc)Follower2_multiply, /*nb_multiply*/ (binaryfunc)Follower2_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Follower2_inplace_add, /*inplace_add*/ (binaryfunc)Follower2_inplace_sub, /*inplace_subtract*/ (binaryfunc)Follower2_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Follower2_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject Follower2Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Follower2_base", /*tp_name*/ sizeof(Follower2), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Follower2_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Follower2_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Follower2 objects. Envelope follower.", /* tp_doc */ (traverseproc)Follower2_traverse, /* tp_traverse */ (inquiry)Follower2_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Follower2_methods, /* tp_methods */ Follower2_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Follower2_new, /* tp_new */ }; /************/ /* ZCross */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; MYFLT thresh; MYFLT lastValue; MYFLT lastSample; int modebuffer[2]; // need at least 2 slots for mul & add } ZCross; static void ZCross_process(ZCross *self) { int i; int count = 0; MYFLT inval; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = self->lastValue; inval = in[i]; if (self->lastSample >= 0.0) { if (inval < 0.0 && (self->lastSample-inval) > self->thresh) count++; } else { if (inval >= 0.0 && (inval-self->lastSample) > self->thresh) count++; } self->lastSample = inval; } self->lastValue = (MYFLT)count / self->bufsize; } static void ZCross_postprocessing_ii(ZCross *self) { POST_PROCESSING_II }; static void ZCross_postprocessing_ai(ZCross *self) { POST_PROCESSING_AI }; static void ZCross_postprocessing_ia(ZCross *self) { POST_PROCESSING_IA }; static void ZCross_postprocessing_aa(ZCross *self) { POST_PROCESSING_AA }; static void ZCross_postprocessing_ireva(ZCross *self) { POST_PROCESSING_IREVA }; static void ZCross_postprocessing_areva(ZCross *self) { POST_PROCESSING_AREVA }; static void ZCross_postprocessing_revai(ZCross *self) { POST_PROCESSING_REVAI }; static void ZCross_postprocessing_revaa(ZCross *self) { POST_PROCESSING_REVAA }; static void ZCross_postprocessing_revareva(ZCross *self) { POST_PROCESSING_REVAREVA }; static void ZCross_setProcMode(ZCross *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = ZCross_process; switch (muladdmode) { case 0: self->muladd_func_ptr = ZCross_postprocessing_ii; break; case 1: self->muladd_func_ptr = ZCross_postprocessing_ai; break; case 2: self->muladd_func_ptr = ZCross_postprocessing_revai; break; case 10: self->muladd_func_ptr = ZCross_postprocessing_ia; break; case 11: self->muladd_func_ptr = ZCross_postprocessing_aa; break; case 12: self->muladd_func_ptr = ZCross_postprocessing_revaa; break; case 20: self->muladd_func_ptr = ZCross_postprocessing_ireva; break; case 21: self->muladd_func_ptr = ZCross_postprocessing_areva; break; case 22: self->muladd_func_ptr = ZCross_postprocessing_revareva; break; } } static void ZCross_compute_next_data_frame(ZCross *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int ZCross_traverse(ZCross *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int ZCross_clear(ZCross *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void ZCross_dealloc(ZCross* self) { pyo_DEALLOC ZCross_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * ZCross_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; ZCross *self; self = (ZCross *)type->tp_alloc(type, 0); self->thresh = 0.0; self->lastValue = self->lastSample = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, ZCross_compute_next_data_frame); self->mode_func_ptr = ZCross_setProcMode; static char *kwlist[] = {"input", "thresh", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FOO, kwlist, &inputtmp, &self->thresh, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * ZCross_getServer(ZCross* self) { GET_SERVER }; static PyObject * ZCross_getStream(ZCross* self) { GET_STREAM }; static PyObject * ZCross_setMul(ZCross *self, PyObject *arg) { SET_MUL }; static PyObject * ZCross_setAdd(ZCross *self, PyObject *arg) { SET_ADD }; static PyObject * ZCross_setSub(ZCross *self, PyObject *arg) { SET_SUB }; static PyObject * ZCross_setDiv(ZCross *self, PyObject *arg) { SET_DIV }; static PyObject * ZCross_play(ZCross *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * ZCross_stop(ZCross *self) { STOP }; static PyObject * ZCross_multiply(ZCross *self, PyObject *arg) { MULTIPLY }; static PyObject * ZCross_inplace_multiply(ZCross *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * ZCross_add(ZCross *self, PyObject *arg) { ADD }; static PyObject * ZCross_inplace_add(ZCross *self, PyObject *arg) { INPLACE_ADD }; static PyObject * ZCross_sub(ZCross *self, PyObject *arg) { SUB }; static PyObject * ZCross_inplace_sub(ZCross *self, PyObject *arg) { INPLACE_SUB }; static PyObject * ZCross_div(ZCross *self, PyObject *arg) { DIV }; static PyObject * ZCross_inplace_div(ZCross *self, PyObject *arg) { INPLACE_DIV }; static PyObject * ZCross_setThresh(ZCross *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->thresh = PyFloat_AsDouble(arg); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef ZCross_members[] = { {"server", T_OBJECT_EX, offsetof(ZCross, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(ZCross, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(ZCross, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(ZCross, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(ZCross, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef ZCross_methods[] = { {"getServer", (PyCFunction)ZCross_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)ZCross_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)ZCross_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)ZCross_stop, METH_NOARGS, "Stops computing."}, {"setThresh", (PyCFunction)ZCross_setThresh, METH_O, "Sets the threshold factor."}, {"setMul", (PyCFunction)ZCross_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)ZCross_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)ZCross_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)ZCross_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods ZCross_as_number = { (binaryfunc)ZCross_add, /*nb_add*/ (binaryfunc)ZCross_sub, /*nb_subtract*/ (binaryfunc)ZCross_multiply, /*nb_multiply*/ (binaryfunc)ZCross_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)ZCross_inplace_add, /*inplace_add*/ (binaryfunc)ZCross_inplace_sub, /*inplace_subtract*/ (binaryfunc)ZCross_inplace_multiply, /*inplace_multiply*/ (binaryfunc)ZCross_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ZCrossType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.ZCross_base", /*tp_name*/ sizeof(ZCross), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)ZCross_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &ZCross_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "ZCross objects. Returns number of zero crossing.", /* tp_doc */ (traverseproc)ZCross_traverse, /* tp_traverse */ (inquiry)ZCross_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ ZCross_methods, /* tp_methods */ ZCross_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ ZCross_new, /* tp_new */ }; static int min_elem_pos(MYFLT *buf, int size ) { int i; int pos = 0; for (i=1; iinput_stream); if (self->cutoff != self->last_cutoff) { if (self->cutoff <= 1.0) self->cutoff = 1.0; else if (self->cutoff >= self->sr*0.5) self->cutoff = self->sr*0.5; self->last_cutoff = self->cutoff; self->c2 = MYEXP(-TWOPI * self->cutoff / self->sr); } for (i=0; ibufsize; i++) { self->y1 = in[i] + (self->y1 - in[i]) * self->c2; self->input_buffer[self->input_count] = self->y1; if (self->input_count++ == self->winsize) { self->input_count = 0; self->yin_buffer[0] = 1.0; for (tau = 1; tau < self->halfsize; tau++) { self->yin_buffer[tau] = 0.0; for (j = 0; j < self->halfsize; j++) { tmp = self->input_buffer[j] - self->input_buffer[j+tau]; self->yin_buffer[tau] += tmp*tmp; } tmp2 += self->yin_buffer[tau]; self->yin_buffer[tau] *= tau / tmp2; period = tau - 3; if (tau > 4 && (self->yin_buffer[period] < self->tolerance) && (self->yin_buffer[period] < self->yin_buffer[period+1])) { candidate = quadraticInterpolation(self->yin_buffer, period, self->halfsize); goto founded; } } candidate = quadraticInterpolation(self->yin_buffer, min_elem_pos(self->yin_buffer, self->halfsize), self->halfsize); founded: candidate = self->sr / candidate; if (candidate > self->minfreq && candidate < self->maxfreq) self->pitch = candidate; } self->data[i] = self->pitch; } } static void Yin_postprocessing_ii(Yin *self) { POST_PROCESSING_II }; static void Yin_postprocessing_ai(Yin *self) { POST_PROCESSING_AI }; static void Yin_postprocessing_ia(Yin *self) { POST_PROCESSING_IA }; static void Yin_postprocessing_aa(Yin *self) { POST_PROCESSING_AA }; static void Yin_postprocessing_ireva(Yin *self) { POST_PROCESSING_IREVA }; static void Yin_postprocessing_areva(Yin *self) { POST_PROCESSING_AREVA }; static void Yin_postprocessing_revai(Yin *self) { POST_PROCESSING_REVAI }; static void Yin_postprocessing_revaa(Yin *self) { POST_PROCESSING_REVAA }; static void Yin_postprocessing_revareva(Yin *self) { POST_PROCESSING_REVAREVA }; static void Yin_setProcMode(Yin *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Yin_process; switch (muladdmode) { case 0: self->muladd_func_ptr = Yin_postprocessing_ii; break; case 1: self->muladd_func_ptr = Yin_postprocessing_ai; break; case 2: self->muladd_func_ptr = Yin_postprocessing_revai; break; case 10: self->muladd_func_ptr = Yin_postprocessing_ia; break; case 11: self->muladd_func_ptr = Yin_postprocessing_aa; break; case 12: self->muladd_func_ptr = Yin_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Yin_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Yin_postprocessing_areva; break; case 22: self->muladd_func_ptr = Yin_postprocessing_revareva; break; } } static void Yin_compute_next_data_frame(Yin *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Yin_traverse(Yin *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Yin_clear(Yin *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Yin_dealloc(Yin* self) { pyo_DEALLOC free(self->input_buffer); free(self->yin_buffer); Yin_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Yin_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; Yin *self; self = (Yin *)type->tp_alloc(type, 0); self->winsize = 1024; self->halfsize = 512; self->input_count = 0; self->pitch = 0.; self->tolerance = 0.15; self->minfreq = 40; self->maxfreq = 1000; self->cutoff = 1000; self->last_cutoff = -1.0; self->y1 = self->c2 = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Yin_compute_next_data_frame); self->mode_func_ptr = Yin_setProcMode; static char *kwlist[] = {"input", "tolerance", "minfreq", "maxfreq", "cutoff", "winsize", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FFFFIOO, kwlist, &inputtmp, &self->tolerance, &self->minfreq, &self->maxfreq, &self->cutoff, &self->winsize, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (self->winsize % 2 == 1) self->winsize += 1; self->input_buffer = (MYFLT *)realloc(self->input_buffer, self->winsize * sizeof(MYFLT)); for (i=0; iwinsize; i++) self->input_buffer[i] = 0.0; self->halfsize = self->winsize / 2; self->yin_buffer = (MYFLT *)realloc(self->yin_buffer, self->halfsize * sizeof(MYFLT)); for (i=0; ihalfsize; i++) self->yin_buffer[i] = 0.0; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Yin_getServer(Yin* self) { GET_SERVER }; static PyObject * Yin_getStream(Yin* self) { GET_STREAM }; static PyObject * Yin_setMul(Yin *self, PyObject *arg) { SET_MUL }; static PyObject * Yin_setAdd(Yin *self, PyObject *arg) { SET_ADD }; static PyObject * Yin_setSub(Yin *self, PyObject *arg) { SET_SUB }; static PyObject * Yin_setDiv(Yin *self, PyObject *arg) { SET_DIV }; static PyObject * Yin_play(Yin *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Yin_stop(Yin *self) { STOP }; static PyObject * Yin_multiply(Yin *self, PyObject *arg) { MULTIPLY }; static PyObject * Yin_inplace_multiply(Yin *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Yin_add(Yin *self, PyObject *arg) { ADD }; static PyObject * Yin_inplace_add(Yin *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Yin_sub(Yin *self, PyObject *arg) { SUB }; static PyObject * Yin_inplace_sub(Yin *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Yin_div(Yin *self, PyObject *arg) { DIV }; static PyObject * Yin_inplace_div(Yin *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Yin_setTolerance(Yin *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->tolerance = PyFloat_AsDouble(arg); } Py_RETURN_NONE; } static PyObject * Yin_setMinfreq(Yin *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->minfreq = PyFloat_AsDouble(arg); } Py_RETURN_NONE; } static PyObject * Yin_setMaxfreq(Yin *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->maxfreq = PyFloat_AsDouble(arg); } Py_RETURN_NONE; } static PyObject * Yin_setCutoff(Yin *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->cutoff = PyFloat_AsDouble(arg); } Py_RETURN_NONE; } static PyMemberDef Yin_members[] = { {"server", T_OBJECT_EX, offsetof(Yin, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Yin, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Yin, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(Yin, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Yin, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Yin_methods[] = { {"getServer", (PyCFunction)Yin_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Yin_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Yin_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Yin_stop, METH_NOARGS, "Stops computing."}, {"setTolerance", (PyCFunction)Yin_setTolerance, METH_O, "Sets the tolerance factor."}, {"setMinfreq", (PyCFunction)Yin_setMinfreq, METH_O, "Sets the minimum frequency in output."}, {"setMaxfreq", (PyCFunction)Yin_setMaxfreq, METH_O, "Sets the maximum frequency in output."}, {"setCutoff", (PyCFunction)Yin_setCutoff, METH_O, "Sets the input lowpass filter cutoff frequency."}, {"setMul", (PyCFunction)Yin_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Yin_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Yin_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Yin_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Yin_as_number = { (binaryfunc)Yin_add, /*nb_add*/ (binaryfunc)Yin_sub, /*nb_subtract*/ (binaryfunc)Yin_multiply, /*nb_multiply*/ (binaryfunc)Yin_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Yin_inplace_add, /*inplace_add*/ (binaryfunc)Yin_inplace_sub, /*inplace_subtract*/ (binaryfunc)Yin_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Yin_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject YinType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Yin_base", /*tp_name*/ sizeof(Yin), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Yin_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Yin_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Yin objects. Pitch tracker using the Yin algorithm.", /* tp_doc */ (traverseproc)Yin_traverse, /* tp_traverse */ (inquiry)Yin_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Yin_methods, /* tp_methods */ Yin_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Yin_new, /* tp_new */ }; /********************/ /* Centroid */ /********************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int size; int hsize; int incount; MYFLT centroid; MYFLT *inframe; MYFLT *outframe; MYFLT **twiddle; MYFLT *input_buffer; MYFLT *window; int modebuffer[2]; } Centroid; static void Centroid_alloc_memories(Centroid *self) { int i, n8; self->hsize = self->size / 2; n8 = self->size >> 3; self->inframe = (MYFLT *)realloc(self->inframe, self->size * sizeof(MYFLT)); self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT)); self->input_buffer = (MYFLT *)realloc(self->input_buffer, self->size * sizeof(MYFLT)); for (i=0; isize; i++) self->inframe[i] = self->outframe[i] = self->input_buffer[i] = 0.0; self->twiddle = (MYFLT **)realloc(self->twiddle, 4 * sizeof(MYFLT *)); for(i=0; i<4; i++) self->twiddle[i] = (MYFLT *)malloc(n8 * sizeof(MYFLT)); fft_compute_split_twiddle(self->twiddle, self->size); self->window = (MYFLT *)realloc(self->window, self->size * sizeof(MYFLT)); gen_window(self->window, self->size, 2); } static void Centroid_process_i(Centroid *self) { int i; MYFLT re, im, tmp, sum1, sum2; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->input_buffer[self->incount] = in[i]; self->data[i] = self->centroid; self->incount++; if (self->incount == self->size) { self->incount = self->hsize; for (i=0; isize; i++) { self->inframe[i] = self->input_buffer[i] * self->window[i]; } realfft_split(self->inframe, self->outframe, self->size, self->twiddle); sum1 = sum2 = 0.0; for (i=1; ihsize; i++) { re = self->outframe[i]; im = self->outframe[self->size - i]; tmp = MYSQRT(re*re + im*im); sum1 += tmp * i; sum2 += tmp; } if (sum2 < 0.000000001) tmp = 0.0; else tmp = sum1 / sum2; self->centroid += tmp * self->sr / self->size; self->centroid *= 0.5; for (i=0; ihsize; i++) { self->input_buffer[i] = self->input_buffer[i + self->hsize]; } } } } static void Centroid_postprocessing_ii(Centroid *self) { POST_PROCESSING_II }; static void Centroid_postprocessing_ai(Centroid *self) { POST_PROCESSING_AI }; static void Centroid_postprocessing_ia(Centroid *self) { POST_PROCESSING_IA }; static void Centroid_postprocessing_aa(Centroid *self) { POST_PROCESSING_AA }; static void Centroid_postprocessing_ireva(Centroid *self) { POST_PROCESSING_IREVA }; static void Centroid_postprocessing_areva(Centroid *self) { POST_PROCESSING_AREVA }; static void Centroid_postprocessing_revai(Centroid *self) { POST_PROCESSING_REVAI }; static void Centroid_postprocessing_revaa(Centroid *self) { POST_PROCESSING_REVAA }; static void Centroid_postprocessing_revareva(Centroid *self) { POST_PROCESSING_REVAREVA }; static void Centroid_setProcMode(Centroid *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Centroid_process_i; switch (muladdmode) { case 0: self->muladd_func_ptr = Centroid_postprocessing_ii; break; case 1: self->muladd_func_ptr = Centroid_postprocessing_ai; break; case 2: self->muladd_func_ptr = Centroid_postprocessing_revai; break; case 10: self->muladd_func_ptr = Centroid_postprocessing_ia; break; case 11: self->muladd_func_ptr = Centroid_postprocessing_aa; break; case 12: self->muladd_func_ptr = Centroid_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Centroid_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Centroid_postprocessing_areva; break; case 22: self->muladd_func_ptr = Centroid_postprocessing_revareva; break; } } static void Centroid_compute_next_data_frame(Centroid *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Centroid_traverse(Centroid *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Centroid_clear(Centroid *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Centroid_dealloc(Centroid* self) { int i; pyo_DEALLOC free(self->inframe); free(self->outframe); free(self->input_buffer); for(i=0; i<4; i++) { free(self->twiddle[i]); } free(self->twiddle); free(self->window); Centroid_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Centroid_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, k; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; Centroid *self; self = (Centroid *)type->tp_alloc(type, 0); self->centroid = 0; self->size = 1024; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Centroid_compute_next_data_frame); self->mode_func_ptr = Centroid_setProcMode; static char *kwlist[] = {"input", "size", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &inputtmp, &self->size, &multmp, &addtmp)) Py_RETURN_NONE; if (self->size < self->bufsize) { printf("Warning : Centroid size less than buffer size!\nCentroid size set to buffersize: %d\n", self->bufsize); self->size = self->bufsize; } k = 1; while (k < self->size) k <<= 1; self->size = k; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Centroid_alloc_memories(self); self->incount = self->hsize; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Centroid_getServer(Centroid* self) { GET_SERVER }; static PyObject * Centroid_getStream(Centroid* self) { GET_STREAM }; static PyObject * Centroid_setMul(Centroid *self, PyObject *arg) { SET_MUL }; static PyObject * Centroid_setAdd(Centroid *self, PyObject *arg) { SET_ADD }; static PyObject * Centroid_setSub(Centroid *self, PyObject *arg) { SET_SUB }; static PyObject * Centroid_setDiv(Centroid *self, PyObject *arg) { SET_DIV }; static PyObject * Centroid_play(Centroid *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Centroid_stop(Centroid *self) { STOP }; static PyObject * Centroid_multiply(Centroid *self, PyObject *arg) { MULTIPLY }; static PyObject * Centroid_inplace_multiply(Centroid *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Centroid_add(Centroid *self, PyObject *arg) { ADD }; static PyObject * Centroid_inplace_add(Centroid *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Centroid_sub(Centroid *self, PyObject *arg) { SUB }; static PyObject * Centroid_inplace_sub(Centroid *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Centroid_div(Centroid *self, PyObject *arg) { DIV }; static PyObject * Centroid_inplace_div(Centroid *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Centroid_members[] = { {"server", T_OBJECT_EX, offsetof(Centroid, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Centroid, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Centroid, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Centroid, add), 0, "Add factor."}, {"input", T_OBJECT_EX, offsetof(Centroid, input), 0, "Input sound object."}, {NULL} /* Sentinel */ }; static PyMethodDef Centroid_methods[] = { {"getServer", (PyCFunction)Centroid_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Centroid_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Centroid_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Centroid_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Centroid_setMul, METH_O, "Sets Centroid mul factor."}, {"setAdd", (PyCFunction)Centroid_setAdd, METH_O, "Sets Centroid add factor."}, {"setSub", (PyCFunction)Centroid_setSub, METH_O, "Sets Centroid add factor."}, {"setDiv", (PyCFunction)Centroid_setDiv, METH_O, "Sets Centroid mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Centroid_as_number = { (binaryfunc)Centroid_add, /*nb_add*/ (binaryfunc)Centroid_sub, /*nb_subtract*/ (binaryfunc)Centroid_multiply, /*nb_multiply*/ (binaryfunc)Centroid_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Centroid_inplace_add, /*inplace_add*/ (binaryfunc)Centroid_inplace_sub, /*inplace_subtract*/ (binaryfunc)Centroid_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Centroid_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject CentroidType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Centroid_base", /*tp_name*/ sizeof(Centroid), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Centroid_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Centroid_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Centroid objects. FFT transform.", /* tp_doc */ (traverseproc)Centroid_traverse, /* tp_traverse */ (inquiry)Centroid_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Centroid_methods, /* tp_methods */ Centroid_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Centroid_new, /* tp_new */ }; /************/ /* AttackDetector */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; MYFLT deltime; MYFLT cutoff; MYFLT maxthresh; MYFLT minthresh; MYFLT reltime; MYFLT folfactor; MYFLT follow; MYFLT followdb; MYFLT *buffer; MYFLT previous; int memsize; int sampdel; int incount; int overminok; int belowminok; long maxtime; long timer; int modebuffer[2]; // need at least 2 slots for mul & add } AttackDetector; static void AttackDetector_process(AttackDetector *self) { int i, ind; MYFLT absin; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = 0.0; absin = in[i]; // envelope follower if (absin < 0.0) absin = -absin; self->follow = absin + self->folfactor * (self->follow - absin); // follower in dB if (self->follow <= 0.000001) self->followdb = -120.0; else self->followdb = 20.0 * MYLOG10(self->follow); // previous analysis ind = self->incount - self->sampdel; if (ind < 0) ind += self->memsize; self->previous = self->buffer[ind]; self->buffer[self->incount] = self->followdb; self->incount++; if (self->incount >= self->memsize) self->incount = 0; // if release time has past if (self->timer >= self->maxtime) { // if rms is over min threshold if (self->overminok) { // if rms is greater than previous + maxthresh if (self->followdb > (self->previous + self->maxthresh)) { self->data[i] = 1.0; self->overminok = self->belowminok = 0; self->timer = 0; } } } if (self->belowminok == 0 && self->followdb < self->minthresh) self->belowminok = 1; else if (self->belowminok == 1 && self->followdb > self->minthresh) self->overminok = 1; self->timer++; } } static void AttackDetector_postprocessing_ii(AttackDetector *self) { POST_PROCESSING_II }; static void AttackDetector_postprocessing_ai(AttackDetector *self) { POST_PROCESSING_AI }; static void AttackDetector_postprocessing_ia(AttackDetector *self) { POST_PROCESSING_IA }; static void AttackDetector_postprocessing_aa(AttackDetector *self) { POST_PROCESSING_AA }; static void AttackDetector_postprocessing_ireva(AttackDetector *self) { POST_PROCESSING_IREVA }; static void AttackDetector_postprocessing_areva(AttackDetector *self) { POST_PROCESSING_AREVA }; static void AttackDetector_postprocessing_revai(AttackDetector *self) { POST_PROCESSING_REVAI }; static void AttackDetector_postprocessing_revaa(AttackDetector *self) { POST_PROCESSING_REVAA }; static void AttackDetector_postprocessing_revareva(AttackDetector *self) { POST_PROCESSING_REVAREVA }; static void AttackDetector_setProcMode(AttackDetector *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = AttackDetector_process; switch (muladdmode) { case 0: self->muladd_func_ptr = AttackDetector_postprocessing_ii; break; case 1: self->muladd_func_ptr = AttackDetector_postprocessing_ai; break; case 2: self->muladd_func_ptr = AttackDetector_postprocessing_revai; break; case 10: self->muladd_func_ptr = AttackDetector_postprocessing_ia; break; case 11: self->muladd_func_ptr = AttackDetector_postprocessing_aa; break; case 12: self->muladd_func_ptr = AttackDetector_postprocessing_revaa; break; case 20: self->muladd_func_ptr = AttackDetector_postprocessing_ireva; break; case 21: self->muladd_func_ptr = AttackDetector_postprocessing_areva; break; case 22: self->muladd_func_ptr = AttackDetector_postprocessing_revareva; break; } } static void AttackDetector_compute_next_data_frame(AttackDetector *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int AttackDetector_traverse(AttackDetector *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int AttackDetector_clear(AttackDetector *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void AttackDetector_dealloc(AttackDetector* self) { pyo_DEALLOC free(self->buffer); AttackDetector_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * AttackDetector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; AttackDetector *self; self = (AttackDetector *)type->tp_alloc(type, 0); self->deltime = 0.005; self->cutoff = 10.0; self->maxthresh = 3.0; self->minthresh = -30.0; self->reltime = 0.1; self->follow = 0.0; self->followdb = -120.0; self->previous = 0.0; self->incount = 0; self->overminok = 0; self->belowminok = 0; self->timer = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, AttackDetector_compute_next_data_frame); self->mode_func_ptr = AttackDetector_setProcMode; static char *kwlist[] = {"input", "deltime", "cutoff", "maxthresh", "minthresh", "reltime", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FFFFFOO, kwlist, &inputtmp, &self->deltime, &self->cutoff, &self->maxthresh, &self->minthresh, &self->reltime, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->memsize = (int)(0.055 * self->sr + 0.5); self->buffer = (MYFLT *)realloc(self->buffer, (self->memsize+1) * sizeof(MYFLT)); for (i=0; i<(self->memsize+1); i++) { self->buffer[i] = 0.0; } if (self->deltime < 0.001) self->deltime = 0.001; else if (self->deltime > 0.05) self->deltime = 0.05; self->sampdel = (int)(self->deltime * self->sr); if (self->cutoff < 1.0) self->cutoff = 1.0; else if (self->cutoff > 1000.0) self->cutoff = 1000.0; self->folfactor = MYEXP(-TWOPI * self->cutoff / self->sr); if (self->cutoff < 1.0) self->cutoff = 1.0; else if (self->cutoff > 1000.0) self->cutoff = 1000.0; if (self->maxthresh < 0.0) self->maxthresh = 0.0; else if (self->maxthresh > 18.0) self->maxthresh = 18.0; if (self->minthresh < -90.0) self->minthresh = -90.0; else if (self->minthresh > 0.0) self->minthresh = 0.0; if (self->reltime < 0.001) self->reltime = 0.001; self->maxtime = (long)(self->reltime * self->sr + 0.5); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * AttackDetector_getServer(AttackDetector* self) { GET_SERVER }; static PyObject * AttackDetector_getStream(AttackDetector* self) { GET_STREAM }; static PyObject * AttackDetector_setMul(AttackDetector *self, PyObject *arg) { SET_MUL }; static PyObject * AttackDetector_setAdd(AttackDetector *self, PyObject *arg) { SET_ADD }; static PyObject * AttackDetector_setSub(AttackDetector *self, PyObject *arg) { SET_SUB }; static PyObject * AttackDetector_setDiv(AttackDetector *self, PyObject *arg) { SET_DIV }; static PyObject * AttackDetector_play(AttackDetector *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * AttackDetector_stop(AttackDetector *self) { STOP }; static PyObject * AttackDetector_multiply(AttackDetector *self, PyObject *arg) { MULTIPLY }; static PyObject * AttackDetector_inplace_multiply(AttackDetector *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * AttackDetector_add(AttackDetector *self, PyObject *arg) { ADD }; static PyObject * AttackDetector_inplace_add(AttackDetector *self, PyObject *arg) { INPLACE_ADD }; static PyObject * AttackDetector_sub(AttackDetector *self, PyObject *arg) { SUB }; static PyObject * AttackDetector_inplace_sub(AttackDetector *self, PyObject *arg) { INPLACE_SUB }; static PyObject * AttackDetector_div(AttackDetector *self, PyObject *arg) { DIV }; static PyObject * AttackDetector_inplace_div(AttackDetector *self, PyObject *arg) { INPLACE_DIV }; static PyObject * AttackDetector_setDeltime(AttackDetector *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->deltime = PyFloat_AsDouble(arg); if (self->deltime < 0.001) self->deltime = 0.001; else if (self->deltime > 0.05) self->deltime = 0.05; self->sampdel = (int)(self->deltime * self->sr); } Py_RETURN_NONE; } static PyObject * AttackDetector_setCutoff(AttackDetector *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->cutoff = PyFloat_AsDouble(arg); if (self->cutoff < 1.0) self->cutoff = 1.0; else if (self->cutoff > 1000.0) self->cutoff = 1000.0; self->folfactor = MYEXP(-TWOPI * self->cutoff / self->sr); } Py_RETURN_NONE; } static PyObject * AttackDetector_setMaxthresh(AttackDetector *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->maxthresh = PyFloat_AsDouble(arg); if (self->maxthresh < 0.0) self->maxthresh = 0.0; else if (self->maxthresh > 18.0) self->maxthresh = 18.0; } Py_RETURN_NONE; } static PyObject * AttackDetector_setMinthresh(AttackDetector *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->minthresh = PyFloat_AsDouble(arg); if (self->minthresh < -90.0) self->minthresh = -90.0; else if (self->minthresh > 0.0) self->minthresh = 0.0; } Py_RETURN_NONE; } static PyObject * AttackDetector_setReltime(AttackDetector *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->reltime = PyFloat_AsDouble(arg); if (self->reltime < 0.001) self->reltime = 0.001; self->maxtime = (long)(self->reltime * self->sr + 0.5); } Py_RETURN_NONE; } static PyMemberDef AttackDetector_members[] = { {"server", T_OBJECT_EX, offsetof(AttackDetector, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(AttackDetector, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(AttackDetector, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(AttackDetector, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(AttackDetector, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef AttackDetector_methods[] = { {"getServer", (PyCFunction)AttackDetector_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)AttackDetector_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)AttackDetector_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)AttackDetector_stop, METH_NOARGS, "Stops computing."}, {"setDeltime", (PyCFunction)AttackDetector_setDeltime, METH_O, "Sets the delay time between current and previous analysis."}, {"setCutoff", (PyCFunction)AttackDetector_setCutoff, METH_O, "Sets the frequency of the internal lowpass filter."}, {"setMaxthresh", (PyCFunction)AttackDetector_setMaxthresh, METH_O, "Sets the higher threshold."}, {"setMinthresh", (PyCFunction)AttackDetector_setMinthresh, METH_O, "Sets the lower threshold."}, {"setReltime", (PyCFunction)AttackDetector_setReltime, METH_O, "Sets the release time (min time between two detected attacks)."}, {"setMul", (PyCFunction)AttackDetector_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)AttackDetector_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)AttackDetector_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)AttackDetector_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods AttackDetector_as_number = { (binaryfunc)AttackDetector_add, /*nb_add*/ (binaryfunc)AttackDetector_sub, /*nb_subtract*/ (binaryfunc)AttackDetector_multiply, /*nb_multiply*/ (binaryfunc)AttackDetector_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)AttackDetector_inplace_add, /*inplace_add*/ (binaryfunc)AttackDetector_inplace_sub, /*inplace_subtract*/ (binaryfunc)AttackDetector_inplace_multiply, /*inplace_multiply*/ (binaryfunc)AttackDetector_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject AttackDetectorType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.AttackDetector_base", /*tp_name*/ sizeof(AttackDetector), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)AttackDetector_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &AttackDetector_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "AttackDetector objects. Audio signal peak detection.", /* tp_doc */ (traverseproc)AttackDetector_traverse, /* tp_traverse */ (inquiry)AttackDetector_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ AttackDetector_methods, /* tp_methods */ AttackDetector_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ AttackDetector_new, /* tp_new */ }; /**********************************/ /********* Scope ******************/ /**********************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int size; int width; int height; int pointer; MYFLT gain; MYFLT *buffer; } Scope; static void Scope_generate(Scope *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { if (self->pointer >= self->size) self->pointer = 0; self->buffer[self->pointer] = in[i]; self->pointer++; } } static PyObject * Scope_display(Scope *self) { int i, ipos; MYFLT pos, step, mag, h2; PyObject *points, *tuple; step = self->size / (MYFLT)(self->width); h2 = self->height * 0.5; points = PyList_New(self->width); for (i=0; iwidth; i++) { pos = i * step; ipos = (int)pos; tuple = PyTuple_New(2); mag = ((self->buffer[ipos] + (self->buffer[ipos+1] - self->buffer[ipos]) * (pos - ipos)) * self->gain * h2 + h2); PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(i)); PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->height - (int)mag)); PyList_SET_ITEM(points, i, tuple); } return points; } static void Scope_compute_next_data_frame(Scope *self) { Scope_generate(self); } static int Scope_traverse(Scope *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Scope_clear(Scope *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Scope_dealloc(Scope* self) { pyo_DEALLOC free(self->buffer); Scope_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Scope_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, maxsize; MYFLT length = 0.05; PyObject *inputtmp, *input_streamtmp; Scope *self; self = (Scope *)type->tp_alloc(type, 0); self->gain = 1.0; self->width = 500; self->height = 400; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Scope_compute_next_data_frame); static char *kwlist[] = {"input", "length", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_F, kwlist, &inputtmp, &length)) Py_RETURN_NONE; INIT_INPUT_STREAM maxsize = (int)(self->sr * 0.25); self->buffer = (MYFLT *)realloc(self->buffer, maxsize * sizeof(MYFLT)); self->size = (int)(length * self->sr); if (self->size > maxsize) self->size = maxsize; self->pointer = 0; PyObject_CallMethod(self->server, "addStream", "O", self->stream); return (PyObject *)self; } static PyObject * Scope_getServer(Scope* self) { GET_SERVER }; static PyObject * Scope_getStream(Scope* self) { GET_STREAM }; static PyObject * Scope_play(Scope *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Scope_stop(Scope *self) { STOP }; static PyObject * Scope_setLength(Scope *self, PyObject *arg) { MYFLT length; int maxsize = (int)(self->sr * 0.25); if (PyNumber_Check(arg)) { length = PyFloat_AsDouble(arg); self->size = (int)(length * self->sr); if (self->size > maxsize) self->size = maxsize; self->pointer = 0; } Py_INCREF(Py_None); return Py_None; } static PyObject * Scope_setGain(Scope *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->gain = PyFloat_AsDouble(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Scope_setWidth(Scope *self, PyObject *arg) { if (PyInt_Check(arg)) { self->width = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Scope_setHeight(Scope *self, PyObject *arg) { if (PyInt_Check(arg)) { self->height = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Scope_members[] = { {"server", T_OBJECT_EX, offsetof(Scope, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Scope, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Scope, input), 0, "Input sound object."}, {NULL} /* Sentinel */ }; static PyMethodDef Scope_methods[] = { {"getServer", (PyCFunction)Scope_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Scope_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Scope_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Scope_stop, METH_NOARGS, "Stops computing."}, {"display", (PyCFunction)Scope_display, METH_NOARGS, "Computes the samples to draw."}, {"setLength", (PyCFunction)Scope_setLength, METH_O, "Sets function's argument."}, {"setGain", (PyCFunction)Scope_setGain, METH_O, "Sets gain compensation."}, {"setWidth", (PyCFunction)Scope_setWidth, METH_O, "Sets the width of the display."}, {"setHeight", (PyCFunction)Scope_setHeight, METH_O, "Sets the height of the display."}, {NULL} /* Sentinel */ }; PyTypeObject ScopeType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Scope_base", /*tp_name*/ sizeof(Scope), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Scope_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Scope objects. Show the waveform of an input signal.", /* tp_doc */ (traverseproc)Scope_traverse, /* tp_traverse */ (inquiry)Scope_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Scope_methods, /* tp_methods */ Scope_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Scope_new, /* tp_new */ }; /************/ /* PeakAmp */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add MYFLT follow; } PeakAmp; static void PeakAmp_filters_i(PeakAmp *self) { MYFLT absin, peak; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); peak = 0.0; for (i=0; ibufsize; i++) { absin = in[i]; if (absin < 0.0) absin = -absin; if (absin > peak) peak = absin; self->data[i] = self->follow; } self->follow = peak; } static void PeakAmp_postprocessing_ii(PeakAmp *self) { POST_PROCESSING_II }; static void PeakAmp_postprocessing_ai(PeakAmp *self) { POST_PROCESSING_AI }; static void PeakAmp_postprocessing_ia(PeakAmp *self) { POST_PROCESSING_IA }; static void PeakAmp_postprocessing_aa(PeakAmp *self) { POST_PROCESSING_AA }; static void PeakAmp_postprocessing_ireva(PeakAmp *self) { POST_PROCESSING_IREVA }; static void PeakAmp_postprocessing_areva(PeakAmp *self) { POST_PROCESSING_AREVA }; static void PeakAmp_postprocessing_revai(PeakAmp *self) { POST_PROCESSING_REVAI }; static void PeakAmp_postprocessing_revaa(PeakAmp *self) { POST_PROCESSING_REVAA }; static void PeakAmp_postprocessing_revareva(PeakAmp *self) { POST_PROCESSING_REVAREVA }; static void PeakAmp_setProcMode(PeakAmp *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = PeakAmp_filters_i; switch (muladdmode) { case 0: self->muladd_func_ptr = PeakAmp_postprocessing_ii; break; case 1: self->muladd_func_ptr = PeakAmp_postprocessing_ai; break; case 2: self->muladd_func_ptr = PeakAmp_postprocessing_revai; break; case 10: self->muladd_func_ptr = PeakAmp_postprocessing_ia; break; case 11: self->muladd_func_ptr = PeakAmp_postprocessing_aa; break; case 12: self->muladd_func_ptr = PeakAmp_postprocessing_revaa; break; case 20: self->muladd_func_ptr = PeakAmp_postprocessing_ireva; break; case 21: self->muladd_func_ptr = PeakAmp_postprocessing_areva; break; case 22: self->muladd_func_ptr = PeakAmp_postprocessing_revareva; break; } } static void PeakAmp_compute_next_data_frame(PeakAmp *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int PeakAmp_traverse(PeakAmp *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int PeakAmp_clear(PeakAmp *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void PeakAmp_dealloc(PeakAmp* self) { pyo_DEALLOC PeakAmp_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * PeakAmp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; PeakAmp *self; self = (PeakAmp *)type->tp_alloc(type, 0); self->follow = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, PeakAmp_compute_next_data_frame); self->mode_func_ptr = PeakAmp_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * PeakAmp_getServer(PeakAmp* self) { GET_SERVER }; static PyObject * PeakAmp_getStream(PeakAmp* self) { GET_STREAM }; static PyObject * PeakAmp_setMul(PeakAmp *self, PyObject *arg) { SET_MUL }; static PyObject * PeakAmp_setAdd(PeakAmp *self, PyObject *arg) { SET_ADD }; static PyObject * PeakAmp_setSub(PeakAmp *self, PyObject *arg) { SET_SUB }; static PyObject * PeakAmp_setDiv(PeakAmp *self, PyObject *arg) { SET_DIV }; static PyObject * PeakAmp_play(PeakAmp *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * PeakAmp_stop(PeakAmp *self) { STOP }; static PyObject * PeakAmp_multiply(PeakAmp *self, PyObject *arg) { MULTIPLY }; static PyObject * PeakAmp_inplace_multiply(PeakAmp *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * PeakAmp_add(PeakAmp *self, PyObject *arg) { ADD }; static PyObject * PeakAmp_inplace_add(PeakAmp *self, PyObject *arg) { INPLACE_ADD }; static PyObject * PeakAmp_sub(PeakAmp *self, PyObject *arg) { SUB }; static PyObject * PeakAmp_inplace_sub(PeakAmp *self, PyObject *arg) { INPLACE_SUB }; static PyObject * PeakAmp_div(PeakAmp *self, PyObject *arg) { DIV }; static PyObject * PeakAmp_inplace_div(PeakAmp *self, PyObject *arg) { INPLACE_DIV }; static PyObject * PeakAmp_getValue(PeakAmp *self) { return PyFloat_FromDouble(self->follow); } static PyMemberDef PeakAmp_members[] = { {"server", T_OBJECT_EX, offsetof(PeakAmp, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(PeakAmp, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(PeakAmp, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(PeakAmp, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(PeakAmp, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef PeakAmp_methods[] = { {"getServer", (PyCFunction)PeakAmp_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)PeakAmp_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)PeakAmp_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)PeakAmp_stop, METH_NOARGS, "Stops computing."}, {"getValue", (PyCFunction)PeakAmp_getValue, METH_NOARGS, "Returns the current peaking value."}, {"setMul", (PyCFunction)PeakAmp_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)PeakAmp_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)PeakAmp_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)PeakAmp_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods PeakAmp_as_number = { (binaryfunc)PeakAmp_add, /*nb_add*/ (binaryfunc)PeakAmp_sub, /*nb_subtract*/ (binaryfunc)PeakAmp_multiply, /*nb_multiply*/ (binaryfunc)PeakAmp_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)PeakAmp_inplace_add, /*inplace_add*/ (binaryfunc)PeakAmp_inplace_sub, /*inplace_subtract*/ (binaryfunc)PeakAmp_inplace_multiply, /*inplace_multiply*/ (binaryfunc)PeakAmp_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject PeakAmpType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.PeakAmp_base", /*tp_name*/ sizeof(PeakAmp), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)PeakAmp_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &PeakAmp_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "PeakAmp objects. Envelope follower.", /* tp_doc */ (traverseproc)PeakAmp_traverse, /* tp_traverse */ (inquiry)PeakAmp_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ PeakAmp_methods, /* tp_methods */ PeakAmp_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ PeakAmp_new, /* tp_new */ };pyo/src/objects/midimodule.c0000644000175000017500000037071612652732202015410 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "portmidi.h" typedef struct { pyo_audio_HEAD PyObject *callable; int ctlnumber; int toprint; } CtlScan; static void CtlScan_setProcMode(CtlScan *self) {} static void CtlScan_compute_next_data_frame(CtlScan *self) { PmEvent *buffer; int i, count; buffer = Server_getMidiEventBuffer((Server *)self->server); count = Server_getMidiEventCount((Server *)self->server); if (count > 0) { PyObject *tup; for (i=count-1; i>=0; i--) { int status = Pm_MessageStatus(buffer[i].message); // Temp note event holders int number = Pm_MessageData1(buffer[i].message); int value = Pm_MessageData2(buffer[i].message); if ((status & 0xF0) == 0xB0) { if (number != self->ctlnumber) { self->ctlnumber = number; tup = PyTuple_New(1); PyTuple_SetItem(tup, 0, PyInt_FromLong(self->ctlnumber)); PyObject_Call((PyObject *)self->callable, tup, NULL); } if (self->toprint == 1) printf("ctl number : %i, ctl value : %i, midi channel : %i\n", self->ctlnumber, value, status - 0xB0 + 1); } } } } static int CtlScan_traverse(CtlScan *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->callable); return 0; } static int CtlScan_clear(CtlScan *self) { pyo_CLEAR Py_CLEAR(self->callable); return 0; } static void CtlScan_dealloc(CtlScan* self) { pyo_DEALLOC CtlScan_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * CtlScan_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *calltmp=NULL; CtlScan *self; self = (CtlScan *)type->tp_alloc(type, 0); self->ctlnumber = -1; self->toprint = 1; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, CtlScan_compute_next_data_frame); self->mode_func_ptr = CtlScan_setProcMode; static char *kwlist[] = {"callable", "toprint", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &calltmp, &self->toprint)) Py_RETURN_NONE; if (calltmp) { PyObject_CallMethod((PyObject *)self, "setFunction", "O", calltmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); return (PyObject *)self; } static PyObject * CtlScan_getServer(CtlScan* self) { GET_SERVER }; static PyObject * CtlScan_getStream(CtlScan* self) { GET_STREAM }; static PyObject * CtlScan_play(CtlScan *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * CtlScan_stop(CtlScan *self) { STOP }; static PyObject * CtlScan_reset(CtlScan *self) { self->ctlnumber = -1; Py_INCREF(Py_None); return Py_None; }; static PyObject * CtlScan_setFunction(CtlScan *self, PyObject *arg) { PyObject *tmp; if (! PyCallable_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function."); Py_INCREF(Py_None); return Py_None; } tmp = arg; Py_XDECREF(self->callable); Py_INCREF(tmp); self->callable = tmp; Py_INCREF(Py_None); return Py_None; } static PyObject * CtlScan_setToprint(CtlScan *self, PyObject *arg) { if (PyInt_Check(arg)) { self->toprint = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef CtlScan_members[] = { {"server", T_OBJECT_EX, offsetof(CtlScan, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(CtlScan, stream), 0, "Stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef CtlScan_methods[] = { {"getServer", (PyCFunction)CtlScan_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)CtlScan_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)CtlScan_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)CtlScan_stop, METH_NOARGS, "Stops computing."}, {"reset", (PyCFunction)CtlScan_reset, METH_NOARGS, "Resets the scanned number."}, {"setFunction", (PyCFunction)CtlScan_setFunction, METH_O, "Sets the function to be called."}, {"setToprint", (PyCFunction)CtlScan_setToprint, METH_O, "If True, print values to the console."}, {NULL} /* Sentinel */ }; PyTypeObject CtlScanType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.CtlScan_base", /*tp_name*/ sizeof(CtlScan), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)CtlScan_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "CtlScan objects. Retreive controller numbers from a Midi input.", /* tp_doc */ (traverseproc)CtlScan_traverse, /* tp_traverse */ (inquiry)CtlScan_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ CtlScan_methods, /* tp_methods */ CtlScan_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ CtlScan_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *callable; int ctlnumber; int midichnl; int toprint; } CtlScan2; static void CtlScan2_setProcMode(CtlScan2 *self) {} static void CtlScan2_compute_next_data_frame(CtlScan2 *self) { PmEvent *buffer; int i, count, midichnl; buffer = Server_getMidiEventBuffer((Server *)self->server); count = Server_getMidiEventCount((Server *)self->server); if (count > 0) { PyObject *tup; for (i=count-1; i>=0; i--) { int status = Pm_MessageStatus(buffer[i].message); // Temp note event holders int number = Pm_MessageData1(buffer[i].message); int value = Pm_MessageData2(buffer[i].message); if ((status & 0xF0) == 0xB0) { midichnl = status - 0xB0 + 1; if (number != self->ctlnumber || midichnl != self->midichnl) { self->ctlnumber = number; self->midichnl = midichnl; tup = PyTuple_New(2); PyTuple_SetItem(tup, 0, PyInt_FromLong(self->ctlnumber)); PyTuple_SetItem(tup, 1, PyInt_FromLong(self->midichnl)); PyObject_Call((PyObject *)self->callable, tup, NULL); } if (self->toprint == 1) printf("ctl number : %i, ctl value : %i, midi channel : %i\n", self->ctlnumber, value, midichnl); } } } } static int CtlScan2_traverse(CtlScan2 *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->callable); return 0; } static int CtlScan2_clear(CtlScan2 *self) { pyo_CLEAR Py_CLEAR(self->callable); return 0; } static void CtlScan2_dealloc(CtlScan2* self) { pyo_DEALLOC CtlScan2_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * CtlScan2_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *calltmp=NULL; CtlScan2 *self; self = (CtlScan2 *)type->tp_alloc(type, 0); self->ctlnumber = self->midichnl = -1; self->toprint = 1; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, CtlScan2_compute_next_data_frame); self->mode_func_ptr = CtlScan2_setProcMode; static char *kwlist[] = {"callable", "toprint", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &calltmp, &self->toprint)) Py_RETURN_NONE; if (calltmp) { PyObject_CallMethod((PyObject *)self, "setFunction", "O", calltmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); return (PyObject *)self; } static PyObject * CtlScan2_getServer(CtlScan2* self) { GET_SERVER }; static PyObject * CtlScan2_getStream(CtlScan2* self) { GET_STREAM }; static PyObject * CtlScan2_play(CtlScan2 *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * CtlScan2_stop(CtlScan2 *self) { STOP }; static PyObject * CtlScan2_reset(CtlScan2 *self) { self->ctlnumber = self->midichnl = -1; Py_INCREF(Py_None); return Py_None; }; static PyObject * CtlScan2_setFunction(CtlScan2 *self, PyObject *arg) { PyObject *tmp; if (! PyCallable_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function."); Py_INCREF(Py_None); return Py_None; } tmp = arg; Py_XDECREF(self->callable); Py_INCREF(tmp); self->callable = tmp; Py_INCREF(Py_None); return Py_None; } static PyObject * CtlScan2_setToprint(CtlScan2 *self, PyObject *arg) { if (PyInt_Check(arg)) { self->toprint = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef CtlScan2_members[] = { {"server", T_OBJECT_EX, offsetof(CtlScan2, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(CtlScan2, stream), 0, "Stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef CtlScan2_methods[] = { {"getServer", (PyCFunction)CtlScan2_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)CtlScan2_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)CtlScan2_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)CtlScan2_stop, METH_NOARGS, "Stops computing."}, {"reset", (PyCFunction)CtlScan2_reset, METH_NOARGS, "Reset scanned numbers."}, {"setFunction", (PyCFunction)CtlScan2_setFunction, METH_O, "Sets the function to be called."}, {"setToprint", (PyCFunction)CtlScan2_setToprint, METH_O, "If True, print values to the console."}, {NULL} /* Sentinel */ }; PyTypeObject CtlScan2Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.CtlScan2_base", /*tp_name*/ sizeof(CtlScan2), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)CtlScan2_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "CtlScan2 objects. Retreive midi channel and controller numbers from a midi input.", /* tp_doc */ (traverseproc)CtlScan2_traverse, /* tp_traverse */ (inquiry)CtlScan2_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ CtlScan2_methods, /* tp_methods */ CtlScan2_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ CtlScan2_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD int ctlnumber; int channel; int interp; MYFLT minscale; MYFLT maxscale; MYFLT value; MYFLT oldValue; MYFLT sampleToSec; int modebuffer[2]; } Midictl; static void Midictl_postprocessing_ii(Midictl *self) { POST_PROCESSING_II }; static void Midictl_postprocessing_ai(Midictl *self) { POST_PROCESSING_AI }; static void Midictl_postprocessing_ia(Midictl *self) { POST_PROCESSING_IA }; static void Midictl_postprocessing_aa(Midictl *self) { POST_PROCESSING_AA }; static void Midictl_postprocessing_ireva(Midictl *self) { POST_PROCESSING_IREVA }; static void Midictl_postprocessing_areva(Midictl *self) { POST_PROCESSING_AREVA }; static void Midictl_postprocessing_revai(Midictl *self) { POST_PROCESSING_REVAI }; static void Midictl_postprocessing_revaa(Midictl *self) { POST_PROCESSING_REVAA }; static void Midictl_postprocessing_revareva(Midictl *self) { POST_PROCESSING_REVAREVA }; static void Midictl_setProcMode(Midictl *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Midictl_postprocessing_ii; break; case 1: self->muladd_func_ptr = Midictl_postprocessing_ai; break; case 2: self->muladd_func_ptr = Midictl_postprocessing_revai; break; case 10: self->muladd_func_ptr = Midictl_postprocessing_ia; break; case 11: self->muladd_func_ptr = Midictl_postprocessing_aa; break; case 12: self->muladd_func_ptr = Midictl_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Midictl_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Midictl_postprocessing_areva; break; case 22: self->muladd_func_ptr = Midictl_postprocessing_revareva; break; } } // Take MIDI events and translate them... void translateMidi(Midictl *self, PmEvent *buffer, int count) { int i, ok; for (i=count-1; i>=0; i--) { int status = Pm_MessageStatus(buffer[i].message); // Temp note event holders int number = Pm_MessageData1(buffer[i].message); int value = Pm_MessageData2(buffer[i].message); if (self->channel == 0) { if ((status & 0xF0) == 0xB0) ok = 1; else ok = 0; } else { if (status == (0xB0 | (self->channel - 1))) ok = 1; else ok = 0; } if (ok == 1 && number == self->ctlnumber) { self->oldValue = self->value; self->value = (value / 127.) * (self->maxscale - self->minscale) + self->minscale; break; } } } static void Midictl_compute_next_data_frame(Midictl *self) { PmEvent *tmp; int i, count; MYFLT step; tmp = Server_getMidiEventBuffer((Server *)self->server); count = Server_getMidiEventCount((Server *)self->server); if (count > 0) translateMidi((Midictl *)self, tmp, count); if (self->interp == 0) { for (i=0; ibufsize; i++) { self->data[i] = self->value; } } else { step = (self->value - self->oldValue) / self->bufsize; for (i=0; ibufsize; i++) { self->data[i] = self->oldValue + step; } } (*self->muladd_func_ptr)(self); } static int Midictl_traverse(Midictl *self, visitproc visit, void *arg) { pyo_VISIT return 0; } static int Midictl_clear(Midictl *self) { pyo_CLEAR return 0; } static void Midictl_dealloc(Midictl* self) { pyo_DEALLOC Midictl_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Midictl_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *multmp=NULL, *addtmp=NULL; Midictl *self; self = (Midictl *)type->tp_alloc(type, 0); self->channel = 0; self->value = 0.; self->oldValue = 0.; self->minscale = 0.; self->maxscale = 1.; self->interp = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Midictl_compute_next_data_frame); self->mode_func_ptr = Midictl_setProcMode; static char *kwlist[] = {"ctlnumber", "minscale", "maxscale", "init", "channel", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_I_FFFIOO, kwlist, &self->ctlnumber, &self->minscale, &self->maxscale, &self->oldValue, &self->channel, &multmp, &addtmp)) Py_RETURN_NONE; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->value = self->oldValue; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Midictl_getServer(Midictl* self) { GET_SERVER }; static PyObject * Midictl_getStream(Midictl* self) { GET_STREAM }; static PyObject * Midictl_setMul(Midictl *self, PyObject *arg) { SET_MUL }; static PyObject * Midictl_setAdd(Midictl *self, PyObject *arg) { SET_ADD }; static PyObject * Midictl_setSub(Midictl *self, PyObject *arg) { SET_SUB }; static PyObject * Midictl_setDiv(Midictl *self, PyObject *arg) { SET_DIV }; static PyObject * Midictl_play(Midictl *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Midictl_stop(Midictl *self) { STOP }; static PyObject * Midictl_multiply(Midictl *self, PyObject *arg) { MULTIPLY }; static PyObject * Midictl_inplace_multiply(Midictl *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Midictl_add(Midictl *self, PyObject *arg) { ADD }; static PyObject * Midictl_inplace_add(Midictl *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Midictl_sub(Midictl *self, PyObject *arg) { SUB }; static PyObject * Midictl_inplace_sub(Midictl *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Midictl_div(Midictl *self, PyObject *arg) { DIV }; static PyObject * Midictl_inplace_div(Midictl *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Midictl_setInterpolation(Midictl *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isNum = PyInt_Check(arg); if (isNum == 1) { tmp = PyInt_AsLong(arg); if (tmp == 0) self->interp = 0; else self->interp = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * Midictl_setValue(Midictl *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isNum = PyNumber_Check(arg); if (isNum == 1) { tmp = PyFloat_AsDouble(arg); self->oldValue = self->value = tmp; } Py_INCREF(Py_None); return Py_None; } static PyObject * Midictl_setMinScale(Midictl *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isNum = PyNumber_Check(arg); if (isNum == 1) { tmp = PyFloat_AsDouble(arg); self->minscale = tmp; } Py_INCREF(Py_None); return Py_None; } static PyObject * Midictl_setMaxScale(Midictl *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isNum = PyNumber_Check(arg); if (isNum == 1) { tmp = PyFloat_AsDouble(arg); self->maxscale = tmp; } Py_INCREF(Py_None); return Py_None; } static PyObject * Midictl_setCtlNumber(Midictl *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { tmp = PyInt_AsLong(arg); if (tmp >= 0 && tmp < 128) self->ctlnumber = tmp; } Py_INCREF(Py_None); return Py_None; } static PyObject * Midictl_setChannel(Midictl *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { tmp = PyInt_AsLong(arg); if (tmp >= 0 && tmp < 128) self->channel = tmp; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Midictl_members[] = { {"server", T_OBJECT_EX, offsetof(Midictl, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Midictl, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Midictl, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Midictl, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Midictl_methods[] = { {"getServer", (PyCFunction)Midictl_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Midictl_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Midictl_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Midictl_stop, METH_NOARGS, "Stops computing."}, {"setInterpolation", (PyCFunction)Midictl_setInterpolation, METH_O, "Activate/Deactivate interpolation."}, {"setValue", (PyCFunction)Midictl_setValue, METH_O, "Resets audio stream to value in argument."}, {"setMinScale", (PyCFunction)Midictl_setMinScale, METH_O, "Sets the minimum value of scaling."}, {"setMaxScale", (PyCFunction)Midictl_setMaxScale, METH_O, "Sets the maximum value of scaling."}, {"setCtlNumber", (PyCFunction)Midictl_setCtlNumber, METH_O, "Sets the controller number."}, {"setChannel", (PyCFunction)Midictl_setChannel, METH_O, "Sets the midi channel."}, {"setMul", (PyCFunction)Midictl_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Midictl_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Midictl_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Midictl_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Midictl_as_number = { (binaryfunc)Midictl_add, /*nb_add*/ (binaryfunc)Midictl_sub, /*nb_subtract*/ (binaryfunc)Midictl_multiply, /*nb_multiply*/ (binaryfunc)Midictl_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Midictl_inplace_add, /*inplace_add*/ (binaryfunc)Midictl_inplace_sub, /*inplace_subtract*/ (binaryfunc)Midictl_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Midictl_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject MidictlType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Midictl_base", /*tp_name*/ sizeof(Midictl), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Midictl_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Midictl_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Midictl objects. Retreive audio from an input channel.", /* tp_doc */ (traverseproc)Midictl_traverse, /* tp_traverse */ (inquiry)Midictl_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Midictl_methods, /* tp_methods */ Midictl_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Midictl_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD int channel; int scale; /* 0 = midi, 1 = transpo */ MYFLT range; MYFLT value; MYFLT oldValue; MYFLT sampleToSec; int modebuffer[2]; } Bendin; static void Bendin_postprocessing_ii(Bendin *self) { POST_PROCESSING_II }; static void Bendin_postprocessing_ai(Bendin *self) { POST_PROCESSING_AI }; static void Bendin_postprocessing_ia(Bendin *self) { POST_PROCESSING_IA }; static void Bendin_postprocessing_aa(Bendin *self) { POST_PROCESSING_AA }; static void Bendin_postprocessing_ireva(Bendin *self) { POST_PROCESSING_IREVA }; static void Bendin_postprocessing_areva(Bendin *self) { POST_PROCESSING_AREVA }; static void Bendin_postprocessing_revai(Bendin *self) { POST_PROCESSING_REVAI }; static void Bendin_postprocessing_revaa(Bendin *self) { POST_PROCESSING_REVAA }; static void Bendin_postprocessing_revareva(Bendin *self) { POST_PROCESSING_REVAREVA }; static void Bendin_setProcMode(Bendin *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Bendin_postprocessing_ii; break; case 1: self->muladd_func_ptr = Bendin_postprocessing_ai; break; case 2: self->muladd_func_ptr = Bendin_postprocessing_revai; break; case 10: self->muladd_func_ptr = Bendin_postprocessing_ia; break; case 11: self->muladd_func_ptr = Bendin_postprocessing_aa; break; case 12: self->muladd_func_ptr = Bendin_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Bendin_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Bendin_postprocessing_areva; break; case 22: self->muladd_func_ptr = Bendin_postprocessing_revareva; break; } } // Take MIDI events and translate them... void Bendin_translateMidi(Bendin *self, PmEvent *buffer, int count) { int i, ok; MYFLT val; for (i=count-1; i>=0; i--) { int status = Pm_MessageStatus(buffer[i].message); // Temp note event holders int number = Pm_MessageData1(buffer[i].message); int value = Pm_MessageData2(buffer[i].message); if (self->channel == 0) { if ((status & 0xF0) == 0xe0) ok = 1; else ok = 0; } else { if (status == (0xe0 | (self->channel - 1))) ok = 1; else ok = 0; } if (ok == 1) { self->oldValue = self->value; val = (number + (value << 7) - 8192) / 8192.0 * self->range; if (self->scale == 0) self->value = val; else self->value = MYPOW(1.0594630943593, val); break; } } } static void Bendin_compute_next_data_frame(Bendin *self) { PmEvent *tmp; int i, count; tmp = Server_getMidiEventBuffer((Server *)self->server); count = Server_getMidiEventCount((Server *)self->server); if (count > 0) Bendin_translateMidi((Bendin *)self, tmp, count); MYFLT step = (self->value - self->oldValue) / self->bufsize; for (i=0; ibufsize; i++) { self->data[i] = self->oldValue + step; } (*self->muladd_func_ptr)(self); } static int Bendin_traverse(Bendin *self, visitproc visit, void *arg) { pyo_VISIT return 0; } static int Bendin_clear(Bendin *self) { pyo_CLEAR return 0; } static void Bendin_dealloc(Bendin* self) { pyo_DEALLOC Bendin_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Bendin_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *multmp=NULL, *addtmp=NULL; Bendin *self; self = (Bendin *)type->tp_alloc(type, 0); self->channel = 0; self->scale = 0; self->value = 0.; self->oldValue = 0.; self->range = 2.; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Bendin_compute_next_data_frame); self->mode_func_ptr = Bendin_setProcMode; static char *kwlist[] = {"brange", "scale", "channel", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FIIOO, kwlist, &self->range, &self->scale, &self->channel, &multmp, &addtmp)) Py_RETURN_NONE; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (self->scale == 0) self->oldValue = self->value = 0.; else self->oldValue = self->value = 1.; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Bendin_getServer(Bendin* self) { GET_SERVER }; static PyObject * Bendin_getStream(Bendin* self) { GET_STREAM }; static PyObject * Bendin_setMul(Bendin *self, PyObject *arg) { SET_MUL }; static PyObject * Bendin_setAdd(Bendin *self, PyObject *arg) { SET_ADD }; static PyObject * Bendin_setSub(Bendin *self, PyObject *arg) { SET_SUB }; static PyObject * Bendin_setDiv(Bendin *self, PyObject *arg) { SET_DIV }; static PyObject * Bendin_play(Bendin *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Bendin_stop(Bendin *self) { STOP }; static PyObject * Bendin_multiply(Bendin *self, PyObject *arg) { MULTIPLY }; static PyObject * Bendin_inplace_multiply(Bendin *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Bendin_add(Bendin *self, PyObject *arg) { ADD }; static PyObject * Bendin_inplace_add(Bendin *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Bendin_sub(Bendin *self, PyObject *arg) { SUB }; static PyObject * Bendin_inplace_sub(Bendin *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Bendin_div(Bendin *self, PyObject *arg) { DIV }; static PyObject * Bendin_inplace_div(Bendin *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Bendin_setBrange(Bendin *self, PyObject *arg) { MYFLT tmp; ASSERT_ARG_NOT_NULL int isNum = PyNumber_Check(arg); if (isNum == 1) { tmp = PyFloat_AsDouble(arg); if (tmp >= 0.0 && tmp < 128.0) self->range = tmp; } Py_INCREF(Py_None); return Py_None; } static PyObject * Bendin_setChannel(Bendin *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { tmp = PyInt_AsLong(arg); if (tmp >= 0 && tmp < 128) self->channel = tmp; } Py_INCREF(Py_None); return Py_None; } static PyObject * Bendin_setScale(Bendin *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { tmp = PyInt_AsLong(arg); if (tmp == 0) self->scale = 0; else if (tmp == 1) self->scale = 1; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Bendin_members[] = { {"server", T_OBJECT_EX, offsetof(Bendin, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Bendin, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Bendin, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Bendin, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Bendin_methods[] = { {"getServer", (PyCFunction)Bendin_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Bendin_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Bendin_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Bendin_stop, METH_NOARGS, "Stops computing."}, {"setBrange", (PyCFunction)Bendin_setBrange, METH_O, "Sets the bending bipolar range."}, {"setScale", (PyCFunction)Bendin_setScale, METH_O, "Sets the output type, midi vs transpo."}, {"setChannel", (PyCFunction)Bendin_setChannel, METH_O, "Sets the midi channel."}, {"setMul", (PyCFunction)Bendin_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Bendin_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Bendin_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Bendin_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Bendin_as_number = { (binaryfunc)Bendin_add, /*nb_add*/ (binaryfunc)Bendin_sub, /*nb_subtract*/ (binaryfunc)Bendin_multiply, /*nb_multiply*/ (binaryfunc)Bendin_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Bendin_inplace_add, /*inplace_add*/ (binaryfunc)Bendin_inplace_sub, /*inplace_subtract*/ (binaryfunc)Bendin_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Bendin_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject BendinType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Bendin_base", /*tp_name*/ sizeof(Bendin), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Bendin_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Bendin_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Bendin objects. Retreive audio from an input channel.", /* tp_doc */ (traverseproc)Bendin_traverse, /* tp_traverse */ (inquiry)Bendin_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Bendin_methods, /* tp_methods */ Bendin_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Bendin_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD int channel; MYFLT minscale; MYFLT maxscale; MYFLT value; MYFLT oldValue; MYFLT sampleToSec; int modebuffer[2]; } Touchin; static void Touchin_postprocessing_ii(Touchin *self) { POST_PROCESSING_II }; static void Touchin_postprocessing_ai(Touchin *self) { POST_PROCESSING_AI }; static void Touchin_postprocessing_ia(Touchin *self) { POST_PROCESSING_IA }; static void Touchin_postprocessing_aa(Touchin *self) { POST_PROCESSING_AA }; static void Touchin_postprocessing_ireva(Touchin *self) { POST_PROCESSING_IREVA }; static void Touchin_postprocessing_areva(Touchin *self) { POST_PROCESSING_AREVA }; static void Touchin_postprocessing_revai(Touchin *self) { POST_PROCESSING_REVAI }; static void Touchin_postprocessing_revaa(Touchin *self) { POST_PROCESSING_REVAA }; static void Touchin_postprocessing_revareva(Touchin *self) { POST_PROCESSING_REVAREVA }; static void Touchin_setProcMode(Touchin *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Touchin_postprocessing_ii; break; case 1: self->muladd_func_ptr = Touchin_postprocessing_ai; break; case 2: self->muladd_func_ptr = Touchin_postprocessing_revai; break; case 10: self->muladd_func_ptr = Touchin_postprocessing_ia; break; case 11: self->muladd_func_ptr = Touchin_postprocessing_aa; break; case 12: self->muladd_func_ptr = Touchin_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Touchin_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Touchin_postprocessing_areva; break; case 22: self->muladd_func_ptr = Touchin_postprocessing_revareva; break; } } // Take MIDI events and translate them... void Touchin_translateMidi(Touchin *self, PmEvent *buffer, int count) { int i, ok; for (i=count-1; i>=0; i--) { int status = Pm_MessageStatus(buffer[i].message); // Temp note event holders int number = Pm_MessageData1(buffer[i].message); /* int value = Pm_MessageData2(buffer[i].message); */ if (self->channel == 0) { if ((status & 0xF0) == 0xd0) ok = 1; else ok = 0; } else { if (status == (0xd0 | (self->channel - 1))) ok = 1; else ok = 0; } if (ok == 1) { self->oldValue = self->value; self->value = (number / 127.) * (self->maxscale - self->minscale) + self->minscale; break; } } } static void Touchin_compute_next_data_frame(Touchin *self) { PmEvent *tmp; int i, count; tmp = Server_getMidiEventBuffer((Server *)self->server); count = Server_getMidiEventCount((Server *)self->server); if (count > 0) Touchin_translateMidi((Touchin *)self, tmp, count); MYFLT step = (self->value - self->oldValue) / self->bufsize; for (i=0; ibufsize; i++) { self->data[i] = self->oldValue + step; } (*self->muladd_func_ptr)(self); } static int Touchin_traverse(Touchin *self, visitproc visit, void *arg) { pyo_VISIT return 0; } static int Touchin_clear(Touchin *self) { pyo_CLEAR return 0; } static void Touchin_dealloc(Touchin* self) { pyo_DEALLOC Touchin_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Touchin_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *multmp=NULL, *addtmp=NULL; Touchin *self; self = (Touchin *)type->tp_alloc(type, 0); self->channel = 0; self->value = 0.; self->oldValue = 0.; self->minscale = 0.; self->maxscale = 1.; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Touchin_compute_next_data_frame); self->mode_func_ptr = Touchin_setProcMode; static char *kwlist[] = {"minscale", "maxscale", "init", "channel", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FFFIOO, kwlist, &self->minscale, &self->maxscale, &self->oldValue, &self->channel, &multmp, &addtmp)) Py_RETURN_NONE; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->value = self->oldValue; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Touchin_getServer(Touchin* self) { GET_SERVER }; static PyObject * Touchin_getStream(Touchin* self) { GET_STREAM }; static PyObject * Touchin_setMul(Touchin *self, PyObject *arg) { SET_MUL }; static PyObject * Touchin_setAdd(Touchin *self, PyObject *arg) { SET_ADD }; static PyObject * Touchin_setSub(Touchin *self, PyObject *arg) { SET_SUB }; static PyObject * Touchin_setDiv(Touchin *self, PyObject *arg) { SET_DIV }; static PyObject * Touchin_play(Touchin *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Touchin_stop(Touchin *self) { STOP }; static PyObject * Touchin_multiply(Touchin *self, PyObject *arg) { MULTIPLY }; static PyObject * Touchin_inplace_multiply(Touchin *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Touchin_add(Touchin *self, PyObject *arg) { ADD }; static PyObject * Touchin_inplace_add(Touchin *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Touchin_sub(Touchin *self, PyObject *arg) { SUB }; static PyObject * Touchin_inplace_sub(Touchin *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Touchin_div(Touchin *self, PyObject *arg) { DIV }; static PyObject * Touchin_inplace_div(Touchin *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Touchin_setMinScale(Touchin *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isNum = PyNumber_Check(arg); if (isNum == 1) { tmp = PyFloat_AsDouble(arg); self->minscale = tmp; } Py_INCREF(Py_None); return Py_None; } static PyObject * Touchin_setMaxScale(Touchin *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isNum = PyNumber_Check(arg); if (isNum == 1) { tmp = PyFloat_AsDouble(arg); self->maxscale = tmp; } Py_INCREF(Py_None); return Py_None; } static PyObject * Touchin_setChannel(Touchin *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { tmp = PyInt_AsLong(arg); if (tmp >= 0 && tmp < 128) self->channel = tmp; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Touchin_members[] = { {"server", T_OBJECT_EX, offsetof(Touchin, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Touchin, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Touchin, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Touchin, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Touchin_methods[] = { {"getServer", (PyCFunction)Touchin_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Touchin_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Touchin_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Touchin_stop, METH_NOARGS, "Stops computing."}, {"setMinScale", (PyCFunction)Touchin_setMinScale, METH_O, "Sets the minimum value of scaling."}, {"setMaxScale", (PyCFunction)Touchin_setMaxScale, METH_O, "Sets the maximum value of scaling."}, {"setChannel", (PyCFunction)Touchin_setChannel, METH_O, "Sets the midi channel."}, {"setMul", (PyCFunction)Touchin_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Touchin_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Touchin_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Touchin_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Touchin_as_number = { (binaryfunc)Touchin_add, /*nb_add*/ (binaryfunc)Touchin_sub, /*nb_subtract*/ (binaryfunc)Touchin_multiply, /*nb_multiply*/ (binaryfunc)Touchin_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Touchin_inplace_add, /*inplace_add*/ (binaryfunc)Touchin_inplace_sub, /*inplace_subtract*/ (binaryfunc)Touchin_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Touchin_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TouchinType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Touchin_base", /*tp_name*/ sizeof(Touchin), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Touchin_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Touchin_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Touchin objects. Retrieve the signal of an aftertouch midi controller.", /* tp_doc */ (traverseproc)Touchin_traverse, /* tp_traverse */ (inquiry)Touchin_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Touchin_methods, /* tp_methods */ Touchin_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Touchin_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD int channel; MYFLT value; int modebuffer[2]; } Programin; static void Programin_postprocessing_ii(Programin *self) { POST_PROCESSING_II }; static void Programin_postprocessing_ai(Programin *self) { POST_PROCESSING_AI }; static void Programin_postprocessing_ia(Programin *self) { POST_PROCESSING_IA }; static void Programin_postprocessing_aa(Programin *self) { POST_PROCESSING_AA }; static void Programin_postprocessing_ireva(Programin *self) { POST_PROCESSING_IREVA }; static void Programin_postprocessing_areva(Programin *self) { POST_PROCESSING_AREVA }; static void Programin_postprocessing_revai(Programin *self) { POST_PROCESSING_REVAI }; static void Programin_postprocessing_revaa(Programin *self) { POST_PROCESSING_REVAA }; static void Programin_postprocessing_revareva(Programin *self) { POST_PROCESSING_REVAREVA }; static void Programin_setProcMode(Programin *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Programin_postprocessing_ii; break; case 1: self->muladd_func_ptr = Programin_postprocessing_ai; break; case 2: self->muladd_func_ptr = Programin_postprocessing_revai; break; case 10: self->muladd_func_ptr = Programin_postprocessing_ia; break; case 11: self->muladd_func_ptr = Programin_postprocessing_aa; break; case 12: self->muladd_func_ptr = Programin_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Programin_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Programin_postprocessing_areva; break; case 22: self->muladd_func_ptr = Programin_postprocessing_revareva; break; } } // Take MIDI events and translate them... void Programin_translateMidi(Programin *self, PmEvent *buffer, int count) { int i, ok; for (i=count-1; i>=0; i--) { int status = Pm_MessageStatus(buffer[i].message); // Temp note event holders int number = Pm_MessageData1(buffer[i].message); if (self->channel == 0) { if ((status & 0xF0) == 0xc0) ok = 1; else ok = 0; } else { if (status == (0xc0 | (self->channel - 1))) ok = 1; else ok = 0; } if (ok == 1) { self->value = (MYFLT)number; break; } } } static void Programin_compute_next_data_frame(Programin *self) { PmEvent *tmp; int i, count; tmp = Server_getMidiEventBuffer((Server *)self->server); count = Server_getMidiEventCount((Server *)self->server); if (count > 0) Programin_translateMidi((Programin *)self, tmp, count); for (i=0; ibufsize; i++) { self->data[i] = self->value; } (*self->muladd_func_ptr)(self); } static int Programin_traverse(Programin *self, visitproc visit, void *arg) { pyo_VISIT return 0; } static int Programin_clear(Programin *self) { pyo_CLEAR return 0; } static void Programin_dealloc(Programin* self) { pyo_DEALLOC Programin_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Programin_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *multmp=NULL, *addtmp=NULL; Programin *self; self = (Programin *)type->tp_alloc(type, 0); self->channel = 0; self->value = 0.; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Programin_compute_next_data_frame); self->mode_func_ptr = Programin_setProcMode; static char *kwlist[] = {"channel", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "iOO", kwlist, &self->channel, &multmp, &addtmp)) Py_RETURN_NONE; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Programin_getServer(Programin* self) { GET_SERVER }; static PyObject * Programin_getStream(Programin* self) { GET_STREAM }; static PyObject * Programin_setMul(Programin *self, PyObject *arg) { SET_MUL }; static PyObject * Programin_setAdd(Programin *self, PyObject *arg) { SET_ADD }; static PyObject * Programin_setSub(Programin *self, PyObject *arg) { SET_SUB }; static PyObject * Programin_setDiv(Programin *self, PyObject *arg) { SET_DIV }; static PyObject * Programin_play(Programin *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Programin_stop(Programin *self) { STOP }; static PyObject * Programin_multiply(Programin *self, PyObject *arg) { MULTIPLY }; static PyObject * Programin_inplace_multiply(Programin *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Programin_add(Programin *self, PyObject *arg) { ADD }; static PyObject * Programin_inplace_add(Programin *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Programin_sub(Programin *self, PyObject *arg) { SUB }; static PyObject * Programin_inplace_sub(Programin *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Programin_div(Programin *self, PyObject *arg) { DIV }; static PyObject * Programin_inplace_div(Programin *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Programin_setChannel(Programin *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { tmp = PyInt_AsLong(arg); if (tmp >= 0 && tmp < 128) self->channel = tmp; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Programin_members[] = { {"server", T_OBJECT_EX, offsetof(Programin, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Programin, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Programin, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Programin, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Programin_methods[] = { {"getServer", (PyCFunction)Programin_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Programin_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Programin_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Programin_stop, METH_NOARGS, "Stops computing."}, {"setChannel", (PyCFunction)Programin_setChannel, METH_O, "Sets the midi channel."}, {"setMul", (PyCFunction)Programin_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Programin_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Programin_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Programin_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Programin_as_number = { (binaryfunc)Programin_add, /*nb_add*/ (binaryfunc)Programin_sub, /*nb_subtract*/ (binaryfunc)Programin_multiply, /*nb_multiply*/ (binaryfunc)Programin_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Programin_inplace_add, /*inplace_add*/ (binaryfunc)Programin_inplace_sub, /*inplace_subtract*/ (binaryfunc)Programin_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Programin_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject PrograminType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Programin_base", /*tp_name*/ sizeof(Programin), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Programin_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Programin_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Programin objects. Retrieve the signal of a program change midi controller.", /* tp_doc */ (traverseproc)Programin_traverse, /* tp_traverse */ (inquiry)Programin_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Programin_methods, /* tp_methods */ Programin_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Programin_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD int *notebuf; /* pitch, velocity, ... */ int voices; int vcount; int scale; /* 0 = midi, 1 = hertz, 2 = transpo */ int first; int last; int centralkey; int channel; int stealing; MYFLT *trigger_streams; } MidiNote; static void MidiNote_setProcMode(MidiNote *self) {}; int pitchIsIn(int *buf, int pitch, int len) { int i; int isIn = 0; for (i=0; ichannel == 0) { if ((status & 0xF0) == 0x90 || (status & 0xF0) == 0x80) ok = 1; else ok = 0; } else { if ( status == (0x90 | (self->channel - 1)) || status == (0x80 | (self->channel - 1))) ok = 1; else ok = 0; } if (ok == 1) { if ((status & 0xF0) == 0x80) kind = 0; else if ((status & 0xF0) == 0x90 && velocity == 0) kind = 0; else kind = 1; if (pitchIsIn(self->notebuf, pitch, self->voices) == 0 && kind == 1 && pitch >= self->first && pitch <= self->last) { //printf("%i, %i, %i\n", status, pitch, velocity); if (!self->stealing) { voice = nextEmptyVoice(self->notebuf, self->vcount, self->voices); if (voice != -1) { self->vcount = voice; self->notebuf[voice*2] = pitch; self->notebuf[voice*2+1] = velocity; self->trigger_streams[self->bufsize*(self->vcount*2)] = 1.0; } } else { self->vcount = (self->vcount + 1) % self->voices; self->notebuf[self->vcount*2] = pitch; self->notebuf[self->vcount*2+1] = velocity; self->trigger_streams[self->bufsize*(self->vcount*2)] = 1.0; } } else if (pitchIsIn(self->notebuf, pitch, self->voices) == 1 && kind == 0 && pitch >= self->first && pitch <= self->last) { //printf("%i, %i, %i\n", status, pitch, velocity); voice = whichVoice(self->notebuf, pitch, self->voices); self->notebuf[voice*2] = -1; self->notebuf[voice*2+1] = 0.; self->trigger_streams[self->bufsize*(voice*2+1)] = 1.0; } } } } static void MidiNote_compute_next_data_frame(MidiNote *self) { PmEvent *tmp; int i, count; for (i=0; ibufsize*self->voices*2; i++) { self->trigger_streams[i] = 0.0; } tmp = Server_getMidiEventBuffer((Server *)self->server); count = Server_getMidiEventCount((Server *)self->server); if (count > 0) grabMidiNotes((MidiNote *)self, tmp, count); } static int MidiNote_traverse(MidiNote *self, visitproc visit, void *arg) { pyo_VISIT return 0; } static int MidiNote_clear(MidiNote *self) { pyo_CLEAR return 0; } static void MidiNote_dealloc(MidiNote* self) { pyo_DEALLOC free(self->notebuf); free(self->trigger_streams); MidiNote_clear(self); self->ob_type->tp_free((PyObject*)self); } static MYFLT * MidiNote_get_trigger_buffer(MidiNote *self) { return self->trigger_streams; } static PyObject * MidiNote_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MidiNote *self; self = (MidiNote *)type->tp_alloc(type, 0); self->voices = 10; self->vcount = 0; self->scale = 0; self->first = 0; self->last = 127; self->channel = 0; self->stealing = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, MidiNote_compute_next_data_frame); self->mode_func_ptr = MidiNote_setProcMode; static char *kwlist[] = {"voices", "scale", "first", "last", "channel", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iiiii", kwlist, &self->voices, &self->scale, &self->first, &self->last, &self->channel)) Py_RETURN_NONE; PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->notebuf = (int *)realloc(self->notebuf, self->voices * 2 * sizeof(int)); self->trigger_streams = (MYFLT *)realloc(self->trigger_streams, self->bufsize * self->voices * 2 * sizeof(MYFLT)); for (i=0; ibufsize*self->voices*2; i++) { self->trigger_streams[i] = 0.0; } for (i=0; ivoices; i++) { self->notebuf[i*2] = -1; self->notebuf[i*2+1] = 0; } self->centralkey = (self->first + self->last) / 2; (*self->mode_func_ptr)(self); return (PyObject *)self; } MYFLT MidiNote_getValue(MidiNote *self, int voice, int which) { MYFLT val = -1.0; int midival = self->notebuf[voice*2+which]; if (which == 0 && midival != -1) { if (self->scale == 0) val = midival; else if (self->scale == 1) val = 8.1757989156437 * MYPOW(1.0594630943593, midival); else if (self->scale == 2) val = MYPOW(1.0594630943593, midival - self->centralkey); } else if (which == 0) val = (MYFLT)midival; else if (which == 1) val = (MYFLT)midival / 127.; return val; } static PyObject * MidiNote_getServer(MidiNote* self) { GET_SERVER }; static PyObject * MidiNote_getStream(MidiNote* self) { GET_STREAM }; static PyObject * MidiNote_play(MidiNote *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * MidiNote_stop(MidiNote *self) { STOP }; static PyObject * MidiNote_setChannel(MidiNote *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { tmp = PyInt_AsLong(arg); if (tmp >= 0 && tmp < 128) self->channel = tmp; } Py_INCREF(Py_None); return Py_None; } static PyObject * MidiNote_setCentralKey(MidiNote *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { tmp = PyInt_AsLong(arg); if (tmp >= self->first && tmp <= self->last) self->centralkey = tmp; } Py_INCREF(Py_None); return Py_None; } static PyObject * MidiNote_setStealing(MidiNote *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) self->stealing = PyInt_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyMemberDef MidiNote_members[] = { {"server", T_OBJECT_EX, offsetof(MidiNote, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(MidiNote, stream), 0, "Stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef MidiNote_methods[] = { {"getServer", (PyCFunction)MidiNote_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)MidiNote_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)MidiNote_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)MidiNote_stop, METH_NOARGS, "Stops computing."}, {"setChannel", (PyCFunction)MidiNote_setChannel, METH_O, "Sets the midi channel."}, {"setCentralKey", (PyCFunction)MidiNote_setCentralKey, METH_O, "Sets the midi key where there is no transposition."}, {"setStealing", (PyCFunction)MidiNote_setStealing, METH_O, "Sets the stealing mode."}, {NULL} /* Sentinel */ }; PyTypeObject MidiNoteType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.MidiNote_base", /*tp_name*/ sizeof(MidiNote), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)MidiNote_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "MidiNote objects. Retreive midi note from a midi input.", /* tp_doc */ (traverseproc)MidiNote_traverse, /* tp_traverse */ (inquiry)MidiNote_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ MidiNote_methods, /* tp_methods */ MidiNote_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MidiNote_new, /* tp_new */ }; /* Notein streamer */ typedef struct { pyo_audio_HEAD MidiNote *handler; int modebuffer[2]; int voice; int mode; /* 0 = pitch, 1 = velocity */ } Notein; static void Notein_postprocessing_ii(Notein *self) { POST_PROCESSING_II }; static void Notein_postprocessing_ai(Notein *self) { POST_PROCESSING_AI }; static void Notein_postprocessing_ia(Notein *self) { POST_PROCESSING_IA }; static void Notein_postprocessing_aa(Notein *self) { POST_PROCESSING_AA }; static void Notein_postprocessing_ireva(Notein *self) { POST_PROCESSING_IREVA }; static void Notein_postprocessing_areva(Notein *self) { POST_PROCESSING_AREVA }; static void Notein_postprocessing_revai(Notein *self) { POST_PROCESSING_REVAI }; static void Notein_postprocessing_revaa(Notein *self) { POST_PROCESSING_REVAA }; static void Notein_postprocessing_revareva(Notein *self) { POST_PROCESSING_REVAREVA }; static void Notein_setProcMode(Notein *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Notein_postprocessing_ii; break; case 1: self->muladd_func_ptr = Notein_postprocessing_ai; break; case 2: self->muladd_func_ptr = Notein_postprocessing_revai; break; case 10: self->muladd_func_ptr = Notein_postprocessing_ia; break; case 11: self->muladd_func_ptr = Notein_postprocessing_aa; break; case 12: self->muladd_func_ptr = Notein_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Notein_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Notein_postprocessing_areva; break; case 22: self->muladd_func_ptr = Notein_postprocessing_revareva; break; } } static void Notein_compute_next_data_frame(Notein *self) { int i; MYFLT tmp = MidiNote_getValue(self->handler, self->voice, self->mode); if (self->mode == 0 && tmp != -1) { for (i=0; ibufsize; i++) { self->data[i] = tmp; } } else if (self->mode == 1) { for (i=0; ibufsize; i++) { self->data[i] = tmp; } (*self->muladd_func_ptr)(self); } } static int Notein_traverse(Notein *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->handler); return 0; } static int Notein_clear(Notein *self) { pyo_CLEAR Py_CLEAR(self->handler); return 0; } static void Notein_dealloc(Notein* self) { pyo_DEALLOC Notein_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Notein_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *handlertmp=NULL, *multmp=NULL, *addtmp=NULL; Notein *self; self = (Notein *)type->tp_alloc(type, 0); self->voice = 0; self->mode = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Notein_compute_next_data_frame); self->mode_func_ptr = Notein_setProcMode; static char *kwlist[] = {"handler", "voice", "mode", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iiOO", kwlist, &handlertmp, &self->voice, &self->mode, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->handler); Py_INCREF(handlertmp); self->handler = (MidiNote *)handlertmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Notein_getServer(Notein* self) { GET_SERVER }; static PyObject * Notein_getStream(Notein* self) { GET_STREAM }; static PyObject * Notein_setMul(Notein *self, PyObject *arg) { SET_MUL }; static PyObject * Notein_setAdd(Notein *self, PyObject *arg) { SET_ADD }; static PyObject * Notein_setSub(Notein *self, PyObject *arg) { SET_SUB }; static PyObject * Notein_setDiv(Notein *self, PyObject *arg) { SET_DIV }; static PyObject * Notein_play(Notein *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Notein_stop(Notein *self) { STOP }; static PyObject * Notein_multiply(Notein *self, PyObject *arg) { MULTIPLY }; static PyObject * Notein_inplace_multiply(Notein *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Notein_add(Notein *self, PyObject *arg) { ADD }; static PyObject * Notein_inplace_add(Notein *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Notein_sub(Notein *self, PyObject *arg) { SUB }; static PyObject * Notein_inplace_sub(Notein *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Notein_div(Notein *self, PyObject *arg) { DIV }; static PyObject * Notein_inplace_div(Notein *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Notein_members[] = { {"server", T_OBJECT_EX, offsetof(Notein, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Notein, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Notein, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Notein, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Notein_methods[] = { {"getServer", (PyCFunction)Notein_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Notein_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Notein_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Notein_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Notein_setMul, METH_O, "Sets Notein mul factor."}, {"setAdd", (PyCFunction)Notein_setAdd, METH_O, "Sets Notein add factor."}, {"setSub", (PyCFunction)Notein_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Notein_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Notein_as_number = { (binaryfunc)Notein_add, /*nb_add*/ (binaryfunc)Notein_sub, /*nb_subtract*/ (binaryfunc)Notein_multiply, /*nb_multiply*/ (binaryfunc)Notein_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Notein_inplace_add, /*inplace_add*/ (binaryfunc)Notein_inplace_sub, /*inplace_subtract*/ (binaryfunc)Notein_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Notein_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject NoteinType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Notein_base", /*tp_name*/ sizeof(Notein), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Notein_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Notein_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Notein objects. Stream pitch or velocity from a Notein voice.", /* tp_doc */ (traverseproc)Notein_traverse, /* tp_traverse */ (inquiry)Notein_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Notein_methods, /* tp_methods */ Notein_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Notein_new, /* tp_new */ }; /* NoteinTrig trig streamer */ typedef struct { pyo_audio_HEAD MidiNote *handler; int modebuffer[2]; int voice; int mode; /* 0 = noteon, 1 = noteoff */ } NoteinTrig; static void NoteinTrig_postprocessing_ii(NoteinTrig *self) { POST_PROCESSING_II }; static void NoteinTrig_postprocessing_ai(NoteinTrig *self) { POST_PROCESSING_AI }; static void NoteinTrig_postprocessing_ia(NoteinTrig *self) { POST_PROCESSING_IA }; static void NoteinTrig_postprocessing_aa(NoteinTrig *self) { POST_PROCESSING_AA }; static void NoteinTrig_postprocessing_ireva(NoteinTrig *self) { POST_PROCESSING_IREVA }; static void NoteinTrig_postprocessing_areva(NoteinTrig *self) { POST_PROCESSING_AREVA }; static void NoteinTrig_postprocessing_revai(NoteinTrig *self) { POST_PROCESSING_REVAI }; static void NoteinTrig_postprocessing_revaa(NoteinTrig *self) { POST_PROCESSING_REVAA }; static void NoteinTrig_postprocessing_revareva(NoteinTrig *self) { POST_PROCESSING_REVAREVA }; static void NoteinTrig_setProcMode(NoteinTrig *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = NoteinTrig_postprocessing_ii; break; case 1: self->muladd_func_ptr = NoteinTrig_postprocessing_ai; break; case 2: self->muladd_func_ptr = NoteinTrig_postprocessing_revai; break; case 10: self->muladd_func_ptr = NoteinTrig_postprocessing_ia; break; case 11: self->muladd_func_ptr = NoteinTrig_postprocessing_aa; break; case 12: self->muladd_func_ptr = NoteinTrig_postprocessing_revaa; break; case 20: self->muladd_func_ptr = NoteinTrig_postprocessing_ireva; break; case 21: self->muladd_func_ptr = NoteinTrig_postprocessing_areva; break; case 22: self->muladd_func_ptr = NoteinTrig_postprocessing_revareva; break; } } static void NoteinTrig_compute_next_data_frame(NoteinTrig *self) { int i; MYFLT *tmp = MidiNote_get_trigger_buffer(self->handler); for (i=0; ibufsize; i++) { self->data[i] = tmp[self->bufsize*(self->voice*2+self->mode)+i]; } (*self->muladd_func_ptr)(self); } static int NoteinTrig_traverse(NoteinTrig *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->handler); return 0; } static int NoteinTrig_clear(NoteinTrig *self) { pyo_CLEAR Py_CLEAR(self->handler); return 0; } static void NoteinTrig_dealloc(NoteinTrig* self) { pyo_DEALLOC NoteinTrig_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * NoteinTrig_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *handlertmp=NULL, *multmp=NULL, *addtmp=NULL; NoteinTrig *self; self = (NoteinTrig *)type->tp_alloc(type, 0); self->voice = 0; self->mode = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, NoteinTrig_compute_next_data_frame); self->mode_func_ptr = NoteinTrig_setProcMode; static char *kwlist[] = {"handler", "voice", "mode", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iiOO", kwlist, &handlertmp, &self->voice, &self->mode, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->handler); Py_INCREF(handlertmp); self->handler = (MidiNote *)handlertmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * NoteinTrig_getServer(NoteinTrig* self) { GET_SERVER }; static PyObject * NoteinTrig_getStream(NoteinTrig* self) { GET_STREAM }; static PyObject * NoteinTrig_setMul(NoteinTrig *self, PyObject *arg) { SET_MUL }; static PyObject * NoteinTrig_setAdd(NoteinTrig *self, PyObject *arg) { SET_ADD }; static PyObject * NoteinTrig_setSub(NoteinTrig *self, PyObject *arg) { SET_SUB }; static PyObject * NoteinTrig_setDiv(NoteinTrig *self, PyObject *arg) { SET_DIV }; static PyObject * NoteinTrig_play(NoteinTrig *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * NoteinTrig_stop(NoteinTrig *self) { STOP }; static PyObject * NoteinTrig_multiply(NoteinTrig *self, PyObject *arg) { MULTIPLY }; static PyObject * NoteinTrig_inplace_multiply(NoteinTrig *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * NoteinTrig_add(NoteinTrig *self, PyObject *arg) { ADD }; static PyObject * NoteinTrig_inplace_add(NoteinTrig *self, PyObject *arg) { INPLACE_ADD }; static PyObject * NoteinTrig_sub(NoteinTrig *self, PyObject *arg) { SUB }; static PyObject * NoteinTrig_inplace_sub(NoteinTrig *self, PyObject *arg) { INPLACE_SUB }; static PyObject * NoteinTrig_div(NoteinTrig *self, PyObject *arg) { DIV }; static PyObject * NoteinTrig_inplace_div(NoteinTrig *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef NoteinTrig_members[] = { {"server", T_OBJECT_EX, offsetof(NoteinTrig, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(NoteinTrig, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(NoteinTrig, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(NoteinTrig, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef NoteinTrig_methods[] = { {"getServer", (PyCFunction)NoteinTrig_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)NoteinTrig_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)NoteinTrig_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)NoteinTrig_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)NoteinTrig_setMul, METH_O, "Sets NoteinTrig mul factor."}, {"setAdd", (PyCFunction)NoteinTrig_setAdd, METH_O, "Sets NoteinTrig add factor."}, {"setSub", (PyCFunction)NoteinTrig_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)NoteinTrig_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods NoteinTrig_as_number = { (binaryfunc)NoteinTrig_add, /*nb_add*/ (binaryfunc)NoteinTrig_sub, /*nb_subtract*/ (binaryfunc)NoteinTrig_multiply, /*nb_multiply*/ (binaryfunc)NoteinTrig_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)NoteinTrig_inplace_add, /*inplace_add*/ (binaryfunc)NoteinTrig_inplace_sub, /*inplace_subtract*/ (binaryfunc)NoteinTrig_inplace_multiply, /*inplace_multiply*/ (binaryfunc)NoteinTrig_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject NoteinTrigType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.NoteinTrig_base", /*tp_name*/ sizeof(NoteinTrig), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)NoteinTrig_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &NoteinTrig_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "NoteinTrig objects. Stream noteon or noteoff trigger from a Notein voice.", /* tp_doc */ (traverseproc)NoteinTrig_traverse, /* tp_traverse */ (inquiry)NoteinTrig_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ NoteinTrig_methods, /* tp_methods */ NoteinTrig_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ NoteinTrig_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; int fademode; int changed; MYFLT topValue; MYFLT offsetAmp; MYFLT initAmp; MYFLT sustainAmp; MYFLT attack; MYFLT decay; MYFLT sustain; MYFLT release; MYFLT invAttack; MYFLT initAmpMinusOffsetAmp; MYFLT attackPlusDecay; MYFLT invDecay; MYFLT initAmpMinusSustainAmp; MYFLT invRelease; double currentTime; MYFLT sampleToSec; } MidiAdsr; static void MidiAdsr_generates(MidiAdsr *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { if (self->fademode == 0 && in[i] > 0.0) { self->fademode = 1; self->initAmp = in[i]; self->offsetAmp = self->data[i]; self->sustainAmp = self->initAmp * self->sustain; self->currentTime = 0.0; self->invAttack = 1.0 / self->attack; self->invDecay = 1.0 / self->decay; self->attackPlusDecay = self->attack + self->decay; self->initAmpMinusOffsetAmp = self->initAmp - self->offsetAmp; self->initAmpMinusSustainAmp = self->initAmp - self->sustainAmp; } else if (self->fademode == 1 && in[i] == 0.0) { self->fademode = 0; self->currentTime = 0.0; self->invRelease = 1.0 / self->release; } if (self->fademode == 1) { if (self->currentTime <= self->attack) val = self->currentTime * self->invAttack * self->initAmpMinusOffsetAmp + self->offsetAmp; else if (self->currentTime <= self->attackPlusDecay) val = (self->decay - (self->currentTime - self->attack)) * self->invDecay * self->initAmpMinusSustainAmp + self->sustainAmp; else val = self->sustainAmp; self->topValue = val; } else { if (self->currentTime <= self->release) val = self->topValue * (1. - self->currentTime * self->invRelease); else val = 0.; } self->data[i] = val; self->currentTime += self->sampleToSec; } } static void MidiAdsr_postprocessing_ii(MidiAdsr *self) { POST_PROCESSING_II }; static void MidiAdsr_postprocessing_ai(MidiAdsr *self) { POST_PROCESSING_AI }; static void MidiAdsr_postprocessing_ia(MidiAdsr *self) { POST_PROCESSING_IA }; static void MidiAdsr_postprocessing_aa(MidiAdsr *self) { POST_PROCESSING_AA }; static void MidiAdsr_postprocessing_ireva(MidiAdsr *self) { POST_PROCESSING_IREVA }; static void MidiAdsr_postprocessing_areva(MidiAdsr *self) { POST_PROCESSING_AREVA }; static void MidiAdsr_postprocessing_revai(MidiAdsr *self) { POST_PROCESSING_REVAI }; static void MidiAdsr_postprocessing_revaa(MidiAdsr *self) { POST_PROCESSING_REVAA }; static void MidiAdsr_postprocessing_revareva(MidiAdsr *self) { POST_PROCESSING_REVAREVA }; static void MidiAdsr_setProcMode(MidiAdsr *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = MidiAdsr_generates; switch (muladdmode) { case 0: self->muladd_func_ptr = MidiAdsr_postprocessing_ii; break; case 1: self->muladd_func_ptr = MidiAdsr_postprocessing_ai; break; case 2: self->muladd_func_ptr = MidiAdsr_postprocessing_revai; break; case 10: self->muladd_func_ptr = MidiAdsr_postprocessing_ia; break; case 11: self->muladd_func_ptr = MidiAdsr_postprocessing_aa; break; case 12: self->muladd_func_ptr = MidiAdsr_postprocessing_revaa; break; case 20: self->muladd_func_ptr = MidiAdsr_postprocessing_ireva; break; case 21: self->muladd_func_ptr = MidiAdsr_postprocessing_areva; break; case 22: self->muladd_func_ptr = MidiAdsr_postprocessing_revareva; break; } } static void MidiAdsr_compute_next_data_frame(MidiAdsr *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int MidiAdsr_traverse(MidiAdsr *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int MidiAdsr_clear(MidiAdsr *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void MidiAdsr_dealloc(MidiAdsr* self) { pyo_DEALLOC MidiAdsr_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * MidiAdsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; MidiAdsr *self; self = (MidiAdsr *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->topValue = 0.0; self->fademode = 0; self->changed = 0; self->attack = 0.01; self->decay = 0.05; self->sustain = 0.707; self->release = 0.1; self->currentTime = 0.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, MidiAdsr_compute_next_data_frame); self->mode_func_ptr = MidiAdsr_setProcMode; self->sampleToSec = 1. / self->sr; static char *kwlist[] = {"input", "attack", "decay", "sustain", "release", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FFFFOO, kwlist, &inputtmp, &self->attack, &self->decay, &self->sustain, &self->release, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (self->attack < 0.000001) self->attack = 0.000001; if (self->decay < 0.000001) self->decay = 0.000001; if (self->release < 0.000001) self->release = 0.000001; if (self->sustain < 0.0) self->sustain = 0.0; else if (self->sustain > 1.0) self->sustain = 1.0; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * MidiAdsr_getServer(MidiAdsr* self) { GET_SERVER }; static PyObject * MidiAdsr_getStream(MidiAdsr* self) { GET_STREAM }; static PyObject * MidiAdsr_setMul(MidiAdsr *self, PyObject *arg) { SET_MUL }; static PyObject * MidiAdsr_setAdd(MidiAdsr *self, PyObject *arg) { SET_ADD }; static PyObject * MidiAdsr_setSub(MidiAdsr *self, PyObject *arg) { SET_SUB }; static PyObject * MidiAdsr_setDiv(MidiAdsr *self, PyObject *arg) { SET_DIV }; static PyObject * MidiAdsr_play(MidiAdsr *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * MidiAdsr_stop(MidiAdsr *self) { STOP } static PyObject * MidiAdsr_multiply(MidiAdsr *self, PyObject *arg) { MULTIPLY }; static PyObject * MidiAdsr_inplace_multiply(MidiAdsr *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * MidiAdsr_add(MidiAdsr *self, PyObject *arg) { ADD }; static PyObject * MidiAdsr_inplace_add(MidiAdsr *self, PyObject *arg) { INPLACE_ADD }; static PyObject * MidiAdsr_sub(MidiAdsr *self, PyObject *arg) { SUB }; static PyObject * MidiAdsr_inplace_sub(MidiAdsr *self, PyObject *arg) { INPLACE_SUB }; static PyObject * MidiAdsr_div(MidiAdsr *self, PyObject *arg) { DIV }; static PyObject * MidiAdsr_inplace_div(MidiAdsr *self, PyObject *arg) { INPLACE_DIV }; static PyObject * MidiAdsr_setAttack(MidiAdsr *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->attack = PyFloat_AsDouble(arg); if (self->attack < 0.000001) self->attack = 0.000001; self->invAttack = 1.0 / self->attack; self->attackPlusDecay = self->attack + self->decay; } Py_INCREF(Py_None); return Py_None; } static PyObject * MidiAdsr_setDecay(MidiAdsr *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->decay = PyFloat_AsDouble(arg); if (self->decay < 0.000001) self->decay = 0.000001; self->invDecay = 1.0 / self->decay; self->attackPlusDecay = self->attack + self->decay; } Py_INCREF(Py_None); return Py_None; } static PyObject * MidiAdsr_setSustain(MidiAdsr *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->sustain = PyFloat_AsDouble(arg); if (self->sustain < 0.0) self->sustain = 0.0; else if (self->sustain > 1.0) self->sustain = 1.0; } Py_INCREF(Py_None); return Py_None; } static PyObject * MidiAdsr_setRelease(MidiAdsr *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->release = PyFloat_AsDouble(arg); if (self->release < 0.000001) self->release = 0.000001; self->invRelease = 1.0 / self->release; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef MidiAdsr_members[] = { {"server", T_OBJECT_EX, offsetof(MidiAdsr, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(MidiAdsr, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(MidiAdsr, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(MidiAdsr, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(MidiAdsr, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef MidiAdsr_methods[] = { {"getServer", (PyCFunction)MidiAdsr_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)MidiAdsr_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)MidiAdsr_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)MidiAdsr_stop, METH_NOARGS, "Starts fadeout and stops computing."}, {"setMul", (PyCFunction)MidiAdsr_setMul, METH_O, "Sets MidiAdsr mul factor."}, {"setAdd", (PyCFunction)MidiAdsr_setAdd, METH_O, "Sets MidiAdsr add factor."}, {"setSub", (PyCFunction)MidiAdsr_setSub, METH_O, "Sets inverse add factor."}, {"setAttack", (PyCFunction)MidiAdsr_setAttack, METH_O, "Sets attack time in seconds."}, {"setDecay", (PyCFunction)MidiAdsr_setDecay, METH_O, "Sets decay time in seconds."}, {"setSustain", (PyCFunction)MidiAdsr_setSustain, METH_O, "Sets sustain level in percent of note amplitude."}, {"setRelease", (PyCFunction)MidiAdsr_setRelease, METH_O, "Sets release time in seconds."}, {"setDiv", (PyCFunction)MidiAdsr_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods MidiAdsr_as_number = { (binaryfunc)MidiAdsr_add, /*nb_add*/ (binaryfunc)MidiAdsr_sub, /*nb_subtract*/ (binaryfunc)MidiAdsr_multiply, /*nb_multiply*/ (binaryfunc)MidiAdsr_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)MidiAdsr_inplace_add, /*inplace_add*/ (binaryfunc)MidiAdsr_inplace_sub, /*inplace_subtract*/ (binaryfunc)MidiAdsr_inplace_multiply, /*inplace_multiply*/ (binaryfunc)MidiAdsr_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject MidiAdsrType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.MidiAdsr_base", /*tp_name*/ sizeof(MidiAdsr), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)MidiAdsr_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &MidiAdsr_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "MidiAdsr objects. Generates MidiAdsr envelope signal.", /* tp_doc */ (traverseproc)MidiAdsr_traverse, /* tp_traverse */ (inquiry)MidiAdsr_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ MidiAdsr_methods, /* tp_methods */ MidiAdsr_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MidiAdsr_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; int fademode; int changed; MYFLT topValue; MYFLT offsetAmp; MYFLT initAmp; MYFLT sustainAmp; MYFLT delay; MYFLT attack; MYFLT decay; MYFLT sustain; MYFLT release; MYFLT invAttack; MYFLT initAmpMinusOffsetAmp; MYFLT invDecay; MYFLT delayPlusAttack; MYFLT delayPlusAttackPlusDecay; MYFLT initAmpMinusSustainAmp; MYFLT invRelease; double currentTime; MYFLT sampleToSec; } MidiDelAdsr; static void MidiDelAdsr_generates(MidiDelAdsr *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { if (self->fademode == 0 && in[i] > 0.0) { self->fademode = 1; self->initAmp = in[i]; self->offsetAmp = self->data[i]; self->sustainAmp = self->initAmp * self->sustain; self->currentTime = 0.0; self->invAttack = 1.0 / self->attack; self->invDecay = 1.0 / self->decay; self->delayPlusAttack = self->delay + self->attack; self->delayPlusAttackPlusDecay = self->delay + self->attack + self->decay; self->initAmpMinusOffsetAmp = self->initAmp - self->offsetAmp; self->initAmpMinusSustainAmp = self->initAmp - self->sustainAmp; } else if (self->fademode == 1 && in[i] == 0.0) { self->fademode = 0; self->currentTime = 0.0; self->invRelease = 1.0 / self->release; } if (self->fademode == 1) { if (self->currentTime < self->delay) val = 0.0; else if (self->currentTime <= self->delayPlusAttack) val = (self->currentTime - self->delay) * self->invAttack * self->initAmpMinusOffsetAmp + self->offsetAmp; else if (self->currentTime <= self->delayPlusAttackPlusDecay) val = (self->decay - (self->currentTime - self->delay - self->attack)) * self->invDecay * self->initAmpMinusSustainAmp + self->sustainAmp; else val = self->sustainAmp; self->topValue = val; } else { if (self->currentTime <= self->release) val = self->topValue * (1. - self->currentTime * self->invRelease); else val = 0.; } self->data[i] = val; self->currentTime += self->sampleToSec; } } static void MidiDelAdsr_postprocessing_ii(MidiDelAdsr *self) { POST_PROCESSING_II }; static void MidiDelAdsr_postprocessing_ai(MidiDelAdsr *self) { POST_PROCESSING_AI }; static void MidiDelAdsr_postprocessing_ia(MidiDelAdsr *self) { POST_PROCESSING_IA }; static void MidiDelAdsr_postprocessing_aa(MidiDelAdsr *self) { POST_PROCESSING_AA }; static void MidiDelAdsr_postprocessing_ireva(MidiDelAdsr *self) { POST_PROCESSING_IREVA }; static void MidiDelAdsr_postprocessing_areva(MidiDelAdsr *self) { POST_PROCESSING_AREVA }; static void MidiDelAdsr_postprocessing_revai(MidiDelAdsr *self) { POST_PROCESSING_REVAI }; static void MidiDelAdsr_postprocessing_revaa(MidiDelAdsr *self) { POST_PROCESSING_REVAA }; static void MidiDelAdsr_postprocessing_revareva(MidiDelAdsr *self) { POST_PROCESSING_REVAREVA }; static void MidiDelAdsr_setProcMode(MidiDelAdsr *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = MidiDelAdsr_generates; switch (muladdmode) { case 0: self->muladd_func_ptr = MidiDelAdsr_postprocessing_ii; break; case 1: self->muladd_func_ptr = MidiDelAdsr_postprocessing_ai; break; case 2: self->muladd_func_ptr = MidiDelAdsr_postprocessing_revai; break; case 10: self->muladd_func_ptr = MidiDelAdsr_postprocessing_ia; break; case 11: self->muladd_func_ptr = MidiDelAdsr_postprocessing_aa; break; case 12: self->muladd_func_ptr = MidiDelAdsr_postprocessing_revaa; break; case 20: self->muladd_func_ptr = MidiDelAdsr_postprocessing_ireva; break; case 21: self->muladd_func_ptr = MidiDelAdsr_postprocessing_areva; break; case 22: self->muladd_func_ptr = MidiDelAdsr_postprocessing_revareva; break; } } static void MidiDelAdsr_compute_next_data_frame(MidiDelAdsr *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int MidiDelAdsr_traverse(MidiDelAdsr *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int MidiDelAdsr_clear(MidiDelAdsr *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void MidiDelAdsr_dealloc(MidiDelAdsr* self) { pyo_DEALLOC MidiDelAdsr_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * MidiDelAdsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; MidiDelAdsr *self; self = (MidiDelAdsr *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->topValue = 0.0; self->fademode = 0; self->changed = 0; self->delay = 0.; self->attack = 0.01; self->decay = 0.05; self->sustain = 0.707; self->release = 0.1; self->currentTime = 0.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, MidiDelAdsr_compute_next_data_frame); self->mode_func_ptr = MidiDelAdsr_setProcMode; self->sampleToSec = 1. / self->sr; static char *kwlist[] = {"input", "delay", "attack", "decay", "sustain", "release", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FFFFFOO, kwlist, &inputtmp, &self->delay, &self->attack, &self->decay, &self->sustain, &self->release, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (self->attack < 0.000001) self->attack = 0.000001; if (self->decay < 0.000001) self->decay = 0.000001; if (self->release < 0.000001) self->release = 0.000001; if (self->sustain < 0.0) self->sustain = 0.0; else if (self->sustain > 1.0) self->sustain = 1.0; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * MidiDelAdsr_getServer(MidiDelAdsr* self) { GET_SERVER }; static PyObject * MidiDelAdsr_getStream(MidiDelAdsr* self) { GET_STREAM }; static PyObject * MidiDelAdsr_setMul(MidiDelAdsr *self, PyObject *arg) { SET_MUL }; static PyObject * MidiDelAdsr_setAdd(MidiDelAdsr *self, PyObject *arg) { SET_ADD }; static PyObject * MidiDelAdsr_setSub(MidiDelAdsr *self, PyObject *arg) { SET_SUB }; static PyObject * MidiDelAdsr_setDiv(MidiDelAdsr *self, PyObject *arg) { SET_DIV }; static PyObject * MidiDelAdsr_play(MidiDelAdsr *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * MidiDelAdsr_stop(MidiDelAdsr *self) { STOP } static PyObject * MidiDelAdsr_multiply(MidiDelAdsr *self, PyObject *arg) { MULTIPLY }; static PyObject * MidiDelAdsr_inplace_multiply(MidiDelAdsr *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * MidiDelAdsr_add(MidiDelAdsr *self, PyObject *arg) { ADD }; static PyObject * MidiDelAdsr_inplace_add(MidiDelAdsr *self, PyObject *arg) { INPLACE_ADD }; static PyObject * MidiDelAdsr_sub(MidiDelAdsr *self, PyObject *arg) { SUB }; static PyObject * MidiDelAdsr_inplace_sub(MidiDelAdsr *self, PyObject *arg) { INPLACE_SUB }; static PyObject * MidiDelAdsr_div(MidiDelAdsr *self, PyObject *arg) { DIV }; static PyObject * MidiDelAdsr_inplace_div(MidiDelAdsr *self, PyObject *arg) { INPLACE_DIV }; static PyObject * MidiDelAdsr_setDelay(MidiDelAdsr *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->delay = PyFloat_AsDouble(arg); self->delayPlusAttack = self->delay + self->attack; self->delayPlusAttackPlusDecay = self->delay + self->attack + self->decay; } Py_INCREF(Py_None); return Py_None; } static PyObject * MidiDelAdsr_setAttack(MidiDelAdsr *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->attack = PyFloat_AsDouble(arg); if (self->attack < 0.000001) self->attack = 0.000001; self->invAttack = 1.0 / self->attack; self->delayPlusAttack = self->delay + self->attack; self->delayPlusAttackPlusDecay = self->delay + self->attack + self->decay; } Py_INCREF(Py_None); return Py_None; } static PyObject * MidiDelAdsr_setDecay(MidiDelAdsr *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->decay = PyFloat_AsDouble(arg); if (self->decay < 0.000001) self->decay = 0.000001; self->invDecay = 1.0 / self->decay; self->delayPlusAttackPlusDecay = self->delay + self->attack + self->decay; } Py_INCREF(Py_None); return Py_None; } static PyObject * MidiDelAdsr_setSustain(MidiDelAdsr *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->sustain = PyFloat_AsDouble(arg); if (self->sustain < 0.0) self->sustain = 0.0; else if (self->sustain > 1.0) self->sustain = 1.0; } Py_INCREF(Py_None); return Py_None; } static PyObject * MidiDelAdsr_setRelease(MidiDelAdsr *self, PyObject *arg) { if (PyNumber_Check(arg)) { self->release = PyFloat_AsDouble(arg); if (self->release < 0.000001) self->release = 0.000001; self->invRelease = 1.0 / self->release; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef MidiDelAdsr_members[] = { {"server", T_OBJECT_EX, offsetof(MidiDelAdsr, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(MidiDelAdsr, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(MidiDelAdsr, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(MidiDelAdsr, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(MidiDelAdsr, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef MidiDelAdsr_methods[] = { {"getServer", (PyCFunction)MidiDelAdsr_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)MidiDelAdsr_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)MidiDelAdsr_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)MidiDelAdsr_stop, METH_NOARGS, "Starts fadeout and stops computing."}, {"setMul", (PyCFunction)MidiDelAdsr_setMul, METH_O, "Sets MidiDelAdsr mul factor."}, {"setAdd", (PyCFunction)MidiDelAdsr_setAdd, METH_O, "Sets MidiDelAdsr add factor."}, {"setSub", (PyCFunction)MidiDelAdsr_setSub, METH_O, "Sets inverse add factor."}, {"setDelay", (PyCFunction)MidiDelAdsr_setDelay, METH_O, "Sets delay time in seconds."}, {"setAttack", (PyCFunction)MidiDelAdsr_setAttack, METH_O, "Sets attack time in seconds."}, {"setDecay", (PyCFunction)MidiDelAdsr_setDecay, METH_O, "Sets decay time in seconds."}, {"setSustain", (PyCFunction)MidiDelAdsr_setSustain, METH_O, "Sets sustain level in percent of note amplitude."}, {"setRelease", (PyCFunction)MidiDelAdsr_setRelease, METH_O, "Sets release time in seconds."}, {"setDiv", (PyCFunction)MidiDelAdsr_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods MidiDelAdsr_as_number = { (binaryfunc)MidiDelAdsr_add, /*nb_add*/ (binaryfunc)MidiDelAdsr_sub, /*nb_subtract*/ (binaryfunc)MidiDelAdsr_multiply, /*nb_multiply*/ (binaryfunc)MidiDelAdsr_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)MidiDelAdsr_inplace_add, /*inplace_add*/ (binaryfunc)MidiDelAdsr_inplace_sub, /*inplace_subtract*/ (binaryfunc)MidiDelAdsr_inplace_multiply, /*inplace_multiply*/ (binaryfunc)MidiDelAdsr_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject MidiDelAdsrType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.MidiDelAdsr_base", /*tp_name*/ sizeof(MidiDelAdsr), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)MidiDelAdsr_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &MidiDelAdsr_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "MidiDelAdsr objects. Generates MidiDelAdsr envelope signal.", /* tp_doc */ (traverseproc)MidiDelAdsr_traverse, /* tp_traverse */ (inquiry)MidiDelAdsr_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ MidiDelAdsr_methods, /* tp_methods */ MidiDelAdsr_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MidiDelAdsr_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *callable; } RawMidi; static void RawMidi_setProcMode(RawMidi *self) {} static void RawMidi_compute_next_data_frame(RawMidi *self) { PmEvent *buffer; int i, count, status, data1, data2; buffer = Server_getMidiEventBuffer((Server *)self->server); count = Server_getMidiEventCount((Server *)self->server); if (count > 0) { PyObject *tup; for (i=count-1; i>=0; i--) { status = Pm_MessageStatus(buffer[i].message); // Temp note event holders data1 = Pm_MessageData1(buffer[i].message); data2 = Pm_MessageData2(buffer[i].message); tup = PyTuple_New(3); PyTuple_SetItem(tup, 0, PyInt_FromLong(status)); PyTuple_SetItem(tup, 1, PyInt_FromLong(data1)); PyTuple_SetItem(tup, 2, PyInt_FromLong(data2)); PyObject_Call((PyObject *)self->callable, tup, NULL); } } } static int RawMidi_traverse(RawMidi *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->callable); return 0; } static int RawMidi_clear(RawMidi *self) { pyo_CLEAR Py_CLEAR(self->callable); return 0; } static void RawMidi_dealloc(RawMidi* self) { pyo_DEALLOC RawMidi_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * RawMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *calltmp=NULL; RawMidi *self; self = (RawMidi *)type->tp_alloc(type, 0); INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, RawMidi_compute_next_data_frame); self->mode_func_ptr = RawMidi_setProcMode; static char *kwlist[] = {"callable", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &calltmp)) Py_RETURN_NONE; if (calltmp) { PyObject_CallMethod((PyObject *)self, "setFunction", "O", calltmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); return (PyObject *)self; } static PyObject * RawMidi_getServer(RawMidi* self) { GET_SERVER }; static PyObject * RawMidi_getStream(RawMidi* self) { GET_STREAM }; static PyObject * RawMidi_play(RawMidi *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * RawMidi_stop(RawMidi *self) { STOP }; static PyObject * RawMidi_setFunction(RawMidi *self, PyObject *arg) { PyObject *tmp; if (! PyCallable_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function."); Py_INCREF(Py_None); return Py_None; } tmp = arg; Py_XDECREF(self->callable); Py_INCREF(tmp); self->callable = tmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef RawMidi_members[] = { {"server", T_OBJECT_EX, offsetof(RawMidi, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(RawMidi, stream), 0, "Stream object."}, {NULL} /* Sentinel */ }; static PyMethodDef RawMidi_methods[] = { {"getServer", (PyCFunction)RawMidi_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)RawMidi_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)RawMidi_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)RawMidi_stop, METH_NOARGS, "Stops computing."}, {"setFunction", (PyCFunction)RawMidi_setFunction, METH_O, "Sets the function to be called."}, {NULL} /* Sentinel */ }; PyTypeObject RawMidiType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.RawMidi_base", /*tp_name*/ sizeof(RawMidi), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)RawMidi_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "RawMidi objects. Calls a function with midi data as arguments.", /* tp_doc */ (traverseproc)RawMidi_traverse, /* tp_traverse */ (inquiry)RawMidi_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ RawMidi_methods, /* tp_methods */ RawMidi_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ RawMidi_new, /* tp_new */ }; pyo/src/objects/freeverbmodule.c0000644000175000017500000007700312652732202016257 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #define DEFAULT_SRATE 44100.0 #define NUM_COMB 8 #define NUM_ALLPASS 4 static const MYFLT comb_delays[NUM_COMB] = { 1116.0 / DEFAULT_SRATE, 1188.0 / DEFAULT_SRATE, 1277.0 / DEFAULT_SRATE, 1356.0 / DEFAULT_SRATE, 1422.0 / DEFAULT_SRATE, 1491.0 / DEFAULT_SRATE, 1557.0 / DEFAULT_SRATE, 1617.0 / DEFAULT_SRATE }; static const MYFLT allpass_delays[NUM_ALLPASS] = { 556.0 / DEFAULT_SRATE, 441.0 / DEFAULT_SRATE, 341.0 / DEFAULT_SRATE, 225.0 / DEFAULT_SRATE }; static const MYFLT fixedGain = 0.015; static const MYFLT scaleDamp = 0.5; static const MYFLT scaleRoom = 0.29; static const MYFLT offsetRoom = 0.7; static const MYFLT allPassFeedBack = 0.5; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *size; Stream *size_stream; PyObject *damp; Stream *damp_stream; PyObject *mix; Stream *mix_stream; int comb_nSamples[NUM_COMB]; int comb_bufPos[NUM_COMB]; MYFLT comb_filterState[NUM_COMB]; MYFLT *comb_buf[NUM_COMB]; int allpass_nSamples[NUM_ALLPASS]; int allpass_bufPos[NUM_ALLPASS]; MYFLT *allpass_buf[NUM_ALLPASS]; int modebuffer[5]; MYFLT srFactor; } Freeverb; static MYFLT _clip(MYFLT x) { if (x < 0) return 0; else if (x > 1) return 1; else return x; } static int Freeverb_calc_nsamples(Freeverb *self, MYFLT delTime) { return (int)(delTime * self->sr + 0.5); } static void Freeverb_transform_iii(Freeverb *self) { MYFLT x, feedback, damp1, damp2, mix1, mix2; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT siz = _clip(PyFloat_AS_DOUBLE(self->size)); MYFLT dam = _clip(PyFloat_AS_DOUBLE(self->damp)); MYFLT mix = _clip(PyFloat_AS_DOUBLE(self->mix)); feedback = siz * scaleRoom + offsetRoom; damp1 = dam * scaleDamp; damp2 = 1.0 - damp1; mix1 = MYSQRT(mix); mix2 = MYSQRT(1.0 - mix); MYFLT tmp[self->bufsize]; memset(&tmp, 0, sizeof(tmp)); for (j=0; jbufsize; j++) { for (i=0; icomb_buf[i][self->comb_bufPos[i]]; tmp[j] += x; self->comb_filterState[i] = (self->comb_filterState[i] * damp1) + (x * damp2); x = self->comb_filterState[i] * feedback + in[j]; self->comb_buf[i][self->comb_bufPos[i]] = x; self->comb_bufPos[i]++; if (self->comb_bufPos[i] >= self->comb_nSamples[i]) self->comb_bufPos[i] = 0; } } for (i=0; ibufsize; j++) { x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j]; self->allpass_buf[i][self->allpass_bufPos[i]] *= allPassFeedBack; self->allpass_buf[i][self->allpass_bufPos[i]] += tmp[j]; self->allpass_bufPos[i]++; if (self->allpass_bufPos[i] >= self->allpass_nSamples[i]) self->allpass_bufPos[i] = 0; tmp[j] = x; } } for (i=0; ibufsize; i++) { self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2); } } static void Freeverb_transform_aii(Freeverb *self) { MYFLT x, feedback, damp1, damp2, mix1, mix2; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *siz = Stream_getData((Stream *)self->size_stream); MYFLT dam = _clip(PyFloat_AS_DOUBLE(self->damp)); MYFLT mix = _clip(PyFloat_AS_DOUBLE(self->mix)); damp1 = dam * scaleDamp; damp2 = 1.0 - damp1; mix1 = MYSQRT(mix); mix2 = MYSQRT(1.0 - mix); MYFLT tmp[self->bufsize]; memset(&tmp, 0, sizeof(tmp)); for (j=0; jbufsize; j++) { feedback = _clip(siz[j]) * scaleRoom + offsetRoom; for (i=0; icomb_buf[i][self->comb_bufPos[i]]; tmp[j] += x; self->comb_filterState[i] = (self->comb_filterState[i] * damp1) + (x * damp2); x = self->comb_filterState[i] * feedback + in[j]; self->comb_buf[i][self->comb_bufPos[i]] = x; self->comb_bufPos[i]++; if (self->comb_bufPos[i] >= self->comb_nSamples[i]) self->comb_bufPos[i] = 0; } } for (i=0; ibufsize; j++) { x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j]; self->allpass_buf[i][self->allpass_bufPos[i]] *= allPassFeedBack; self->allpass_buf[i][self->allpass_bufPos[i]] += tmp[j]; self->allpass_bufPos[i]++; if (self->allpass_bufPos[i] >= self->allpass_nSamples[i]) self->allpass_bufPos[i] = 0; tmp[j] = x; } } for (i=0; ibufsize; i++) { self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2); } } static void Freeverb_transform_iai(Freeverb *self) { MYFLT x, feedback, damp1, damp2, mix1, mix2; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT siz = _clip(PyFloat_AS_DOUBLE(self->size)); MYFLT *dam = Stream_getData((Stream *)self->damp_stream); MYFLT mix = _clip(PyFloat_AS_DOUBLE(self->mix)); feedback = siz * scaleRoom + offsetRoom; mix1 = MYSQRT(mix); mix2 = MYSQRT(1.0 - mix); MYFLT tmp[self->bufsize]; memset(&tmp, 0, sizeof(tmp)); for (j=0; jbufsize; j++) { damp1 = _clip(dam[j]) * scaleDamp; damp2 = 1.0 - damp1; for (i=0; icomb_buf[i][self->comb_bufPos[i]]; tmp[j] += x; self->comb_filterState[i] = (self->comb_filterState[i] * damp1) + (x * damp2); x = self->comb_filterState[i] * feedback + in[j]; self->comb_buf[i][self->comb_bufPos[i]] = x; self->comb_bufPos[i]++; if (self->comb_bufPos[i] >= self->comb_nSamples[i]) self->comb_bufPos[i] = 0; } } for (i=0; ibufsize; j++) { x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j]; self->allpass_buf[i][self->allpass_bufPos[i]] *= allPassFeedBack; self->allpass_buf[i][self->allpass_bufPos[i]] += tmp[j]; self->allpass_bufPos[i]++; if (self->allpass_bufPos[i] >= self->allpass_nSamples[i]) self->allpass_bufPos[i] = 0; tmp[j] = x; } } for (i=0; ibufsize; i++) { self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2); } } static void Freeverb_transform_aai(Freeverb *self) { MYFLT x, feedback, damp1, damp2, mix1, mix2; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *siz = Stream_getData((Stream *)self->size_stream); MYFLT *dam = Stream_getData((Stream *)self->damp_stream); MYFLT mix = _clip(PyFloat_AS_DOUBLE(self->mix)); mix1 = MYSQRT(mix); mix2 = MYSQRT(1.0 - mix); MYFLT tmp[self->bufsize]; memset(&tmp, 0, sizeof(tmp)); for (j=0; jbufsize; j++) { feedback = _clip(siz[j]) * scaleRoom + offsetRoom; damp1 = _clip(dam[j]) * scaleDamp; damp2 = 1.0 - damp1; for (i=0; icomb_buf[i][self->comb_bufPos[i]]; tmp[j] += x; self->comb_filterState[i] = (self->comb_filterState[i] * damp1) + (x * damp2); x = self->comb_filterState[i] * feedback + in[j]; self->comb_buf[i][self->comb_bufPos[i]] = x; self->comb_bufPos[i]++; if (self->comb_bufPos[i] >= self->comb_nSamples[i]) self->comb_bufPos[i] = 0; } } for (i=0; ibufsize; j++) { x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j]; self->allpass_buf[i][self->allpass_bufPos[i]] *= allPassFeedBack; self->allpass_buf[i][self->allpass_bufPos[i]] += tmp[j]; self->allpass_bufPos[i]++; if (self->allpass_bufPos[i] >= self->allpass_nSamples[i]) self->allpass_bufPos[i] = 0; tmp[j] = x; } } for (i=0; ibufsize; i++) { self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2); } } static void Freeverb_transform_iia(Freeverb *self) { MYFLT x, feedback, damp1, damp2, mix1, mix2, mixtmp; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT siz = _clip(PyFloat_AS_DOUBLE(self->size)); MYFLT dam = _clip(PyFloat_AS_DOUBLE(self->damp)); MYFLT *mix = Stream_getData((Stream *)self->mix_stream); feedback = siz * scaleRoom + offsetRoom; damp1 = dam * scaleDamp; damp2 = 1.0 - damp1; MYFLT tmp[self->bufsize]; memset(&tmp, 0, sizeof(tmp)); for (j=0; jbufsize; j++) { for (i=0; icomb_buf[i][self->comb_bufPos[i]]; tmp[j] += x; self->comb_filterState[i] = (self->comb_filterState[i] * damp1) + (x * damp2); x = self->comb_filterState[i] * feedback + in[j]; self->comb_buf[i][self->comb_bufPos[i]] = x; self->comb_bufPos[i]++; if (self->comb_bufPos[i] >= self->comb_nSamples[i]) self->comb_bufPos[i] = 0; } } for (i=0; ibufsize; j++) { x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j]; self->allpass_buf[i][self->allpass_bufPos[i]] *= allPassFeedBack; self->allpass_buf[i][self->allpass_bufPos[i]] += tmp[j]; self->allpass_bufPos[i]++; if (self->allpass_bufPos[i] >= self->allpass_nSamples[i]) self->allpass_bufPos[i] = 0; tmp[j] = x; } } for (i=0; ibufsize; i++) { mixtmp = _clip(mix[i]); mix1 = MYSQRT(mixtmp); mix2 = MYSQRT(1.0 - mixtmp); self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2); } } static void Freeverb_transform_aia(Freeverb *self) { MYFLT x, feedback, damp1, damp2, mix1, mix2, mixtmp; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *siz = Stream_getData((Stream *)self->size_stream); MYFLT dam = _clip(PyFloat_AS_DOUBLE(self->damp)); MYFLT *mix = Stream_getData((Stream *)self->mix_stream); damp1 = dam * scaleDamp; damp2 = 1.0 - damp1; MYFLT tmp[self->bufsize]; memset(&tmp, 0, sizeof(tmp)); for (j=0; jbufsize; j++) { feedback = _clip(siz[j]) * scaleRoom + offsetRoom; for (i=0; icomb_buf[i][self->comb_bufPos[i]]; tmp[j] += x; self->comb_filterState[i] = (self->comb_filterState[i] * damp1) + (x * damp2); x = self->comb_filterState[i] * feedback + in[j]; self->comb_buf[i][self->comb_bufPos[i]] = x; self->comb_bufPos[i]++; if (self->comb_bufPos[i] >= self->comb_nSamples[i]) self->comb_bufPos[i] = 0; } } for (i=0; ibufsize; j++) { x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j]; self->allpass_buf[i][self->allpass_bufPos[i]] *= allPassFeedBack; self->allpass_buf[i][self->allpass_bufPos[i]] += tmp[j]; self->allpass_bufPos[i]++; if (self->allpass_bufPos[i] >= self->allpass_nSamples[i]) self->allpass_bufPos[i] = 0; tmp[j] = x; } } for (i=0; ibufsize; i++) { mixtmp = _clip(mix[i]); mix1 = MYSQRT(mixtmp); mix2 = MYSQRT(1.0 - mixtmp); self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2); } } static void Freeverb_transform_iaa(Freeverb *self) { MYFLT x, feedback, damp1, damp2, mix1, mix2, mixtmp; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT siz = _clip(PyFloat_AS_DOUBLE(self->size)); MYFLT *dam = Stream_getData((Stream *)self->damp_stream); MYFLT *mix = Stream_getData((Stream *)self->mix_stream); feedback = siz * scaleRoom + offsetRoom; MYFLT tmp[self->bufsize]; memset(&tmp, 0, sizeof(tmp)); for (j=0; jbufsize; j++) { damp1 = _clip(dam[j]) * scaleDamp; damp2 = 1.0 - damp1; for (i=0; icomb_buf[i][self->comb_bufPos[i]]; tmp[j] += x; self->comb_filterState[i] = (self->comb_filterState[i] * damp1) + (x * damp2); x = self->comb_filterState[i] * feedback + in[j]; self->comb_buf[i][self->comb_bufPos[i]] = x; self->comb_bufPos[i]++; if (self->comb_bufPos[i] >= self->comb_nSamples[i]) self->comb_bufPos[i] = 0; } } for (i=0; ibufsize; j++) { x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j]; self->allpass_buf[i][self->allpass_bufPos[i]] *= allPassFeedBack; self->allpass_buf[i][self->allpass_bufPos[i]] += tmp[j]; self->allpass_bufPos[i]++; if (self->allpass_bufPos[i] >= self->allpass_nSamples[i]) self->allpass_bufPos[i] = 0; tmp[j] = x; } } for (i=0; ibufsize; i++) { mixtmp = _clip(mix[i]); mix1 = MYSQRT(mixtmp); mix2 = MYSQRT(1.0 - mixtmp); self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2); } } static void Freeverb_transform_aaa(Freeverb *self) { MYFLT x, feedback, damp1, damp2, mix1, mix2, mixtmp; int i, j; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *siz = Stream_getData((Stream *)self->size_stream); MYFLT *dam = Stream_getData((Stream *)self->damp_stream); MYFLT *mix = Stream_getData((Stream *)self->mix_stream); MYFLT tmp[self->bufsize]; memset(&tmp, 0, sizeof(tmp)); for (j=0; jbufsize; j++) { feedback = _clip(siz[j]) * scaleRoom + offsetRoom; damp1 = _clip(dam[j]) * scaleDamp; damp2 = 1.0 - damp1; for (i=0; icomb_buf[i][self->comb_bufPos[i]]; tmp[j] += x; self->comb_filterState[i] = (self->comb_filterState[i] * damp1) + (x * damp2); x = self->comb_filterState[i] * feedback + in[j]; self->comb_buf[i][self->comb_bufPos[i]] = x; self->comb_bufPos[i]++; if (self->comb_bufPos[i] >= self->comb_nSamples[i]) self->comb_bufPos[i] = 0; } } for (i=0; ibufsize; j++) { x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j]; self->allpass_buf[i][self->allpass_bufPos[i]] *= allPassFeedBack; self->allpass_buf[i][self->allpass_bufPos[i]] += tmp[j]; self->allpass_bufPos[i]++; if (self->allpass_bufPos[i] >= self->allpass_nSamples[i]) self->allpass_bufPos[i] = 0; tmp[j] = x; } } for (i=0; ibufsize; i++) { mixtmp = _clip(mix[i]); mix1 = MYSQRT(mixtmp); mix2 = MYSQRT(1.0 - mixtmp); self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2); } } static void Freeverb_postprocessing_ii(Freeverb *self) { POST_PROCESSING_II }; static void Freeverb_postprocessing_ai(Freeverb *self) { POST_PROCESSING_AI }; static void Freeverb_postprocessing_ia(Freeverb *self) { POST_PROCESSING_IA }; static void Freeverb_postprocessing_aa(Freeverb *self) { POST_PROCESSING_AA }; static void Freeverb_postprocessing_ireva(Freeverb *self) { POST_PROCESSING_IREVA }; static void Freeverb_postprocessing_areva(Freeverb *self) { POST_PROCESSING_AREVA }; static void Freeverb_postprocessing_revai(Freeverb *self) { POST_PROCESSING_REVAI }; static void Freeverb_postprocessing_revaa(Freeverb *self) { POST_PROCESSING_REVAA }; static void Freeverb_postprocessing_revareva(Freeverb *self) { POST_PROCESSING_REVAREVA }; static void Freeverb_setProcMode(Freeverb *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Freeverb_transform_iii; break; case 1: self->proc_func_ptr = Freeverb_transform_aii; break; case 10: self->proc_func_ptr = Freeverb_transform_iai; break; case 11: self->proc_func_ptr = Freeverb_transform_aai; break; case 100: self->proc_func_ptr = Freeverb_transform_iia; break; case 101: self->proc_func_ptr = Freeverb_transform_aia; break; case 110: self->proc_func_ptr = Freeverb_transform_iaa; break; case 111: self->proc_func_ptr = Freeverb_transform_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Freeverb_postprocessing_ii; break; case 1: self->muladd_func_ptr = Freeverb_postprocessing_ai; break; case 2: self->muladd_func_ptr = Freeverb_postprocessing_revai; break; case 10: self->muladd_func_ptr = Freeverb_postprocessing_ia; break; case 11: self->muladd_func_ptr = Freeverb_postprocessing_aa; break; case 12: self->muladd_func_ptr = Freeverb_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Freeverb_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Freeverb_postprocessing_areva; break; case 22: self->muladd_func_ptr = Freeverb_postprocessing_revareva; break; } } static void Freeverb_compute_next_data_frame(Freeverb *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Freeverb_traverse(Freeverb *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->size); Py_VISIT(self->size_stream); Py_VISIT(self->damp); Py_VISIT(self->damp_stream); Py_VISIT(self->mix); Py_VISIT(self->mix_stream); return 0; } static int Freeverb_clear(Freeverb *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->size); Py_CLEAR(self->size_stream); Py_CLEAR(self->damp); Py_CLEAR(self->damp_stream); Py_CLEAR(self->mix); Py_CLEAR(self->mix_stream); return 0; } static void Freeverb_dealloc(Freeverb* self) { int i; pyo_DEALLOC for(i=0; icomb_buf[i]); } for(i=0; iallpass_buf[i]); } Freeverb_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Freeverb_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, j, rndSamps; MYFLT nsamps; PyObject *inputtmp, *input_streamtmp, *sizetmp=NULL, *damptmp=NULL, *mixtmp=NULL, *multmp=NULL, *addtmp=NULL; Freeverb *self; self = (Freeverb *)type->tp_alloc(type, 0); self->size = PyFloat_FromDouble(.5); self->damp = PyFloat_FromDouble(.5); self->mix = PyFloat_FromDouble(.5); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->srFactor = pow((DEFAULT_SRATE/self->sr), 0.8); INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Freeverb_compute_next_data_frame); self->mode_func_ptr = Freeverb_setProcMode; static char *kwlist[] = {"input", "size", "damp", "mix", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOO", kwlist, &inputtmp, &sizetmp, &damptmp, &mixtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (sizetmp) { PyObject_CallMethod((PyObject *)self, "setSize", "O", sizetmp); } if (damptmp) { PyObject_CallMethod((PyObject *)self, "setDamp", "O", damptmp); } if (mixtmp) { PyObject_CallMethod((PyObject *)self, "setMix", "O", mixtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); Server_generateSeed((Server *)self->server, FREEVERB_ID); rndSamps = (rand()/(MYFLT)(RAND_MAX) * 20 + 10) / DEFAULT_SRATE; for(i=0; icomb_buf[i] = (MYFLT *)realloc(self->comb_buf[i], (nsamps+1) * sizeof(MYFLT)); self->comb_nSamples[i] = nsamps; self->comb_bufPos[i] = 0; self->comb_filterState[i] = 0.0; for(j=0; jcomb_buf[i][j] = 0.0; } } for(i=0; iallpass_buf[i] = (MYFLT *)realloc(self->allpass_buf[i], (nsamps+1) * sizeof(MYFLT)); self->allpass_nSamples[i] = nsamps; self->allpass_bufPos[i] = 0; for(j=0; jallpass_buf[i][j] = 0.0; } } return (PyObject *)self; } static PyObject * Freeverb_getServer(Freeverb* self) { GET_SERVER }; static PyObject * Freeverb_getStream(Freeverb* self) { GET_STREAM }; static PyObject * Freeverb_setMul(Freeverb *self, PyObject *arg) { SET_MUL }; static PyObject * Freeverb_setAdd(Freeverb *self, PyObject *arg) { SET_ADD }; static PyObject * Freeverb_setSub(Freeverb *self, PyObject *arg) { SET_SUB }; static PyObject * Freeverb_setDiv(Freeverb *self, PyObject *arg) { SET_DIV }; static PyObject * Freeverb_play(Freeverb *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Freeverb_out(Freeverb *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Freeverb_stop(Freeverb *self) { STOP }; static PyObject * Freeverb_multiply(Freeverb *self, PyObject *arg) { MULTIPLY }; static PyObject * Freeverb_inplace_multiply(Freeverb *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Freeverb_add(Freeverb *self, PyObject *arg) { ADD }; static PyObject * Freeverb_inplace_add(Freeverb *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Freeverb_sub(Freeverb *self, PyObject *arg) { SUB }; static PyObject * Freeverb_inplace_sub(Freeverb *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Freeverb_div(Freeverb *self, PyObject *arg) { DIV }; static PyObject * Freeverb_inplace_div(Freeverb *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Freeverb_setSize(Freeverb *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->size); if (isNumber == 1) { self->size = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->size = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->size, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->size_stream); self->size_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Freeverb_setDamp(Freeverb *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->damp); if (isNumber == 1) { self->damp = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->damp = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->damp, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->damp_stream); self->damp_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Freeverb_setMix(Freeverb *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->mix); if (isNumber == 1) { self->mix = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->mix = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->mix, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->mix_stream); self->mix_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Freeverb_members[] = { {"server", T_OBJECT_EX, offsetof(Freeverb, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Freeverb, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Freeverb, input), 0, "Input sound object."}, {"size", T_OBJECT_EX, offsetof(Freeverb, size), 0, "Room size."}, {"damp", T_OBJECT_EX, offsetof(Freeverb, damp), 0, "High frequencies damp factor."}, {"mix", T_OBJECT_EX, offsetof(Freeverb, mix), 0, "Mix between dry and wet signal."}, {"mul", T_OBJECT_EX, offsetof(Freeverb, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Freeverb, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Freeverb_methods[] = { {"getServer", (PyCFunction)Freeverb_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Freeverb_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Freeverb_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Freeverb_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Freeverb_stop, METH_NOARGS, "Stops computing."}, {"setSize", (PyCFunction)Freeverb_setSize, METH_O, "Sets distortion size factor (0 -> 1)."}, {"setDamp", (PyCFunction)Freeverb_setDamp, METH_O, "Sets lowpass filter damp factor."}, {"setMix", (PyCFunction)Freeverb_setMix, METH_O, "Sets the mix factor."}, {"setMul", (PyCFunction)Freeverb_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Freeverb_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Freeverb_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Freeverb_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Freeverb_as_number = { (binaryfunc)Freeverb_add, /*nb_add*/ (binaryfunc)Freeverb_sub, /*nb_subtract*/ (binaryfunc)Freeverb_multiply, /*nb_multiply*/ (binaryfunc)Freeverb_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Freeverb_inplace_add, /*inplace_add*/ (binaryfunc)Freeverb_inplace_sub, /*inplace_subtract*/ (binaryfunc)Freeverb_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Freeverb_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject FreeverbType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Freeverb_base", /*tp_name*/ sizeof(Freeverb), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Freeverb_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Freeverb_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Freeverb objects. Jezar's Freeverb .", /* tp_doc */ (traverseproc)Freeverb_traverse, /* tp_traverse */ (inquiry)Freeverb_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Freeverb_methods, /* tp_methods */ Freeverb_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Freeverb_new, /* tp_new */ };pyo/src/objects/granulatormodule.c0000644000175000017500000053160712652732202016642 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "tablemodule.h" #include "interpolation.h" static MYFLT LOOPER_LINEAR_FADE[513] = {0.0, 0.001953125, 0.00390625, 0.005859375, 0.0078125, 0.009765625, 0.01171875, 0.013671875, 0.015625, 0.017578125, 0.01953125, 0.021484375, 0.0234375, 0.025390625, 0.02734375, 0.029296875, 0.03125, 0.033203125, 0.03515625, 0.037109375, 0.0390625, 0.041015625, 0.04296875, 0.044921875, 0.046875, 0.048828125, 0.05078125, 0.052734375, 0.0546875, 0.056640625, 0.05859375, 0.060546875, 0.0625, 0.064453125, 0.06640625, 0.068359375, 0.0703125, 0.072265625, 0.07421875, 0.076171875, 0.078125, 0.080078125, 0.08203125, 0.083984375, 0.0859375, 0.087890625, 0.08984375, 0.091796875, 0.09375, 0.095703125, 0.09765625, 0.099609375, 0.1015625, 0.103515625, 0.10546875, 0.107421875, 0.109375, 0.111328125, 0.11328125, 0.115234375, 0.1171875, 0.119140625, 0.12109375, 0.123046875, 0.125, 0.126953125, 0.12890625, 0.130859375, 0.1328125, 0.134765625, 0.13671875, 0.138671875, 0.140625, 0.142578125, 0.14453125, 0.146484375, 0.1484375, 0.150390625, 0.15234375, 0.154296875, 0.15625, 0.158203125, 0.16015625, 0.162109375, 0.1640625, 0.166015625, 0.16796875, 0.169921875, 0.171875, 0.173828125, 0.17578125, 0.177734375, 0.1796875, 0.181640625, 0.18359375, 0.185546875, 0.1875, 0.189453125, 0.19140625, 0.193359375, 0.1953125, 0.197265625, 0.19921875, 0.201171875, 0.203125, 0.205078125, 0.20703125, 0.208984375, 0.2109375, 0.212890625, 0.21484375, 0.216796875, 0.21875, 0.220703125, 0.22265625, 0.224609375, 0.2265625, 0.228515625, 0.23046875, 0.232421875, 0.234375, 0.236328125, 0.23828125, 0.240234375, 0.2421875, 0.244140625, 0.24609375, 0.248046875, 0.25, 0.251953125, 0.25390625, 0.255859375, 0.2578125, 0.259765625, 0.26171875, 0.263671875, 0.265625, 0.267578125, 0.26953125, 0.271484375, 0.2734375, 0.275390625, 0.27734375, 0.279296875, 0.28125, 0.283203125, 0.28515625, 0.287109375, 0.2890625, 0.291015625, 0.29296875, 0.294921875, 0.296875, 0.298828125, 0.30078125, 0.302734375, 0.3046875, 0.306640625, 0.30859375, 0.310546875, 0.3125, 0.314453125, 0.31640625, 0.318359375, 0.3203125, 0.322265625, 0.32421875, 0.326171875, 0.328125, 0.330078125, 0.33203125, 0.333984375, 0.3359375, 0.337890625, 0.33984375, 0.341796875, 0.34375, 0.345703125, 0.34765625, 0.349609375, 0.3515625, 0.353515625, 0.35546875, 0.357421875, 0.359375, 0.361328125, 0.36328125, 0.365234375, 0.3671875, 0.369140625, 0.37109375, 0.373046875, 0.375, 0.376953125, 0.37890625, 0.380859375, 0.3828125, 0.384765625, 0.38671875, 0.388671875, 0.390625, 0.392578125, 0.39453125, 0.396484375, 0.3984375, 0.400390625, 0.40234375, 0.404296875, 0.40625, 0.408203125, 0.41015625, 0.412109375, 0.4140625, 0.416015625, 0.41796875, 0.419921875, 0.421875, 0.423828125, 0.42578125, 0.427734375, 0.4296875, 0.431640625, 0.43359375, 0.435546875, 0.4375, 0.439453125, 0.44140625, 0.443359375, 0.4453125, 0.447265625, 0.44921875, 0.451171875, 0.453125, 0.455078125, 0.45703125, 0.458984375, 0.4609375, 0.462890625, 0.46484375, 0.466796875, 0.46875, 0.470703125, 0.47265625, 0.474609375, 0.4765625, 0.478515625, 0.48046875, 0.482421875, 0.484375, 0.486328125, 0.48828125, 0.490234375, 0.4921875, 0.494140625, 0.49609375, 0.498046875, 0.5, 0.501953125, 0.50390625, 0.505859375, 0.5078125, 0.509765625, 0.51171875, 0.513671875, 0.515625, 0.517578125, 0.51953125, 0.521484375, 0.5234375, 0.525390625, 0.52734375, 0.529296875, 0.53125, 0.533203125, 0.53515625, 0.537109375, 0.5390625, 0.541015625, 0.54296875, 0.544921875, 0.546875, 0.548828125, 0.55078125, 0.552734375, 0.5546875, 0.556640625, 0.55859375, 0.560546875, 0.5625, 0.564453125, 0.56640625, 0.568359375, 0.5703125, 0.572265625, 0.57421875, 0.576171875, 0.578125, 0.580078125, 0.58203125, 0.583984375, 0.5859375, 0.587890625, 0.58984375, 0.591796875, 0.59375, 0.595703125, 0.59765625, 0.599609375, 0.6015625, 0.603515625, 0.60546875, 0.607421875, 0.609375, 0.611328125, 0.61328125, 0.615234375, 0.6171875, 0.619140625, 0.62109375, 0.623046875, 0.625, 0.626953125, 0.62890625, 0.630859375, 0.6328125, 0.634765625, 0.63671875, 0.638671875, 0.640625, 0.642578125, 0.64453125, 0.646484375, 0.6484375, 0.650390625, 0.65234375, 0.654296875, 0.65625, 0.658203125, 0.66015625, 0.662109375, 0.6640625, 0.666015625, 0.66796875, 0.669921875, 0.671875, 0.673828125, 0.67578125, 0.677734375, 0.6796875, 0.681640625, 0.68359375, 0.685546875, 0.6875, 0.689453125, 0.69140625, 0.693359375, 0.6953125, 0.697265625, 0.69921875, 0.701171875, 0.703125, 0.705078125, 0.70703125, 0.708984375, 0.7109375, 0.712890625, 0.71484375, 0.716796875, 0.71875, 0.720703125, 0.72265625, 0.724609375, 0.7265625, 0.728515625, 0.73046875, 0.732421875, 0.734375, 0.736328125, 0.73828125, 0.740234375, 0.7421875, 0.744140625, 0.74609375, 0.748046875, 0.75, 0.751953125, 0.75390625, 0.755859375, 0.7578125, 0.759765625, 0.76171875, 0.763671875, 0.765625, 0.767578125, 0.76953125, 0.771484375, 0.7734375, 0.775390625, 0.77734375, 0.779296875, 0.78125, 0.783203125, 0.78515625, 0.787109375, 0.7890625, 0.791015625, 0.79296875, 0.794921875, 0.796875, 0.798828125, 0.80078125, 0.802734375, 0.8046875, 0.806640625, 0.80859375, 0.810546875, 0.8125, 0.814453125, 0.81640625, 0.818359375, 0.8203125, 0.822265625, 0.82421875, 0.826171875, 0.828125, 0.830078125, 0.83203125, 0.833984375, 0.8359375, 0.837890625, 0.83984375, 0.841796875, 0.84375, 0.845703125, 0.84765625, 0.849609375, 0.8515625, 0.853515625, 0.85546875, 0.857421875, 0.859375, 0.861328125, 0.86328125, 0.865234375, 0.8671875, 0.869140625, 0.87109375, 0.873046875, 0.875, 0.876953125, 0.87890625, 0.880859375, 0.8828125, 0.884765625, 0.88671875, 0.888671875, 0.890625, 0.892578125, 0.89453125, 0.896484375, 0.8984375, 0.900390625, 0.90234375, 0.904296875, 0.90625, 0.908203125, 0.91015625, 0.912109375, 0.9140625, 0.916015625, 0.91796875, 0.919921875, 0.921875, 0.923828125, 0.92578125, 0.927734375, 0.9296875, 0.931640625, 0.93359375, 0.935546875, 0.9375, 0.939453125, 0.94140625, 0.943359375, 0.9453125, 0.947265625, 0.94921875, 0.951171875, 0.953125, 0.955078125, 0.95703125, 0.958984375, 0.9609375, 0.962890625, 0.96484375, 0.966796875, 0.96875, 0.970703125, 0.97265625, 0.974609375, 0.9765625, 0.978515625, 0.98046875, 0.982421875, 0.984375, 0.986328125, 0.98828125, 0.990234375, 0.9921875, 0.994140625, 0.99609375, 0.998046875, 1.0}; static MYFLT LOOPER_POWER_FADE[513] = {0.0, 0.0030679567629659761, 0.0061358846491544753, 0.0092037547820598194, 0.012271538285719925, 0.0153392062849881, 0.01840672990580482, 0.021474080275469508, 0.024541228522912288, 0.02760814577896574, 0.030674803176636626, 0.03374117185137758, 0.036807222941358832, 0.039872927587739811, 0.04293825693494082, 0.046003182130914623, 0.049067674327418015, 0.052131704680283324, 0.055195244349689941, 0.058258264500435752, 0.061320736302208578, 0.064382630929857465, 0.067443919563664051, 0.070504573389613856, 0.073564563599667426, 0.076623861392031492, 0.079682437971430126, 0.082740264549375692, 0.085797312344439894, 0.0888535525825246, 0.091908956497132724, 0.094963495329638992, 0.098017140329560604, 0.10106986275482782, 0.10412163387205459, 0.10717242495680884, 0.11022220729388306, 0.11327095217756435, 0.11631863091190475, 0.11936521481099135, 0.1224106751992162, 0.12545498341154623, 0.12849811079379317, 0.13154002870288312, 0.13458070850712617, 0.13762012158648604, 0.14065823933284921, 0.14369503315029447, 0.14673047445536175, 0.14976453467732151, 0.15279718525844344, 0.15582839765426523, 0.15885814333386145, 0.16188639378011183, 0.16491312048996992, 0.16793829497473117, 0.17096188876030122, 0.17398387338746382, 0.17700422041214875, 0.18002290140569951, 0.18303988795514095, 0.18605515166344663, 0.18906866414980619, 0.19208039704989244, 0.19509032201612825, 0.19809841071795356, 0.2011046348420919, 0.20410896609281687, 0.20711137619221856, 0.21011183688046961, 0.21311031991609136, 0.21610679707621952, 0.2191012401568698, 0.22209362097320351, 0.22508391135979283, 0.22807208317088573, 0.23105810828067111, 0.23404195858354343, 0.2370236059943672, 0.2400030224487415, 0.24298017990326387, 0.24595505033579459, 0.24892760574572015, 0.25189781815421697, 0.25486565960451457, 0.25783110216215899, 0.26079411791527551, 0.26375467897483135, 0.26671275747489837, 0.26966832557291509, 0.27262135544994898, 0.27557181931095814, 0.27851968938505306, 0.28146493792575794, 0.28440753721127188, 0.28734745954472951, 0.29028467725446233, 0.29321916269425863, 0.29615088824362379, 0.29907982630804048, 0.30200594931922808, 0.30492922973540237, 0.30784964004153487, 0.31076715274961147, 0.31368174039889152, 0.31659337555616585, 0.31950203081601569, 0.32240767880106985, 0.32531029216226293, 0.3282098435790925, 0.33110630575987643, 0.33399965144200938, 0.33688985339222005, 0.33977688440682685, 0.34266071731199438, 0.34554132496398909, 0.34841868024943456, 0.35129275608556709, 0.35416352542049034, 0.35703096123342998, 0.35989503653498811, 0.36275572436739723, 0.36561299780477385, 0.36846682995337232, 0.37131719395183754, 0.37416406297145793, 0.37700741021641826, 0.37984720892405116, 0.38268343236508978, 0.38551605384391885, 0.38834504669882625, 0.39117038430225387, 0.3939920400610481, 0.39680998741671031, 0.39962419984564679, 0.40243465085941843, 0.40524131400498986, 0.40804416286497869, 0.41084317105790391, 0.41363831223843456, 0.41642956009763715, 0.41921688836322391, 0.42200027079979968, 0.42477968120910881, 0.42755509343028208, 0.43032648134008261, 0.43309381885315196, 0.43585707992225547, 0.43861623853852766, 0.44137126873171667, 0.4441221445704292, 0.44686884016237416, 0.44961132965460654, 0.45234958723377089, 0.45508358712634384, 0.45781330359887723, 0.46053871095824001, 0.46325978355186015, 0.46597649576796618, 0.46868882203582796, 0.47139673682599764, 0.47410021465054997, 0.47679923006332209, 0.47949375766015301, 0.48218377207912272, 0.48486924800079106, 0.487550160148436, 0.49022648328829116, 0.49289819222978404, 0.49556526182577254, 0.49822766697278187, 0.50088538261124071, 0.50353838372571758, 0.50618664534515523, 0.50883014254310699, 0.5114688504379703, 0.51410274419322166, 0.51673179901764987, 0.51935599016558964, 0.52197529293715439, 0.52458968267846895, 0.52719913478190139, 0.52980362468629461, 0.5324031278771979, 0.53499761988709715, 0.53758707629564539, 0.54017147272989285, 0.54275078486451589, 0.54532498842204646, 0.54789405917310019, 0.55045797293660481, 0.55301670558002747, 0.55557023301960218, 0.5581185312205561, 0.56066157619733603, 0.56319934401383409, 0.56573181078361312, 0.56825895267013149, 0.57078074588696726, 0.5732971666980422, 0.57580819141784534, 0.57831379641165559, 0.58081395809576453, 0.58330865293769829, 0.58579785745643886, 0.58828154822264522, 0.59075970185887416, 0.5932322950397998, 0.59569930449243336, 0.59816070699634238, 0.60061647938386897, 0.60306659854034816, 0.60551104140432555, 0.60794978496777363, 0.61038280627630948, 0.61281008242940971, 0.61523159058062682, 0.61764730793780387, 0.6200572117632891, 0.62246127937414997, 0.62485948814238634, 0.62725181549514408, 0.62963823891492698, 0.63201873593980906, 0.63439328416364549, 0.6367618612362842, 0.63912444486377573, 0.64148101280858316, 0.64383154288979139, 0.64617601298331628, 0.64851440102211244, 0.65084668499638099, 0.65317284295377676, 0.65549285299961535, 0.65780669329707864, 0.66011434206742048, 0.66241577759017178, 0.66471097820334479, 0.66699992230363747, 0.66928258834663601, 0.67155895484701833, 0.67382900037875604, 0.67609270357531592, 0.67835004312986147, 0.68060099779545302, 0.68284554638524808, 0.68508366777270036, 0.68731534089175905, 0.68954054473706683, 0.69175925836415775, 0.69397146088965389, 0.69617713149146299, 0.69837624940897292, 0.70056879394324834, 0.7027547444572253, 0.70493408037590488, 0.70710678118654746, 0.70927282643886558, 0.71143219574521632, 0.71358486878079352, 0.71573082528381859, 0.7178700450557316, 0.72000250796138165, 0.72212819392921523, 0.72424708295146689, 0.7263591550843459, 0.7284643904482252, 0.73056276922782759, 0.7326542716724127, 0.73473887809596339, 0.73681656887736979, 0.73888732446061511, 0.74095112535495899, 0.74300795213512161, 0.74505778544146595, 0.74710060598018013, 0.74913639452345926, 0.75116513190968637, 0.75318679904361241, 0.75520137689653644, 0.75720884650648446, 0.75920918897838796, 0.76120238548426178, 0.76318841726338127, 0.76516726562245885, 0.76713891193582029, 0.76910333764557959, 0.77106052426181371, 0.77301045336273688, 0.77495310659487382, 0.77688846567323244, 0.77881651238147587, 0.78073722857209438, 0.78265059616657562, 0.78455659715557524, 0.78645521359908577, 0.78834642762660623, 0.79023022143731003, 0.79210657730021228, 0.79397547755433706, 0.79583690460888346, 0.79769084094339104, 0.79953726910790501, 0.80137617172314013, 0.80320753148064483, 0.80503133114296355, 0.80684755354379922, 0.80865618158817498, 0.81045719825259477, 0.81225058658520388, 0.8140363297059483, 0.81581441080673378, 0.81758481315158371, 0.8193475200767969, 0.82110251499110465, 0.82284978137582632, 0.82458930278502529, 0.82632106284566342, 0.82804504525775569, 0.82976123379452305, 0.83146961230254512, 0.83317016470191319, 0.83486287498638001, 0.83654772722351189, 0.83822470555483797, 0.83989379419599941, 0.84155497743689833, 0.84320823964184544, 0.84485356524970701, 0.84649093877405202, 0.84812034480329712, 0.84974176800085244, 0.8513551931052652, 0.85296060493036363, 0.85455798836540053, 0.85614732837519436, 0.85772861000027212, 0.85930181835700825, 0.8608669386377672, 0.8624239561110405, 0.8639728561215867, 0.86551362409056898, 0.86704624551569265, 0.8685707059713409, 0.87008699110871135, 0.87159508665595098, 0.87309497841828998, 0.87458665227817611, 0.87607009419540649, 0.87754529020726124, 0.87901222642863341, 0.88047088905216075, 0.88192126434835494, 0.88336333866573158, 0.88479709843093779, 0.88622253014888064, 0.88763962040285393, 0.88904835585466446, 0.89044872324475788, 0.89184070939234272, 0.89322430119551532, 0.89459948563138258, 0.89596624975618511, 0.89732458070541832, 0.89867446569395382, 0.90001589201616028, 0.90134884704602203, 0.90267331823725883, 0.90398929312344334, 0.90529675931811882, 0.90659570451491533, 0.90788611648766615, 0.90916798309052238, 0.91044129225806714, 0.91170603200542988, 0.9129621904283981, 0.91420975570353069, 0.91544871608826783, 0.9166790599210427, 0.91790077562139039, 0.91911385169005777, 0.92031827670911048, 0.9215140393420419, 0.92270112833387852, 0.92387953251128674, 0.92504924078267758, 0.92621024213831138, 0.92736252565040111, 0.92850608047321548, 0.92964089584318121, 0.93076696107898371, 0.93188426558166815, 0.93299279883473885, 0.93409255040425887, 0.9351835099389475, 0.93626566717027826, 0.93733901191257496, 0.93840353406310806, 0.93945922360218992, 0.9405060705932683, 0.94154406518302081, 0.94257319760144687, 0.94359345816196039, 0.94460483726148026, 0.94560732538052128, 0.94660091308328353, 0.94758559101774109, 0.94856134991573027, 0.94952818059303667, 0.9504860739494817, 0.95143502096900834, 0.95237501271976588, 0.95330604035419375, 0.95422809510910567, 0.95514116830577067, 0.95604525134999641, 0.95694033573220894, 0.95782641302753291, 0.9587034748958716, 0.95957151308198452, 0.96043051941556579, 0.96128048581132064, 0.96212140426904158, 0.96295326687368388, 0.96377606579543984, 0.96458979328981265, 0.9653944416976894, 0.96619000344541262, 0.96697647104485207, 0.96775383709347551, 0.96852209427441727, 0.96928123535654853, 0.97003125319454397, 0.97077214072895035, 0.97150389098625178, 0.97222649707893627, 0.97293995220556007, 0.97364424965081187, 0.97433938278557586, 0.97502534506699412, 0.97570213003852857, 0.97636973133002114, 0.97702814265775439, 0.97767735782450993, 0.97831737071962765, 0.9789481753190622, 0.97956976568544052, 0.98018213596811732, 0.98078528040323043, 0.98137919331375456, 0.98196386910955524, 0.98253930228744124, 0.98310548743121629, 0.98366241921173025, 0.98421009238692903, 0.98474850180190421, 0.98527764238894122, 0.98579750916756737, 0.98630809724459867, 0.98680940181418542, 0.98730141815785843, 0.98778414164457218, 0.98825756773074946, 0.98872169196032378, 0.98917650996478101, 0.98962201746320078, 0.99005821026229712, 0.99048508425645698, 0.99090263542778001, 0.99131085984611544, 0.99170975366909953, 0.9920993131421918, 0.99247953459870997, 0.9928504144598651, 0.9932119492347945, 0.9935641355205953, 0.99390697000235606, 0.9942404494531879, 0.99456457073425542, 0.99487933079480562, 0.99518472667219682, 0.99548075549192694, 0.99576741446765982, 0.99604470090125197, 0.996312612182778, 0.99657114579055484, 0.99682029929116567, 0.99706007033948296, 0.99729045667869021, 0.99751145614030345, 0.99772306664419164, 0.997925286198596, 0.99811811290014918, 0.99830154493389289, 0.99847558057329477, 0.99864021818026527, 0.99879545620517241, 0.99894129318685687, 0.99907772775264536, 0.99920475861836389, 0.99932238458834954, 0.99943060455546173, 0.99952941750109314, 0.99961882249517864, 0.99969881869620425, 0.99976940535121528, 0.9998305817958234, 0.99988234745421256, 0.9999247018391445, 0.9999576445519639, 0.99998117528260111, 0.99999529380957619, 1.0}; static MYFLT LOOPER_SIGMOID_FADE[513] = {0.0, 9.4123586994454556e-06, 3.7649080427748505e-05, 8.4709102088298405e-05, 0.00015059065189787502, 0.00023529124945342872, 0.00033880770582522812, 0.00046113612367731927, 0.0006022718974137975, 0.00076220971335261289, 0.00094094354992541041, 0.0011384666779041819, 0.0013547716606548965, 0.0015898503544171105, 0.0018436939086109994, 0.0021162927661700914, 0.0024076366639015356, 0.0027177146328722368, 0.0030465149988219697, 0.0033940253826026945, 0.0037602327006450165, 0.0041451231654502374, 0.0045486822861099951, 0.0049708948688514387, 0.0054117450176094928, 0.0058712161346252678, 0.0063492909210707826, 0.0068459513777006653, 0.0073611788055293337, 0.0078949538065354319, 0.008447256284391802, 0.0090180654452223785, 0.0096073597983847847, 0.010215117157279741, 0.010841314640186173, 0.011485928671122803, 0.012148934980735715, 0.012830308607212071, 0.013530023897219912, 0.014248054506874053, 0.014984373402728013, 0.015738952862791311, 0.016511764477573909, 0.017302779151155301, 0.018111967102280024, 0.01893929786547921, 0.019784740292217051, 0.0206482625520642, 0.021529832133895532, 0.022429415847114664, 0.023346979822903013, 0.024282489515495831, 0.025235909703481607, 0.026207204491129399, 0.02719633730973936, 0.028203270919019807, 0.029227967408489597, 0.030270388198904985, 0.03133049404371252, 0.032408245030526195, 0.033503600582630522, 0.034616519460508088, 0.035746959763392205, 0.036894878930844255, 0.038060233744356631, 0.039242980328979049, 0.040443074154971115, 0.041660470039478648, 0.042895122148234655, 0.044146983997285061, 0.045416008454738754, 0.046702147742542333, 0.048005353438278275, 0.049325576476988986, 0.050662767153022981, 0.052016875121907391, 0.053387849402242338, 0.054775638377621005, 0.056180189798573033, 0.05760145078453105, 0.059039367825822475, 0.060493886785683182, 0.061964952902296699, 0.06345251079085501, 0.06495650444564427, 0.066476877242153565, 0.068013571939206596, 0.069566530681116401, 0.071135694999863941, 0.072721005817299733, 0.074322403447367402, 0.075939827598351384, 0.077573217375146386, 0.079222511281550778, 0.080887647222581016, 0.082568562506809939, 0.084265193848727271, 0.085977477371122046, 0.087705348607487355, 0.08944874250444762, 0.091207593424208144, 0.092981835147025738, 0.094771400873702616, 0.096576223228100277, 0.098396234259677529, 0.10023136544604749, 0.10208154769555822, 0.10394671134989369, 0.10582678618669683, 0.10772170142221238, 0.1096313857139527, 0.11155576716338378, 0.11349477331863145, 0.11544833117721015, 0.11741636718877047, 0.11939880725786906, 0.12139557674675777, 0.12340660047819374, 0.1254318027382702, 0.12747110727926697, 0.1295244373225205, 0.13159171556131499, 0.13367286416379359, 0.13576780477588735, 0.1378764585242665, 0.13999874601930906, 0.14213458735809065, 0.14428390212739184, 0.14644660940672616, 0.14862262777138718, 0.15081187529551349, 0.153014269555173, 0.15522972763146642, 0.15745816611364977, 0.15969950110227338, 0.16195364821234198, 0.16422052257649067, 0.16650003884818121, 0.16879211120491411, 0.17109665335146057, 0.17341357852311146, 0.17574279948894383, 0.17808422855510425, 0.18043777756811202, 0.18280335791817703, 0.18518088054253651, 0.18757025592880677, 0.18997139411835529, 0.19238420470968631, 0.19480859686184526, 0.19724447929783717, 0.19969176030806535, 0.20215034775378338, 0.20462014907056286, 0.20710107127178046, 0.20959302095211751, 0.21209590429107739, 0.21460962705651632, 0.21713409460819322, 0.21966921190133171, 0.22221488349019891, 0.22477101353169748, 0.2273375057889766, 0.22991426363505363, 0.23250119005645137, 0.23509818765685253, 0.23770515866076569, 0.24032200491720523, 0.24294862790338906, 0.24558492872844634, 0.24823080813714093, 0.25088616651360907, 0.25355090388510787, 0.25622491992578178, 0.25890811396043867, 0.26160038496833893, 0.26430163158700104, 0.26701175211601708, 0.26973064452088003, 0.27245820643682805, 0.27519433517269654, 0.27793892771478512, 0.2806918807307362, 0.28345309057342394, 0.28622245328485874, 0.28899986460010024, 0.2917852199511814, 0.29457841447104793, 0.29737934299750524, 0.30018790007717666, 0.30300397996947592, 0.30582747665058668, 0.30865828381745486, 0.31149629489179087, 0.31434140302408115, 0.31719350109761285, 0.320052481732506, 0.32291823728975477, 0.32579065987528255, 0.32866964134400301, 0.33155507330389, 0.33444684712006173, 0.33734485391886837, 0.34024898459199188, 0.3431591298005543, 0.34607517997923243, 0.34899702534038579, 0.35192455587818816, 0.35485766137276881, 0.35779623139436395, 0.36074015530747361, 0.36368932227502559, 0.36664362126255073, 0.36960294104236202, 0.37256717019774244, 0.37553619712713993, 0.37850991004836793, 0.38148819700281617, 0.38447094585966451, 0.38745804432010356, 0.39044937992156492, 0.39344484004195446, 0.39644431190389073, 0.39944768257895397, 0.40245483899193568, 0.40546566792509658, 0.40848005602242954, 0.41149788979392549, 0.41451905561984914, 0.41754343975501512, 0.42057092833306925, 0.42360140737077812, 0.42663476277231926, 0.42967088033357542, 0.43270964574643683, 0.43575094460310321, 0.43879466240039156, 0.44184068454404762, 0.44488889635305834, 0.44793918306397246, 0.45099142983521978, 0.45404552175143359, 0.45710134382777989, 0.46015878101428509, 0.46321771820016633, 0.46627804021816788, 0.46933963184889549, 0.47240237782515471, 0.47546616283629101, 0.47853087153252949, 0.48159638852932035, 0.48466259841168174, 0.4877293857385438, 0.49079663504709742, 0.49386423085714021, 0.49693205767542281, 0.49999999999999989, 0.50306794232457708, 0.50613576914285963, 0.50920336495290242, 0.51227061426145604, 0.51533740158831809, 0.51840361147067948, 0.5214691284674704, 0.52453383716370883, 0.52759762217484507, 0.53066036815110429, 0.5337219597818319, 0.53678228179983345, 0.53984121898571469, 0.54289865617221988, 0.54595447824856624, 0.54900857016478, 0.55206081693602738, 0.55511110364694149, 0.55815931545595221, 0.56120533759960822, 0.56424905539689663, 0.567290354253563, 0.57032911966642441, 0.57336523722768051, 0.57639859262922166, 0.57942907166693058, 0.58245656024498471, 0.58548094438015064, 0.58850211020607435, 0.59151994397757024, 0.59453433207490325, 0.5975451610080641, 0.60055231742104587, 0.60355568809610904, 0.60655515995804532, 0.60955062007843486, 0.61254195567989622, 0.61552905414033532, 0.61851180299718367, 0.62149008995163191, 0.62446380287285996, 0.62743282980225745, 0.63039705895763776, 0.6333563787374491, 0.63631067772497429, 0.63925984469252617, 0.64220376860563588, 0.64514233862723103, 0.64807544412181162, 0.6510029746596141, 0.65392482002076735, 0.65684087019944559, 0.65975101540800796, 0.66265514608113152, 0.6655531528799381, 0.66844492669610978, 0.67133035865599688, 0.67420934012471723, 0.67708176271024501, 0.67994751826749389, 0.68280649890238698, 0.68565859697591869, 0.68850370510820902, 0.69134171618254503, 0.69417252334941315, 0.69699602003052397, 0.69981209992282323, 0.70262065700249465, 0.70542158552895196, 0.70821478004881844, 0.71100013539989959, 0.71377754671514104, 0.71654690942657595, 0.71930811926926363, 0.72206107228521477, 0.72480566482730335, 0.72754179356317183, 0.7302693554791202, 0.73298824788398276, 0.73569836841299874, 0.73839961503166096, 0.74109188603956111, 0.743775080074218, 0.74644909611489196, 0.74911383348639071, 0.75176919186285884, 0.75441507127155349, 0.75705137209661078, 0.75967799508279499, 0.76229484133923409, 0.76490181234314725, 0.76749880994354847, 0.77008573636494626, 0.77266249421102318, 0.77522898646830229, 0.77778511650980087, 0.78033078809866807, 0.78286590539180656, 0.78539037294348346, 0.78790409570892272, 0.79040697904788193, 0.79289892872821932, 0.79537985092943697, 0.7978496522462164, 0.80030823969193454, 0.80275552070216261, 0.80519140313815452, 0.80761579529031347, 0.8100286058816446, 0.81242974407119306, 0.81481911945746366, 0.81719664208182241, 0.81956222243188781, 0.82191577144489558, 0.824257200511056, 0.82658642147688832, 0.82890334664853926, 0.83120788879508578, 0.83349996115181879, 0.83577947742350922, 0.83804635178765785, 0.84030049889772662, 0.84254183388634996, 0.84477027236853341, 0.84698573044482683, 0.84918812470448612, 0.85137737222861265, 0.85355339059327373, 0.85571609787260805, 0.85786541264190941, 0.86000125398069083, 0.86212354147573333, 0.86423219522411276, 0.86632713583620613, 0.8684082844386849, 0.87047556267747939, 0.87252889272073275, 0.87456819726172963, 0.87659339952180615, 0.87860442325324217, 0.880601192742131, 0.88258363281122942, 0.88455166882278968, 0.88650522668136855, 0.888444232836616, 0.89036861428604719, 0.89227829857778751, 0.89417321381330295, 0.89605328865010625, 0.89791845230444167, 0.8997686345539524, 0.90160376574032253, 0.90342377677189956, 0.90522859912629738, 0.90701816485297426, 0.90879240657579163, 0.91055125749555232, 0.91229465139251253, 0.91402252262887773, 0.91573480615127267, 0.91743143749319001, 0.91911235277741887, 0.92077748871844922, 0.92242678262485356, 0.92406017240164862, 0.92567759655263271, 0.92727899418269999, 0.92886430500013595, 0.9304334693188836, 0.93198642806079324, 0.93352312275784632, 0.93504349555435562, 0.93654748920914499, 0.93803504709770336, 0.93950611321431676, 0.94096063217417747, 0.94239854921546895, 0.9438198102014268, 0.94522436162237888, 0.94661215059775761, 0.94798312487809244, 0.94933723284697691, 0.9506744235230109, 0.9519946465617215, 0.95329785225745778, 0.95458399154526119, 0.95585301600271488, 0.95710487785176546, 0.95833952996052119, 0.95955692584502883, 0.9607570196710209, 0.96193976625564326, 0.96310512106915569, 0.96425304023660774, 0.96538348053949186, 0.96649639941736942, 0.96759175496947369, 0.96866950595628742, 0.96972961180109496, 0.97077203259151024, 0.97179672908098014, 0.97280366269026053, 0.97379279550887043, 0.97476409029651834, 0.97571751048450417, 0.97665302017709688, 0.97757058415288545, 0.97847016786610441, 0.97935173744793569, 0.98021525970778289, 0.98106070213452068, 0.98188803289771998, 0.9826972208488447, 0.98348823552242592, 0.98426104713720863, 0.98501562659727204, 0.98575194549312584, 0.98646997610278009, 0.98716969139278787, 0.98785106501926423, 0.98851407132887714, 0.98915868535981377, 0.98978488284272026, 0.99039264020161522, 0.99098193455477757, 0.9915527437156082, 0.99210504619346451, 0.99263882119447056, 0.99315404862229939, 0.99365070907892916, 0.99412878386537473, 0.99458825498239056, 0.99502910513114851, 0.99545131771388995, 0.99585487683454976, 0.99623976729935493, 0.99660597461739719, 0.99695348500117809, 0.99728228536712771, 0.99759236333609846, 0.99788370723382991, 0.99815630609138895, 0.99841014964558283, 0.99864522833934499, 0.99886153332209582, 0.99905905645007453, 0.99923779028664739, 0.9993977281025862, 0.99953886387632274, 0.99966119229417472, 0.99976470875054657, 0.99984940934810207, 0.99991529089791165, 0.99996235091957231, 0.99999058764130055, 1.0}; typedef struct { pyo_audio_HEAD PyObject *table; PyObject *env; PyObject *pitch; Stream *pitch_stream; PyObject *pos; Stream *pos_stream; PyObject *dur; Stream *dur_stream; int ngrains; MYFLT basedur; MYFLT pointerPos; MYFLT *startPos; MYFLT *gsize; MYFLT *gphase; MYFLT *lastppos; int modebuffer[5]; } Granulator; static void Granulator_transform_iii(Granulator *self) { MYFLT val, x, x1, inc, index, fpart, amp, ppos; int i, j, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); MYFLT pit = PyFloat_AS_DOUBLE(self->pitch); MYFLT pos = PyFloat_AS_DOUBLE(self->pos); MYFLT dur = PyFloat_AS_DOUBLE(self->dur); inc = pit * (1.0 / self->basedur) / self->sr; for (i=0; ibufsize; i++) { self->data[i] = 0.0; self->pointerPos += inc; for (j=0; jngrains; j++) { ppos = self->pointerPos + self->gphase[j]; if (ppos >= 1.0) { ppos -= 1.0; } // compute envelope index = ppos * envsize; ipart = (int)index; fpart = index - ipart; x = envlist[ipart]; x1 = envlist[ipart+1]; amp = x + (x1 - x) * fpart; if (ppos < self->lastppos[j]) { self->startPos[j] = pos; self->gsize[j] = dur * self->sr; } self->lastppos[j] = ppos; // compute sampling index = ppos * self->gsize[j] + self->startPos[j]; if (index >= 0 && index < size) { ipart = (int)index; fpart = index - ipart; x = tablelist[ipart]; x1 = tablelist[ipart+1]; val = x + (x1 - x) * fpart; } else val = 0.0; self->data[i] += (val * amp); } if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } } static void Granulator_transform_aii(Granulator *self) { MYFLT val, x, x1, inc, index, fpart, amp, ppos, frtosamps; int i, j, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); MYFLT *pit = Stream_getData((Stream *)self->pitch_stream); MYFLT pos = PyFloat_AS_DOUBLE(self->pos); MYFLT dur = PyFloat_AS_DOUBLE(self->dur); frtosamps = (1.0 / self->basedur) / self->sr; for (i=0; ibufsize; i++) { self->data[i] = 0.0; inc = pit[i] * frtosamps; self->pointerPos += inc; for (j=0; jngrains; j++) { ppos = self->pointerPos + self->gphase[j]; if (ppos >= 1.0) { ppos -= 1.0; } // compute envelope index = ppos * envsize; ipart = (int)index; fpart = index - ipart; x = envlist[ipart]; x1 = envlist[ipart+1]; amp = x + (x1 - x) * fpart; if (ppos < self->lastppos[j]) { self->startPos[j] = pos; self->gsize[j] = dur * self->sr; } self->lastppos[j] = ppos; // compute sampling index = ppos * self->gsize[j] + self->startPos[j]; if (index >= 0 && index < size) { ipart = (int)index; fpart = index - ipart; x = tablelist[ipart]; x1 = tablelist[ipart+1]; val = x + (x1 - x) * fpart; } else val = 0.0; self->data[i] += (val * amp); } if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } } static void Granulator_transform_iai(Granulator *self) { MYFLT val, x, x1, inc, index, fpart, amp, ppos; int i, j, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); MYFLT pit = PyFloat_AS_DOUBLE(self->pitch); MYFLT *pos = Stream_getData((Stream *)self->pos_stream); MYFLT dur = PyFloat_AS_DOUBLE(self->dur); inc = pit * (1.0 / self->basedur) / self->sr; MYFLT gsize = dur * self->sr; for (j=0; jngrains; j++) { self->gsize[j] = gsize; } for (i=0; ibufsize; i++) { self->data[i] = 0.0; self->pointerPos += inc; for (j=0; jngrains; j++) { ppos = self->pointerPos + self->gphase[j]; if (ppos >= 1.0) { ppos -= 1.0; } // compute envelope index = ppos * envsize; ipart = (int)index; fpart = index - ipart; x = envlist[ipart]; x1 = envlist[ipart+1]; amp = x + (x1 - x) * fpart; if (ppos < self->lastppos[j]) { self->startPos[j] = pos[i]; } self->lastppos[j] = ppos; // compute sampling index = ppos * self->gsize[j] + self->startPos[j]; if (index >= 0 && index < size) { ipart = (int)index; fpart = index - ipart; x = tablelist[ipart]; x1 = tablelist[ipart+1]; val = x + (x1 - x) * fpart; } else val = 0.0; self->data[i] += (val * amp); } if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } } static void Granulator_transform_aai(Granulator *self) { MYFLT val, x, x1, inc, index, fpart, amp, ppos, frtosamps; int i, j, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); MYFLT *pit = Stream_getData((Stream *)self->pitch_stream); MYFLT *pos = Stream_getData((Stream *)self->pos_stream); MYFLT dur = PyFloat_AS_DOUBLE(self->dur); frtosamps = (1.0 / self->basedur) / self->sr; for (i=0; ibufsize; i++) { self->data[i] = 0.0; inc = pit[i] * frtosamps; self->pointerPos += inc; for (j=0; jngrains; j++) { ppos = self->pointerPos + self->gphase[j]; if (ppos >= 1.0) { ppos -= 1.0; } // compute envelope index = ppos * envsize; ipart = (int)index; fpart = index - ipart; x = envlist[ipart]; x1 = envlist[ipart+1]; amp = x + (x1 - x) * fpart; if (ppos < self->lastppos[j]) { self->startPos[j] = pos[i]; self->gsize[j] = dur * self->sr; } self->lastppos[j] = ppos; // compute sampling index = ppos * self->gsize[j] + self->startPos[j]; if (index >= 0 && index < size) { ipart = (int)index; fpart = index - ipart; x = tablelist[ipart]; x1 = tablelist[ipart+1]; val = x + (x1 - x) * fpart; } else val = 0.0; self->data[i] += (val * amp); } if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } } static void Granulator_transform_iia(Granulator *self) { MYFLT val, x, x1, inc, index, fpart, amp, ppos; int i, j, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); MYFLT pit = PyFloat_AS_DOUBLE(self->pitch); MYFLT pos = PyFloat_AS_DOUBLE(self->pos); MYFLT *dur = Stream_getData((Stream *)self->dur_stream); inc = pit * (1.0 / self->basedur) / self->sr; for (i=0; ibufsize; i++) { self->data[i] = 0.0; self->pointerPos += inc; for (j=0; jngrains; j++) { ppos = self->pointerPos + self->gphase[j]; if (ppos >= 1.0) { ppos -= 1.0; } // compute envelope index = ppos * envsize; ipart = (int)index; fpart = index - ipart; x = envlist[ipart]; x1 = envlist[ipart+1]; amp = x + (x1 - x) * fpart; if (ppos < self->lastppos[j]) { self->startPos[j] = pos; self->gsize[j] = dur[i] * self->sr; } self->lastppos[j] = ppos; // compute sampling index = ppos * self->gsize[j] + self->startPos[j]; if (index >= 0 && index < size) { ipart = (int)index; fpart = index - ipart; x = tablelist[ipart]; x1 = tablelist[ipart+1]; val = x + (x1 - x) * fpart; } else val = 0.0; self->data[i] += (val * amp); } if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } } static void Granulator_transform_aia(Granulator *self) { MYFLT val, x, x1, inc, index, fpart, amp, ppos, frtosamps; int i, j, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); MYFLT *pit = Stream_getData((Stream *)self->pitch_stream); MYFLT pos = PyFloat_AS_DOUBLE(self->pos); MYFLT *dur = Stream_getData((Stream *)self->dur_stream); frtosamps = (1.0 / self->basedur) / self->sr; for (i=0; ibufsize; i++) { self->data[i] = 0.0; inc = pit[i] * frtosamps; self->pointerPos += inc; for (j=0; jngrains; j++) { ppos = self->pointerPos + self->gphase[j]; if (ppos >= 1.0) { ppos -= 1.0; } // compute envelope index = ppos * envsize; ipart = (int)index; fpart = index - ipart; x = envlist[ipart]; x1 = envlist[ipart+1]; amp = x + (x1 - x) * fpart; if (ppos < self->lastppos[j]) { self->startPos[j] = pos; self->gsize[j] = dur[i] * self->sr; } self->lastppos[j] = ppos; // compute sampling index = ppos * self->gsize[j] + self->startPos[j]; if (index >= 0 && index < size) { ipart = (int)index; fpart = index - ipart; x = tablelist[ipart]; x1 = tablelist[ipart+1]; val = x + (x1 - x) * fpart; } else val = 0.0; self->data[i] += (val * amp); } if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } } static void Granulator_transform_iaa(Granulator *self) { MYFLT val, x, x1, inc, index, fpart, amp, ppos; int i, j, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); MYFLT pit = PyFloat_AS_DOUBLE(self->pitch); MYFLT *pos = Stream_getData((Stream *)self->pos_stream); MYFLT *dur = Stream_getData((Stream *)self->dur_stream); inc = pit * (1.0 / self->basedur) / self->sr; for (i=0; ibufsize; i++) { self->data[i] = 0.0; self->pointerPos += inc; for (j=0; jngrains; j++) { ppos = self->pointerPos + self->gphase[j]; if (ppos >= 1.0) { ppos -= 1.0; } // compute envelope index = ppos * envsize; ipart = (int)index; fpart = index - ipart; x = envlist[ipart]; x1 = envlist[ipart+1]; amp = x + (x1 - x) * fpart; if (ppos < self->lastppos[j]) { self->startPos[j] = pos[i]; self->gsize[j] = dur[i] * self->sr; } self->lastppos[j] = ppos; // compute sampling index = ppos * self->gsize[j] + self->startPos[j]; if (index >= 0 && index < size) { ipart = (int)index; fpart = index - ipart; x = tablelist[ipart]; x1 = tablelist[ipart+1]; val = x + (x1 - x) * fpart; } else val = 0.0; self->data[i] += (val * amp); } if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } } static void Granulator_transform_aaa(Granulator *self) { MYFLT val, x, x1, inc, index, fpart, amp, ppos, frtosamps; int i, j, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); MYFLT *pit = Stream_getData((Stream *)self->pitch_stream); MYFLT *pos = Stream_getData((Stream *)self->pos_stream); MYFLT *dur = Stream_getData((Stream *)self->dur_stream); frtosamps = (1.0 / self->basedur) / self->sr; for (i=0; ibufsize; i++) { self->data[i] = 0.0; inc = pit[i] * frtosamps; self->pointerPos += inc; for (j=0; jngrains; j++) { ppos = self->pointerPos + self->gphase[j]; if (ppos >= 1.0) { ppos -= 1.0; } // compute envelope index = ppos * envsize; ipart = (int)index; fpart = index - ipart; x = envlist[ipart]; x1 = envlist[ipart+1]; amp = x + (x1 - x) * fpart; if (ppos < self->lastppos[j]) { self->startPos[j] = pos[i]; self->gsize[j] = dur[i] * self->sr; } self->lastppos[j] = ppos; // compute sampling index = ppos * self->gsize[j] + self->startPos[j]; if (index >= 0 && index < size) { ipart = (int)index; fpart = index - ipart; x = tablelist[ipart]; x1 = tablelist[ipart+1]; val = x + (x1 - x) * fpart; } else val = 0.0; self->data[i] += (val * amp); } if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } } static void Granulator_postprocessing_ii(Granulator *self) { POST_PROCESSING_II }; static void Granulator_postprocessing_ai(Granulator *self) { POST_PROCESSING_AI }; static void Granulator_postprocessing_ia(Granulator *self) { POST_PROCESSING_IA }; static void Granulator_postprocessing_aa(Granulator *self) { POST_PROCESSING_AA }; static void Granulator_postprocessing_ireva(Granulator *self) { POST_PROCESSING_IREVA }; static void Granulator_postprocessing_areva(Granulator *self) { POST_PROCESSING_AREVA }; static void Granulator_postprocessing_revai(Granulator *self) { POST_PROCESSING_REVAI }; static void Granulator_postprocessing_revaa(Granulator *self) { POST_PROCESSING_REVAA }; static void Granulator_postprocessing_revareva(Granulator *self) { POST_PROCESSING_REVAREVA }; static void Granulator_setProcMode(Granulator *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Granulator_transform_iii; break; case 1: self->proc_func_ptr = Granulator_transform_aii; break; case 10: self->proc_func_ptr = Granulator_transform_iai; break; case 11: self->proc_func_ptr = Granulator_transform_aai; break; case 100: self->proc_func_ptr = Granulator_transform_iia; break; case 101: self->proc_func_ptr = Granulator_transform_aia; break; case 110: self->proc_func_ptr = Granulator_transform_iaa; break; case 111: self->proc_func_ptr = Granulator_transform_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Granulator_postprocessing_ii; break; case 1: self->muladd_func_ptr = Granulator_postprocessing_ai; break; case 2: self->muladd_func_ptr = Granulator_postprocessing_revai; break; case 10: self->muladd_func_ptr = Granulator_postprocessing_ia; break; case 11: self->muladd_func_ptr = Granulator_postprocessing_aa; break; case 12: self->muladd_func_ptr = Granulator_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Granulator_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Granulator_postprocessing_areva; break; case 22: self->muladd_func_ptr = Granulator_postprocessing_revareva; break; } } static void Granulator_compute_next_data_frame(Granulator *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Granulator_traverse(Granulator *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->env); Py_VISIT(self->pitch); Py_VISIT(self->pitch_stream); Py_VISIT(self->pos); Py_VISIT(self->pos_stream); Py_VISIT(self->dur); Py_VISIT(self->dur_stream); return 0; } static int Granulator_clear(Granulator *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->env); Py_CLEAR(self->pitch); Py_CLEAR(self->pitch_stream); Py_CLEAR(self->pos); Py_CLEAR(self->pos_stream); Py_CLEAR(self->dur); Py_CLEAR(self->dur_stream); return 0; } static void Granulator_dealloc(Granulator* self) { pyo_DEALLOC free(self->startPos); free(self->gphase); free(self->gsize); free(self->lastppos); Granulator_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Granulator_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT phase; PyObject *tabletmp, *envtmp, *pitchtmp=NULL, *postmp=NULL, *durtmp=NULL, *multmp=NULL, *addtmp=NULL; Granulator *self; self = (Granulator *)type->tp_alloc(type, 0); self->pitch = PyFloat_FromDouble(1); self->pos = PyFloat_FromDouble(0.0); self->dur = PyFloat_FromDouble(0.1); self->ngrains = 8; self->basedur = 0.1; self->pointerPos = 1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Granulator_compute_next_data_frame); self->mode_func_ptr = Granulator_setProcMode; static char *kwlist[] = {"table", "env", "pitch", "pos", "dur", "grains", "basedur", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_OOOIFOO, kwlist, &tabletmp, &envtmp, &pitchtmp, &postmp, &durtmp, &self->ngrains, &self->basedur, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of Granulator must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if ( PyObject_HasAttrString((PyObject *)envtmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"env\" argument of Granulator must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->env); self->env = PyObject_CallMethod((PyObject *)envtmp, "getTableStream", ""); if (pitchtmp) { PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp); } if (postmp) { PyObject_CallMethod((PyObject *)self, "setPos", "O", postmp); } if (durtmp) { PyObject_CallMethod((PyObject *)self, "setDur", "O", durtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->startPos = (MYFLT *)realloc(self->startPos, self->ngrains * sizeof(MYFLT)); self->gsize = (MYFLT *)realloc(self->gsize, self->ngrains * sizeof(MYFLT)); self->gphase = (MYFLT *)realloc(self->gphase, self->ngrains * sizeof(MYFLT)); self->lastppos = (MYFLT *)realloc(self->lastppos, self->ngrains * sizeof(MYFLT)); Server_generateSeed((Server *)self->server, GRANULATOR_ID); for (i=0; ingrains; i++) { phase = ((MYFLT)i/self->ngrains) * (1.0 + ((rand()/((MYFLT)(RAND_MAX)+1)*2.0-1.0) * 0.01)); if (phase < 0.0) phase = 0.0; else if (phase >= 1.0) phase -= 1.0; self->gphase[i] = phase; self->startPos[i] = self->gsize[i] = 0.0; self->lastppos[i] = 1.0; } (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Granulator_getServer(Granulator* self) { GET_SERVER }; static PyObject * Granulator_getStream(Granulator* self) { GET_STREAM }; static PyObject * Granulator_setMul(Granulator *self, PyObject *arg) { SET_MUL }; static PyObject * Granulator_setAdd(Granulator *self, PyObject *arg) { SET_ADD }; static PyObject * Granulator_setSub(Granulator *self, PyObject *arg) { SET_SUB }; static PyObject * Granulator_setDiv(Granulator *self, PyObject *arg) { SET_DIV }; static PyObject * Granulator_play(Granulator *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Granulator_out(Granulator *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Granulator_stop(Granulator *self) { STOP }; static PyObject * Granulator_multiply(Granulator *self, PyObject *arg) { MULTIPLY }; static PyObject * Granulator_inplace_multiply(Granulator *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Granulator_add(Granulator *self, PyObject *arg) { ADD }; static PyObject * Granulator_inplace_add(Granulator *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Granulator_sub(Granulator *self, PyObject *arg) { SUB }; static PyObject * Granulator_inplace_sub(Granulator *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Granulator_div(Granulator *self, PyObject *arg) { DIV }; static PyObject * Granulator_inplace_div(Granulator *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Granulator_setPitch(Granulator *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pitch); if (isNumber == 1) { self->pitch = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->pitch = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pitch, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pitch_stream); self->pitch_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Granulator_setPos(Granulator *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pos); if (isNumber == 1) { self->pos = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->pos = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pos, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pos_stream); self->pos_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Granulator_setDur(Granulator *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->dur); if (isNumber == 1) { self->dur = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->dur = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->dur, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->dur_stream); self->dur_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Granulator_getTable(Granulator* self) { Py_INCREF(self->table); return self->table; }; static PyObject * Granulator_setTable(Granulator *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * Granulator_getEnv(Granulator* self) { Py_INCREF(self->env); return self->env; }; static PyObject * Granulator_setEnv(Granulator *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->env); self->env = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * Granulator_setBaseDur(Granulator *self, PyObject *arg) { if (arg != NULL) self->basedur = PyFloat_AsDouble(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * Granulator_setGrains(Granulator *self, PyObject *arg) { int i; MYFLT phase; if (PyLong_Check(arg) || PyInt_Check(arg)) { self->ngrains = PyLong_AsLong(arg); self->startPos = (MYFLT *)realloc(self->startPos, self->ngrains * sizeof(MYFLT)); self->gsize = (MYFLT *)realloc(self->gsize, self->ngrains * sizeof(MYFLT)); self->gphase = (MYFLT *)realloc(self->gphase, self->ngrains * sizeof(MYFLT)); self->lastppos = (MYFLT *)realloc(self->lastppos, self->ngrains * sizeof(MYFLT)); for (i=0; ingrains; i++) { phase = ((MYFLT)i/self->ngrains) * (1.0 + ((rand()/((MYFLT)(RAND_MAX)+1)*2.0-1.0) * 0.01)); if (phase < 0.0) phase = 0.0; else if (phase >= 1.0) phase -= 1.0; self->gphase[i] = phase; self->startPos[i] = self->gsize[i] = 0.0; self->lastppos[i] = 1.0; } } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Granulator_members[] = { {"server", T_OBJECT_EX, offsetof(Granulator, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Granulator, stream), 0, "Stream object."}, {"table", T_OBJECT_EX, offsetof(Granulator, table), 0, "Sound table."}, {"env", T_OBJECT_EX, offsetof(Granulator, env), 0, "Envelope table."}, {"pitch", T_OBJECT_EX, offsetof(Granulator, pitch), 0, "Speed of the reading pointer."}, {"pos", T_OBJECT_EX, offsetof(Granulator, pos), 0, "Position in the sound table."}, {"dur", T_OBJECT_EX, offsetof(Granulator, dur), 0, "Duration of each grains."}, {"mul", T_OBJECT_EX, offsetof(Granulator, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Granulator, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Granulator_methods[] = { {"getTable", (PyCFunction)Granulator_getTable, METH_NOARGS, "Returns sound table object."}, {"setTable", (PyCFunction)Granulator_setTable, METH_O, "Sets sound table."}, {"getEnv", (PyCFunction)Granulator_getEnv, METH_NOARGS, "Returns envelope table object."}, {"setEnv", (PyCFunction)Granulator_setEnv, METH_O, "Sets envelope table."}, {"getServer", (PyCFunction)Granulator_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Granulator_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Granulator_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Granulator_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Granulator_stop, METH_NOARGS, "Stops computing."}, {"setPitch", (PyCFunction)Granulator_setPitch, METH_O, "Sets global pitch factor."}, {"setPos", (PyCFunction)Granulator_setPos, METH_O, "Sets position in the sound table."}, {"setDur", (PyCFunction)Granulator_setDur, METH_O, "Sets the grain duration."}, {"setBaseDur", (PyCFunction)Granulator_setBaseDur, METH_O, "Sets the grain base duration."}, {"setGrains", (PyCFunction)Granulator_setGrains, METH_O, "Sets the number of grains."}, {"setMul", (PyCFunction)Granulator_setMul, METH_O, "Sets granulator mul factor."}, {"setAdd", (PyCFunction)Granulator_setAdd, METH_O, "Sets granulator add factor."}, {"setSub", (PyCFunction)Granulator_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Granulator_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Granulator_as_number = { (binaryfunc)Granulator_add, /*nb_add*/ (binaryfunc)Granulator_sub, /*nb_subtract*/ (binaryfunc)Granulator_multiply, /*nb_multiply*/ (binaryfunc)Granulator_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Granulator_inplace_add, /*inplace_add*/ (binaryfunc)Granulator_inplace_sub, /*inplace_subtract*/ (binaryfunc)Granulator_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Granulator_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject GranulatorType = { PyObject_HEAD_INIT(NULL) 0, /*ob_pitch*/ "_pyo.Granulator_base", /*tp_name*/ sizeof(Granulator), /*tp_basicpitch*/ 0, /*tp_itempitch*/ (destructor)Granulator_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Granulator_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Granulator objects. Accumulation of multiples grains of sound.", /* tp_doc */ (traverseproc)Granulator_traverse, /* tp_traverse */ (inquiry)Granulator_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Granulator_methods, /* tp_methods */ Granulator_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Granulator_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *table; PyObject *pitch; Stream *pitch_stream; PyObject *start; Stream *start_stream; PyObject *dur; Stream *dur_stream; PyObject *xfade; Stream *xfade_stream; MYFLT *trigsBuffer; TriggerStream *trig_stream; int xfadeshape; int startfromloop; int init; int mode[2]; /* 0 = no loop, 1 = forward, 2 = backward, 3 = back-and-forth */ int tmpmode; int direction[2]; double pointerPos[2]; int active[2]; long loopstart[2]; long loopend[2]; long crossfadedur[2]; MYFLT crossfadescaling[2]; long minfadepoint[2]; long maxfadepoint[2]; MYFLT *fader; int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */ MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int); int modebuffer[6]; int autosmooth; MYFLT lastpitch; // sample memories MYFLT y1; MYFLT y2; // variables MYFLT c1; } Looper; static void Looper_reset(Looper *self, int x, int which, int init) { MYFLT start, dur, xfade; int size = TableStream_getSize(self->table) - 1; double tableSr = TableStream_getSamplingRate(self->table); if (self->modebuffer[3] == 0) start = PyFloat_AS_DOUBLE(self->start); else start = Stream_getData((Stream *)self->start_stream)[x]; if (self->modebuffer[4] == 0) dur = PyFloat_AS_DOUBLE(self->dur); else dur = Stream_getData((Stream *)self->dur_stream)[x]; if (self->modebuffer[5] == 0) xfade = PyFloat_AS_DOUBLE(self->xfade); else xfade = Stream_getData((Stream *)self->xfade_stream)[x]; if (start < 0.0) start = 0.0; else if (start > (size/tableSr)) start = (MYFLT)(size/tableSr); if (dur < 0.001) dur = 0.001; if (xfade < 0.0) xfade = 0.0; else if (xfade > 50.0) xfade = 50.0; if (self->xfadeshape == 0) self->fader = LOOPER_LINEAR_FADE; else if (self->xfadeshape == 1) self->fader = LOOPER_POWER_FADE; else if (self->xfadeshape == 2) self->fader = LOOPER_SIGMOID_FADE; else self->fader = LOOPER_LINEAR_FADE; if (self->tmpmode != self->mode[which]) self->mode[which] = self->tmpmode; if (init == 0) self->trigsBuffer[x] = 1.0; switch (self->mode[which]) { case 0: self->loopstart[which] = 0; self->loopend[which] = (long)size; if (self->crossfadedur[which] < 1) self->crossfadedur[which] = 1; self->crossfadescaling[which] = 1.0 / self->crossfadedur[which] * 512.0; if (init == 1 && self->startfromloop == 0) { self->minfadepoint[which] = self->crossfadedur[which]; self->maxfadepoint[which] = self->loopend[which] - self->crossfadedur[which]; self->pointerPos[which] = self->loopstart[which] = 0.0; } else { self->minfadepoint[which] = self->loopstart[which] + self->crossfadedur[which]; self->maxfadepoint[which] = self->loopend[which] - self->crossfadedur[which]; self->pointerPos[which] = self->loopstart[which]; } break; case 1: self->loopstart[which] = (long)(start * tableSr); self->loopend[which] = (long)((start + dur) * tableSr); self->crossfadedur[which] = (long)((self->loopend[which] - self->loopstart[which]) * xfade * 0.01); if (self->crossfadedur[which] < 1) self->crossfadedur[which] = 1; self->crossfadescaling[which] = 1.0 / self->crossfadedur[which] * 512.0; if (init == 1 && self->startfromloop == 0) { self->minfadepoint[which] = self->crossfadedur[which]; self->maxfadepoint[which] = self->loopend[which] - self->crossfadedur[which]; self->pointerPos[which] = self->loopstart[which] = 0.0; } else { self->minfadepoint[which] = self->loopstart[which] + self->crossfadedur[which]; self->maxfadepoint[which] = self->loopend[which] - self->crossfadedur[which]; self->pointerPos[which] = self->loopstart[which]; } break; case 2: self->loopstart[which] = (long)((start + dur) * tableSr); self->loopend[which] = (long)(start * tableSr); self->crossfadedur[which] = (long)((self->loopstart[which] - self->loopend[which]) * xfade * 0.01); if (self->crossfadedur[which] < 1) self->crossfadedur[which] = 1; self->crossfadescaling[which] = 1.0 / self->crossfadedur[which] * 512.0; if (init == 1 && self->startfromloop == 0) { self->minfadepoint[which] = size - self->crossfadedur[which]; self->maxfadepoint[which] = self->loopend[which] + self->crossfadedur[which]; self->pointerPos[which] = self->loopstart[which] = (MYFLT)size; } else { self->minfadepoint[which] = self->loopstart[which] - self->crossfadedur[which]; self->maxfadepoint[which] = self->loopend[which] + self->crossfadedur[which]; self->pointerPos[which] = self->loopstart[which]; } break; case 3: if (self->direction[1-which] == 0) { self->direction[which] = 1; self->loopstart[which] = (long)((start + dur) * tableSr); self->loopend[which] = (long)(start * tableSr); self->crossfadedur[which] = (long)((self->loopstart[which] - self->loopend[which]) * xfade * 0.01); if (self->crossfadedur[which] < 1) self->crossfadedur[which] = 1; self->crossfadescaling[which] = 1.0 / self->crossfadedur[which] * 512.0; self->minfadepoint[which] = self->loopstart[which] - self->crossfadedur[which]; self->maxfadepoint[which] = self->loopend[which] + self->crossfadedur[which]; self->pointerPos[which] = self->loopstart[which]; } else { self->direction[which] = 0; self->loopstart[which] = (long)(start * tableSr); self->loopend[which] = (long)((start + dur) * tableSr); self->crossfadedur[which] = (long)((self->loopend[which] - self->loopstart[which]) * xfade * 0.01); if (self->crossfadedur[which] < 1) self->crossfadedur[which] = 1; self->crossfadescaling[which] = 1.0 / self->crossfadedur[which] * 512.0; if (init == 1 && self->startfromloop == 0) { self->minfadepoint[which] = self->crossfadedur[which]; self->maxfadepoint[which] = self->loopend[which] - self->crossfadedur[which]; self->pointerPos[which] = self->loopstart[which] = 0.0; } else { self->minfadepoint[which] = self->loopstart[which] + self->crossfadedur[which]; self->maxfadepoint[which] = self->loopend[which] - self->crossfadedur[which]; self->pointerPos[which] = self->loopstart[which]; } } break; } self->active[which] = 1; } static MYFLT Looper_get_amp(Looper *self, MYFLT pos) { int ipart = (int)pos; return self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * (pos - ipart); } static void Looper_transform_i(Looper *self) { MYFLT fpart, amp, fr; double pit; int i, j, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); double tableSr = TableStream_getSamplingRate(self->table); MYFLT pitval = PyFloat_AS_DOUBLE(self->pitch); if (pitval < 0.0) pitval = 0.0; pit = pitval * tableSr / self->sr; for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } if (self->active[0] == 0 && self->active[1] == 0) { Looper_reset(self, 0, 0, 1); } for (i=0; ibufsize; i++) { self->data[i] = 0.0; for (j=0; j<2; j++) { if (self->active[j] == 1) { switch (self->mode[j]) { case 0: if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) { if (self->pointerPos[j] < self->minfadepoint[j]) { fpart = (self->pointerPos[j] - self->loopstart[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else if (self->pointerPos[j] > self->maxfadepoint[j]) { fpart = (self->loopend[j] - self->pointerPos[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else amp = 1.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp; } self->pointerPos[j] += pit; if (self->pointerPos[j] < 0.0) self->pointerPos[j] = 0.0; else if (self->pointerPos[j] >= self->loopend[j]) { self->active[j] = 0; PyObject_CallMethod((PyObject *)self, "stop", NULL); } break; case 1: if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) { if (self->pointerPos[j] < self->minfadepoint[j]) { fpart = (self->pointerPos[j] - self->loopstart[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else if (self->pointerPos[j] > self->maxfadepoint[j]) { fpart = (self->loopend[j] - self->pointerPos[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else amp = 1.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp; } self->pointerPos[j] += pit; if (self->pointerPos[j] < 0.0) self->pointerPos[j] = 0.0; else if (self->pointerPos[j] > self->maxfadepoint[j] && self->active[1-j] == 0) Looper_reset(self, i, 1-j, 0); if (self->pointerPos[j] >= self->loopend[j]) self->active[j] = 0; break; case 2: if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) { if (self->pointerPos[j] > self->minfadepoint[j]) { fpart = (self->loopstart[j] - self->pointerPos[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else if (self->pointerPos[j] < self->maxfadepoint[j]) { fpart = (self->pointerPos[j] - self->loopend[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else amp = 1.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp; } self->pointerPos[j] -= pit; if (self->pointerPos[j] >= size) self->pointerPos[j] = size-1; else if (self->pointerPos[j] < self->maxfadepoint[j] && self->active[1-j] == 0) Looper_reset(self, i, 1-j, 0); if (self->pointerPos[j] <= self->loopend[j]) self->active[j] = 0; break; case 3: if (self->direction[j] == 0) { if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) { if (self->pointerPos[j] < self->minfadepoint[j]) { fpart = (self->pointerPos[j] - self->loopstart[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else if (self->pointerPos[j] > self->maxfadepoint[j]) { fpart = (self->loopend[j] - self->pointerPos[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else amp = 1.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp; } self->pointerPos[j] += pit; if (self->pointerPos[j] < 0.0) self->pointerPos[j] = 0.0; else if (self->pointerPos[j] > self->maxfadepoint[j] && self->active[1-j] == 0) Looper_reset(self, i, 1-j, 0); if (self->pointerPos[j] >= self->loopend[j]) self->active[j] = 0; } else { if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) { if (self->pointerPos[j] > self->minfadepoint[j]) { fpart = (self->loopstart[j] - self->pointerPos[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else if (self->pointerPos[j] < self->maxfadepoint[j]) { fpart = (self->pointerPos[j] - self->loopend[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else amp = 1.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp; } self->pointerPos[j] -= pit; if (self->pointerPos[j] >= size) self->pointerPos[j] = size-1; else if (self->pointerPos[j] < self->maxfadepoint[j] && self->active[1-j] == 0) Looper_reset(self, i, 1-j, 0); if (self->pointerPos[j] <= self->loopend[j]) self->active[j] = 0; } break; } // end of switch } } } /* Automatic smoothering of low transposition */ if (self->autosmooth == 1 && pitval < 1.0) { if (self->lastpitch != pitval) { self->lastpitch = pitval; if (pitval < 0.001) pitval = 0.001; fr = pitval * self->sr * 0.45; self->c1 = MYEXP(-TWOPI * fr / self->sr); } for (i=0; ibufsize; i++) { self->y1 = self->data[i] + (self->y1 - self->data[i]) * self->c1; self->y2 = self->y1 + (self->y2 - self->y1) * self->c1; self->data[i] = self->y2; } } } static void Looper_transform_a(Looper *self) { MYFLT fpart, amp, fr, pitval; double pit, srFactor; int i, j, ipart; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); double tableSr = TableStream_getSamplingRate(self->table); MYFLT *pitch = Stream_getData((Stream *)self->pitch_stream); srFactor = tableSr / self->sr; if (self->active[0] == 0 && self->active[1] == 0) { Looper_reset(self, 0, 0, 1); } for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } for (i=0; ibufsize; i++) { self->data[i] = 0.0; pitval = pitch[i]; if (pitval < 0.0) pitval = 0.0; pit = pitval * srFactor; for (j=0; j<2; j++) { if (self->active[j] == 1) { switch (self->mode[j]) { case 0: if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) { if (self->pointerPos[j] < self->minfadepoint[j]) { fpart = (self->pointerPos[j] - self->loopstart[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else if (self->pointerPos[j] > self->maxfadepoint[j]) { fpart = (self->loopend[j] - self->pointerPos[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else amp = 1.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp; } self->pointerPos[j] += pit; if (self->pointerPos[j] < 0.0) self->pointerPos[j] = 0.0; else if (self->pointerPos[j] >= self->loopend[j]) { self->active[j] = 0; PyObject_CallMethod((PyObject *)self, "stop", NULL); } break; case 1: if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) { if (self->pointerPos[j] < self->minfadepoint[j]) { fpart = (self->pointerPos[j] - self->loopstart[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else if (self->pointerPos[j] > self->maxfadepoint[j]) { fpart = (self->loopend[j] - self->pointerPos[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else amp = 1.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp; } self->pointerPos[j] += pit; if (self->pointerPos[j] < 0.0) self->pointerPos[j] = 0.0; else if (self->pointerPos[j] > self->maxfadepoint[j] && self->active[1-j] == 0) Looper_reset(self, i, 1-j, 0); if (self->pointerPos[j] >= self->loopend[j]) self->active[j] = 0; break; case 2: if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) { if (self->pointerPos[j] > self->minfadepoint[j]) { fpart = (self->loopstart[j] - self->pointerPos[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else if (self->pointerPos[j] < self->maxfadepoint[j]) { fpart = (self->pointerPos[j] - self->loopend[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else amp = 1.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp; } self->pointerPos[j] -= pit; if (self->pointerPos[j] >= size) self->pointerPos[j] = size-1; else if (self->pointerPos[j] < self->maxfadepoint[j] && self->active[1-j] == 0) Looper_reset(self, i, 1-j, 0); if (self->pointerPos[j] <= self->loopend[j]) self->active[j] = 0; break; case 3: if (self->direction[j] == 0) { if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) { if (self->pointerPos[j] < self->minfadepoint[j]) { fpart = (self->pointerPos[j] - self->loopstart[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else if (self->pointerPos[j] > self->maxfadepoint[j]) { fpart = (self->loopend[j] - self->pointerPos[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else amp = 1.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp; } self->pointerPos[j] += pit; if (self->pointerPos[j] < 0.0) self->pointerPos[j] = 0.0; else if (self->pointerPos[j] > self->maxfadepoint[j] && self->active[1-j] == 0) Looper_reset(self, i, 1-j, 0); if (self->pointerPos[j] >= self->loopend[j]) self->active[j] = 0; } else { if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) { if (self->pointerPos[j] > self->minfadepoint[j]) { fpart = (self->loopstart[j] - self->pointerPos[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else if (self->pointerPos[j] < self->maxfadepoint[j]) { fpart = (self->pointerPos[j] - self->loopend[j]) * self->crossfadescaling[j]; amp = Looper_get_amp(self, fpart); } else amp = 1.0; ipart = (int)self->pointerPos[j]; fpart = self->pointerPos[j] - ipart; self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp; } self->pointerPos[j] -= pit; if (self->pointerPos[j] >= size) self->pointerPos[j] = size-1; else if (self->pointerPos[j] < self->maxfadepoint[j] && self->active[1-j] == 0) Looper_reset(self, i, 1-j, 0); if (self->pointerPos[j] <= self->loopend[j]) self->active[j] = 0; } break; } // end of switch } } } /* Automatic smoothering of low transposition */ if (self->autosmooth == 1) { for (i=0; ibufsize; i++) { pitval = pitch[i]; if (pitval < 0.001) pitval = 0.001; if (pitval < 1.0) { if (self->lastpitch != pitval) { self->lastpitch = pitval; fr = pitval * self->sr * 0.45; self->c1 = MYEXP(-TWOPI * fr / self->sr); } self->y1 = self->data[i] + (self->y1 - self->data[i]) * self->c1; self->y2 = self->y1 + (self->y2 - self->y1) * self->c1; self->data[i] = self->y2; } } } } static void Looper_postprocessing_ii(Looper *self) { POST_PROCESSING_II }; static void Looper_postprocessing_ai(Looper *self) { POST_PROCESSING_AI }; static void Looper_postprocessing_ia(Looper *self) { POST_PROCESSING_IA }; static void Looper_postprocessing_aa(Looper *self) { POST_PROCESSING_AA }; static void Looper_postprocessing_ireva(Looper *self) { POST_PROCESSING_IREVA }; static void Looper_postprocessing_areva(Looper *self) { POST_PROCESSING_AREVA }; static void Looper_postprocessing_revai(Looper *self) { POST_PROCESSING_REVAI }; static void Looper_postprocessing_revaa(Looper *self) { POST_PROCESSING_REVAA }; static void Looper_postprocessing_revareva(Looper *self) { POST_PROCESSING_REVAREVA }; static void Looper_setProcMode(Looper *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Looper_transform_i; break; case 1: self->proc_func_ptr = Looper_transform_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Looper_postprocessing_ii; break; case 1: self->muladd_func_ptr = Looper_postprocessing_ai; break; case 2: self->muladd_func_ptr = Looper_postprocessing_revai; break; case 10: self->muladd_func_ptr = Looper_postprocessing_ia; break; case 11: self->muladd_func_ptr = Looper_postprocessing_aa; break; case 12: self->muladd_func_ptr = Looper_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Looper_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Looper_postprocessing_areva; break; case 22: self->muladd_func_ptr = Looper_postprocessing_revareva; break; } } static void Looper_compute_next_data_frame(Looper *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Looper_traverse(Looper *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->pitch); Py_VISIT(self->pitch_stream); Py_VISIT(self->start); Py_VISIT(self->start_stream); Py_VISIT(self->dur); Py_VISIT(self->dur_stream); Py_VISIT(self->xfade); Py_VISIT(self->xfade_stream); Py_VISIT(self->trig_stream); return 0; } static int Looper_clear(Looper *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->pitch); Py_CLEAR(self->pitch_stream); Py_CLEAR(self->start); Py_CLEAR(self->start_stream); Py_CLEAR(self->dur); Py_CLEAR(self->dur_stream); Py_CLEAR(self->xfade); Py_CLEAR(self->xfade_stream); Py_CLEAR(self->trig_stream); return 0; } static void Looper_dealloc(Looper* self) { pyo_DEALLOC free(self->trigsBuffer); Looper_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Looper_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *tabletmp, *pitchtmp=NULL, *starttmp=NULL, *durtmp=NULL, *xfadetmp=NULL, *multmp=NULL, *addtmp=NULL; Looper *self; self = (Looper *)type->tp_alloc(type, 0); self->pitch = PyFloat_FromDouble(1.0); self->start = PyFloat_FromDouble(0.0); self->dur = PyFloat_FromDouble(1.0); self->xfade = PyFloat_FromDouble(20.0); self->lastpitch = -1.0; self->autosmooth = 0; self->y1 = self->y2 = self->c1 = 0.0; self->xfadeshape = 0; self->startfromloop = 0; self->interp = 2; self->init = 1; self->mode[0] = self->mode[1] = self->tmpmode = 1; self->direction[0] = self->direction[1] = 0; self->pointerPos[0] = self->pointerPos[1] = 0.0; self->active[0] = self->active[1] = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Looper_compute_next_data_frame); self->mode_func_ptr = Looper_setProcMode; static char *kwlist[] = {"table", "pitch", "start", "dur", "xfade", "mode", "xfadeshape", "startfromloop", "interp", "autosmooth", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOiiiiiOO", kwlist, &tabletmp, &pitchtmp, &starttmp, &durtmp, &xfadetmp, &self->tmpmode, &self->xfadeshape, &self->startfromloop, &self->interp, &self->autosmooth, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of Looper must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if (pitchtmp) { PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp); } if (starttmp) { PyObject_CallMethod((PyObject *)self, "setStart", "O", starttmp); } if (durtmp) { PyObject_CallMethod((PyObject *)self, "setDur", "O", durtmp); } if (xfadetmp) { PyObject_CallMethod((PyObject *)self, "setXfade", "O", xfadetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); if (self->tmpmode >= 0 && self->tmpmode < 4) self->mode[0] = self->mode[1] = self->tmpmode; else self->mode[0] = self->mode[1] = self->tmpmode = 1; SET_INTERP_POINTER return (PyObject *)self; } static PyObject * Looper_getServer(Looper* self) { GET_SERVER }; static PyObject * Looper_getStream(Looper* self) { GET_STREAM }; static PyObject * Looper_getTriggerStream(Looper* self) { GET_TRIGGER_STREAM }; static PyObject * Looper_setMul(Looper *self, PyObject *arg) { SET_MUL }; static PyObject * Looper_setAdd(Looper *self, PyObject *arg) { SET_ADD }; static PyObject * Looper_setSub(Looper *self, PyObject *arg) { SET_SUB }; static PyObject * Looper_setDiv(Looper *self, PyObject *arg) { SET_DIV }; static PyObject * Looper_play(Looper *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Looper_out(Looper *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Looper_stop(Looper *self) { STOP }; static PyObject * Looper_multiply(Looper *self, PyObject *arg) { MULTIPLY }; static PyObject * Looper_inplace_multiply(Looper *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Looper_add(Looper *self, PyObject *arg) { ADD }; static PyObject * Looper_inplace_add(Looper *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Looper_sub(Looper *self, PyObject *arg) { SUB }; static PyObject * Looper_inplace_sub(Looper *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Looper_div(Looper *self, PyObject *arg) { DIV }; static PyObject * Looper_inplace_div(Looper *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Looper_setPitch(Looper *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pitch); if (isNumber == 1) { self->pitch = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->pitch = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pitch, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pitch_stream); self->pitch_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Looper_setStart(Looper *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->start); if (isNumber == 1) { self->start = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->start = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->start, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->start_stream); self->start_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * Looper_setDur(Looper *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->dur); if (isNumber == 1) { self->dur = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->dur = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->dur, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->dur_stream); self->dur_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * Looper_setXfade(Looper *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->xfade); if (isNumber == 1) { self->xfade = PyNumber_Float(tmp); self->modebuffer[5] = 0; } else { self->xfade = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->xfade, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->xfade_stream); self->xfade_stream = (Stream *)streamtmp; self->modebuffer[5] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * Looper_getTable(Looper* self) { Py_INCREF(self->table); return self->table; }; static PyObject * Looper_setTable(Looper *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * Looper_setStartFromLoop(Looper *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { self->startfromloop = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Looper_setXfadeShape(Looper *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { self->xfadeshape = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Looper_setMode(Looper *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { tmp = PyInt_AsLong(arg); if (tmp >= 0 && tmp < 4) self->tmpmode = tmp; } Py_INCREF(Py_None); return Py_None; } static PyObject * Looper_setInterp(Looper *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->interp = PyInt_AsLong(PyNumber_Int(arg)); } SET_INTERP_POINTER Py_INCREF(Py_None); return Py_None; } static PyObject * Looper_setAutoSmooth(Looper *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { self->autosmooth = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Looper_on_reset(Looper *self) { self->pointerPos[0] = self->pointerPos[1] = 0.0; self->active[0] = self->active[1] = 0; Py_INCREF(Py_None); return Py_None; }; static PyMemberDef Looper_members[] = { {"server", T_OBJECT_EX, offsetof(Looper, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Looper, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(Looper, trig_stream), 0, "Trigger Stream object."}, {"table", T_OBJECT_EX, offsetof(Looper, table), 0, "Sound table."}, {"pitch", T_OBJECT_EX, offsetof(Looper, pitch), 0, "Speed of the reading pointer."}, {"start", T_OBJECT_EX, offsetof(Looper, start), 0, "Position in the sound table."}, {"dur", T_OBJECT_EX, offsetof(Looper, dur), 0, "Duration of each grains."}, {"xfade", T_OBJECT_EX, offsetof(Looper, xfade), 0, "Crossfade duration in percent."}, {"mul", T_OBJECT_EX, offsetof(Looper, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Looper, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Looper_methods[] = { {"getTable", (PyCFunction)Looper_getTable, METH_NOARGS, "Returns sound table object."}, {"setTable", (PyCFunction)Looper_setTable, METH_O, "Sets sound table."}, {"getServer", (PyCFunction)Looper_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Looper_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)Looper_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"play", (PyCFunction)Looper_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Looper_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Looper_stop, METH_NOARGS, "Stops computing."}, {"setPitch", (PyCFunction)Looper_setPitch, METH_O, "Sets global pitch factor."}, {"setStart", (PyCFunction)Looper_setStart, METH_O, "Sets position in the sound table."}, {"setDur", (PyCFunction)Looper_setDur, METH_O, "Sets the grain duration."}, {"setXfade", (PyCFunction)Looper_setXfade, METH_O, "Sets crossfade length in percent."}, {"setXfadeShape", (PyCFunction)Looper_setXfadeShape, METH_O, "Sets crossfade shape."}, {"setMode", (PyCFunction)Looper_setMode, METH_O, "Sets looping mode (0 = no loop, 1 = forward, 2 = backward, 3 = back-and-forth)."}, {"setStartFromLoop", (PyCFunction)Looper_setStartFromLoop, METH_O, "Sets init pointer position."}, {"setInterp", (PyCFunction)Looper_setInterp, METH_O, "Sets oscillator interpolation mode."}, {"setAutoSmooth", (PyCFunction)Looper_setAutoSmooth, METH_O, "Activate lowpass filter for transposition below 1."}, {"reset", (PyCFunction)Looper_on_reset, METH_NOARGS, "Resets internal counters."}, {"setMul", (PyCFunction)Looper_setMul, METH_O, "Sets granulator mul factor."}, {"setAdd", (PyCFunction)Looper_setAdd, METH_O, "Sets granulator add factor."}, {"setSub", (PyCFunction)Looper_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Looper_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Looper_as_number = { (binaryfunc)Looper_add, /*nb_add*/ (binaryfunc)Looper_sub, /*nb_subtract*/ (binaryfunc)Looper_multiply, /*nb_multiply*/ (binaryfunc)Looper_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Looper_inplace_add, /*inplace_add*/ (binaryfunc)Looper_inplace_sub, /*inplace_subtract*/ (binaryfunc)Looper_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Looper_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject LooperType = { PyObject_HEAD_INIT(NULL) 0, /*ob_pitch*/ "_pyo.Looper_base", /*tp_name*/ sizeof(Looper), /*tp_basicpitch*/ 0, /*tp_itempitch*/ (destructor)Looper_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Looper_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Looper objects. Sound looper with crossfade.", /* tp_doc */ (traverseproc)Looper_traverse, /* tp_traverse */ (inquiry)Looper_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Looper_methods, /* tp_methods */ Looper_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Looper_new, /* tp_new */ }; static const MYFLT Granule_MAX_GRAINS = 4096; typedef struct { pyo_audio_HEAD PyObject *table; PyObject *env; PyObject *dens; Stream *dens_stream; PyObject *pitch; Stream *pitch_stream; PyObject *pos; Stream *pos_stream; PyObject *dur; Stream *dur_stream; MYFLT *gpos; MYFLT *glen; MYFLT *inc; MYFLT *phase; int *flags; int num; int sync; double timer; MYFLT oneOnSr; MYFLT srOnRandMax; int modebuffer[6]; } Granule; static void Granule_transform_i(Granule *self) { MYFLT dens, inc, index, amp, phase; int i, j, ipart, flag = 0; MYFLT pit = 0, pos = 0, dur = 0; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); dens = PyFloat_AS_DOUBLE(self->dens); if (dens < 0.0) dens = 0.0; inc = dens * self->oneOnSr; for (i=0; ibufsize; i++) { self->data[i] = 0.0; if (self->sync == 1) { /* synchronous */ self->timer += inc; if (self->timer >= 1.0) { self->timer -= 1.0; flag = 1; } } else { /* asynchronous */ if ((rand() * self->srOnRandMax) < dens) flag = 1; } /* need to start a new grain */ if (flag) { for (j=0; jflags[j] == 0) { self->flags[j] = 1; if (j >= self->num) self->num = j + 1; if (self->modebuffer[3] == 0) pit = PyFloat_AS_DOUBLE(self->pitch); else pit = Stream_getData((Stream *)self->pitch_stream)[i]; if (self->modebuffer[4] == 0) pos = PyFloat_AS_DOUBLE(self->pos); else pos = Stream_getData((Stream *)self->pos_stream)[i]; if (self->modebuffer[5] == 0) dur = PyFloat_AS_DOUBLE(self->dur); else dur = Stream_getData((Stream *)self->dur_stream)[i]; if (pit < 0.0) pit = -pit; if (pos < 0.0) pos = 0.0; else if (pos >= size) pos = (MYFLT)size; if (dur < 0.0001) dur = 0.0001; self->gpos[j] = pos; self->glen[j] = dur * self->sr * pit; if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0) self->flags[j] = 0; self->phase[j] = 0.0; self->inc[j] = 1.0 / (dur * self->sr); break; } } } /* compute active grains */ for (j=0; jnum; j++) { if (self->flags[j]) { phase = self->phase[j]; /* compute envelope */ index = phase * envsize; ipart = (int)index; amp = envlist[ipart] + (envlist[ipart+1] - envlist[ipart]) * (index - ipart); /* compute sampling */ index = phase * self->glen[j] + self->gpos[j]; ipart = (int)index; self->data[i] += (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart)) * amp; phase += self->inc[j]; if (phase >= 1.0) self->flags[j] = 0; else self->phase[j] = phase; } } flag = 0; } } static void Granule_transform_a(Granule *self) { MYFLT index, amp, phase; int i, j, ipart, flag = 0; MYFLT pit = 0, pos = 0, dur = 0; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); MYFLT *density = Stream_getData((Stream *)self->dens_stream); for (i=0; ibufsize; i++) { self->data[i] = 0.0; if (self->sync == 1) { /* synchronous */ self->timer += density[i] * self->oneOnSr; if (self->timer >= 1.0) { self->timer -= 1.0; flag = 1; } } else { /* asynchronous */ if ((rand() * self->srOnRandMax) < density[i]) flag = 1; } /* need to start a new grain */ if (flag) { for (j=0; jflags[j] == 0) { self->flags[j] = 1; if (j >= self->num) self->num = j + 1; if (self->modebuffer[3] == 0) pit = PyFloat_AS_DOUBLE(self->pitch); else pit = Stream_getData((Stream *)self->pitch_stream)[i]; if (self->modebuffer[4] == 0) pos = PyFloat_AS_DOUBLE(self->pos); else pos = Stream_getData((Stream *)self->pos_stream)[i]; if (self->modebuffer[5] == 0) dur = PyFloat_AS_DOUBLE(self->dur); else dur = Stream_getData((Stream *)self->dur_stream)[i]; if (pit < 0.0) pit = -pit; if (pos < 0.0) pos = 0.0; else if (pos >= size) pos = (MYFLT)size; if (dur < 0.0001) dur = 0.0001; self->gpos[j] = pos; self->glen[j] = dur * self->sr * pit; if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0) self->flags[j] = 0; self->phase[j] = 0.0; self->inc[j] = 1.0 / (dur * self->sr); break; } } } /* compute active grains */ for (j=0; jnum; j++) { if (self->flags[j]) { phase = self->phase[j]; // compute envelope index = phase * envsize; ipart = (int)index; amp = envlist[ipart] + (envlist[ipart+1] - envlist[ipart]) * (index - ipart); // compute sampling index = phase * self->glen[j] + self->gpos[j]; ipart = (int)index; self->data[i] += (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart)) * amp; phase += self->inc[j]; if (phase >= 1.0) self->flags[j] = 0; else self->phase[j] = phase; } } flag = 0; } } static void Granule_postprocessing_ii(Granule *self) { POST_PROCESSING_II }; static void Granule_postprocessing_ai(Granule *self) { POST_PROCESSING_AI }; static void Granule_postprocessing_ia(Granule *self) { POST_PROCESSING_IA }; static void Granule_postprocessing_aa(Granule *self) { POST_PROCESSING_AA }; static void Granule_postprocessing_ireva(Granule *self) { POST_PROCESSING_IREVA }; static void Granule_postprocessing_areva(Granule *self) { POST_PROCESSING_AREVA }; static void Granule_postprocessing_revai(Granule *self) { POST_PROCESSING_REVAI }; static void Granule_postprocessing_revaa(Granule *self) { POST_PROCESSING_REVAA }; static void Granule_postprocessing_revareva(Granule *self) { POST_PROCESSING_REVAREVA }; static void Granule_setProcMode(Granule *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Granule_transform_i; break; case 1: self->proc_func_ptr = Granule_transform_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Granule_postprocessing_ii; break; case 1: self->muladd_func_ptr = Granule_postprocessing_ai; break; case 2: self->muladd_func_ptr = Granule_postprocessing_revai; break; case 10: self->muladd_func_ptr = Granule_postprocessing_ia; break; case 11: self->muladd_func_ptr = Granule_postprocessing_aa; break; case 12: self->muladd_func_ptr = Granule_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Granule_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Granule_postprocessing_areva; break; case 22: self->muladd_func_ptr = Granule_postprocessing_revareva; break; } } static void Granule_compute_next_data_frame(Granule *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Granule_traverse(Granule *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->env); Py_VISIT(self->dens); Py_VISIT(self->dens_stream); Py_VISIT(self->pitch); Py_VISIT(self->pitch_stream); Py_VISIT(self->pos); Py_VISIT(self->pos_stream); Py_VISIT(self->dur); Py_VISIT(self->dur_stream); return 0; } static int Granule_clear(Granule *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->env); Py_CLEAR(self->dens); Py_CLEAR(self->dens_stream); Py_CLEAR(self->pitch); Py_CLEAR(self->pitch_stream); Py_CLEAR(self->pos); Py_CLEAR(self->pos_stream); Py_CLEAR(self->dur); Py_CLEAR(self->dur_stream); return 0; } static void Granule_dealloc(Granule* self) { pyo_DEALLOC free(self->gpos); free(self->glen); free(self->inc); free(self->flags); free(self->phase); Granule_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Granule_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *tabletmp, *envtmp, *denstmp=NULL, *pitchtmp=NULL, *postmp=NULL, *durtmp=NULL, *multmp=NULL, *addtmp=NULL; Granule *self; self = (Granule *)type->tp_alloc(type, 0); self->dens = PyFloat_FromDouble(50); self->pitch = PyFloat_FromDouble(1); self->pos = PyFloat_FromDouble(0.0); self->dur = PyFloat_FromDouble(0.1); self->timer = 1.0; self->num = 0; self->sync = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->modebuffer[5] = 0; INIT_OBJECT_COMMON self->oneOnSr = 1.0 / self->sr; self->srOnRandMax = self->sr / (MYFLT)RAND_MAX; Stream_setFunctionPtr(self->stream, Granule_compute_next_data_frame); self->mode_func_ptr = Granule_setProcMode; static char *kwlist[] = {"table", "env", "dens", "pitch", "pos", "dur", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOOOOO", kwlist, &tabletmp, &envtmp, &denstmp, &pitchtmp, &postmp, &durtmp, &multmp, &addtmp)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of Granule must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if ( PyObject_HasAttrString((PyObject *)envtmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"env\" argument of Granule must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->env); self->env = PyObject_CallMethod((PyObject *)envtmp, "getTableStream", ""); if (denstmp) { PyObject_CallMethod((PyObject *)self, "setDens", "O", denstmp); } if (pitchtmp) { PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp); } if (postmp) { PyObject_CallMethod((PyObject *)self, "setPos", "O", postmp); } if (durtmp) { PyObject_CallMethod((PyObject *)self, "setDur", "O", durtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->gpos = (MYFLT *)realloc(self->gpos, Granule_MAX_GRAINS * sizeof(MYFLT)); self->glen = (MYFLT *)realloc(self->glen, Granule_MAX_GRAINS * sizeof(MYFLT)); self->inc = (MYFLT *)realloc(self->inc, Granule_MAX_GRAINS * sizeof(MYFLT)); self->phase = (MYFLT *)realloc(self->phase, Granule_MAX_GRAINS * sizeof(MYFLT)); self->flags = (int *)realloc(self->flags, Granule_MAX_GRAINS * sizeof(int)); for (i=0; igpos[i] = self->glen[i] = self->inc[i] = self->phase[i] = 0.0; self->flags[i] = 0; } Server_generateSeed((Server *)self->server, GRANULE_ID); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Granule_getServer(Granule* self) { GET_SERVER }; static PyObject * Granule_getStream(Granule* self) { GET_STREAM }; static PyObject * Granule_setMul(Granule *self, PyObject *arg) { SET_MUL }; static PyObject * Granule_setAdd(Granule *self, PyObject *arg) { SET_ADD }; static PyObject * Granule_setSub(Granule *self, PyObject *arg) { SET_SUB }; static PyObject * Granule_setDiv(Granule *self, PyObject *arg) { SET_DIV }; static PyObject * Granule_play(Granule *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Granule_out(Granule *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Granule_stop(Granule *self) { STOP }; static PyObject * Granule_multiply(Granule *self, PyObject *arg) { MULTIPLY }; static PyObject * Granule_inplace_multiply(Granule *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Granule_add(Granule *self, PyObject *arg) { ADD }; static PyObject * Granule_inplace_add(Granule *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Granule_sub(Granule *self, PyObject *arg) { SUB }; static PyObject * Granule_inplace_sub(Granule *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Granule_div(Granule *self, PyObject *arg) { DIV }; static PyObject * Granule_inplace_div(Granule *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Granule_setDens(Granule *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->dens); if (isNumber == 1) { self->dens = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->dens = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->dens, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->dens_stream); self->dens_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Granule_setPitch(Granule *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pitch); if (isNumber == 1) { self->pitch = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->pitch = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pitch, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pitch_stream); self->pitch_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * Granule_setPos(Granule *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pos); if (isNumber == 1) { self->pos = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->pos = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pos, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pos_stream); self->pos_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * Granule_setDur(Granule *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->dur); if (isNumber == 1) { self->dur = PyNumber_Float(tmp); self->modebuffer[5] = 0; } else { self->dur = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->dur, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->dur_stream); self->dur_stream = (Stream *)streamtmp; self->modebuffer[5] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * Granule_getTable(Granule* self) { Py_INCREF(self->table); return self->table; }; static PyObject * Granule_setTable(Granule *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * Granule_getEnv(Granule* self) { Py_INCREF(self->env); return self->env; }; static PyObject * Granule_setEnv(Granule *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->env); self->env = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * Granule_setSync(Granule *self, PyObject *arg) { if (PyLong_Check(arg) || PyInt_Check(arg)) { self->sync = PyLong_AsLong(arg); if (self->sync <= 0) self->sync = 0; else self->sync = 1; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Granule_members[] = { {"server", T_OBJECT_EX, offsetof(Granule, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Granule, stream), 0, "Stream object."}, {"table", T_OBJECT_EX, offsetof(Granule, table), 0, "Sound table."}, {"env", T_OBJECT_EX, offsetof(Granule, env), 0, "Envelope table."}, {"dens", T_OBJECT_EX, offsetof(Granule, dens), 0, "Density of grains per second."}, {"pitch", T_OBJECT_EX, offsetof(Granule, pitch), 0, "Speed of the reading pointer."}, {"pos", T_OBJECT_EX, offsetof(Granule, pos), 0, "Position in the sound table."}, {"dur", T_OBJECT_EX, offsetof(Granule, dur), 0, "Duration of each grains."}, {"mul", T_OBJECT_EX, offsetof(Granule, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Granule, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Granule_methods[] = { {"getTable", (PyCFunction)Granule_getTable, METH_NOARGS, "Returns sound table object."}, {"setTable", (PyCFunction)Granule_setTable, METH_O, "Sets sound table."}, {"getEnv", (PyCFunction)Granule_getEnv, METH_NOARGS, "Returns envelope table object."}, {"setEnv", (PyCFunction)Granule_setEnv, METH_O, "Sets envelope table."}, {"getServer", (PyCFunction)Granule_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Granule_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Granule_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Granule_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Granule_stop, METH_NOARGS, "Stops computing."}, {"setDens", (PyCFunction)Granule_setDens, METH_O, "Sets the density of grains per second."}, {"setPitch", (PyCFunction)Granule_setPitch, METH_O, "Sets global pitch factor."}, {"setPos", (PyCFunction)Granule_setPos, METH_O, "Sets position in the sound table."}, {"setDur", (PyCFunction)Granule_setDur, METH_O, "Sets the grain duration."}, {"setSync", (PyCFunction)Granule_setSync, METH_O, "Sets the granulator mode: synchronous or asynchronous."}, {"setMul", (PyCFunction)Granule_setMul, METH_O, "Sets Granule mul factor."}, {"setAdd", (PyCFunction)Granule_setAdd, METH_O, "Sets Granule add factor."}, {"setSub", (PyCFunction)Granule_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Granule_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Granule_as_number = { (binaryfunc)Granule_add, /*nb_add*/ (binaryfunc)Granule_sub, /*nb_subtract*/ (binaryfunc)Granule_multiply, /*nb_multiply*/ (binaryfunc)Granule_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Granule_inplace_add, /*inplace_add*/ (binaryfunc)Granule_inplace_sub, /*inplace_subtract*/ (binaryfunc)Granule_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Granule_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject GranuleType = { PyObject_HEAD_INIT(NULL) 0, /*ob_pitch*/ "_pyo.Granule_base", /*tp_name*/ sizeof(Granule), /*tp_basicpitch*/ 0, /*tp_itempitch*/ (destructor)Granule_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Granule_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Granule objects. Accumulation of multiples grains of sound.", /* tp_doc */ (traverseproc)Granule_traverse, /* tp_traverse */ (inquiry)Granule_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Granule_methods, /* tp_methods */ Granule_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Granule_new, /* tp_new */ }; static const MYFLT MAINPARTICLE_MAX_GRAINS = 4096; typedef struct { pyo_audio_HEAD PyObject *table; PyObject *env; PyObject *dens; Stream *dens_stream; PyObject *pitch; Stream *pitch_stream; PyObject *pos; Stream *pos_stream; PyObject *dur; Stream *dur_stream; PyObject *dev; Stream *dev_stream; PyObject *pan; Stream *pan_stream; MYFLT *gpos; MYFLT *glen; MYFLT *inc; MYFLT *phase; MYFLT *amp1; MYFLT *amp2; int *flags; int *k1; int *k2; int num; int chnls; double timer; double devFactor; double srScale; MYFLT oneOnSr; MYFLT srOnRandMax; MYFLT *buffer_streams; int modebuffer[6]; } MainParticle; static void MainParticle_transform_mono_i(MainParticle *self) { MYFLT dens, inc, index, amp, phase, val; int i, j, ipart, flag = 0; MYFLT pit = 0, pos = 0, dur = 0, dev = 0; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); dens = PyFloat_AS_DOUBLE(self->dens); if (dens < 0.0) dens = 0.0; inc = dens * self->oneOnSr * self->devFactor; for (i=0; ibufsize*self->chnls; i++) { self->buffer_streams[i] = 0.0; } for (i=0; ibufsize; i++) { self->timer += inc; if (self->timer >= 1.0) { self->timer -= 1.0; flag = 1; } /* need to start a new grain */ if (flag) { for (j=0; jflags[j] == 0) { self->flags[j] = 1; if (j >= self->num) self->num = j + 1; if (self->modebuffer[1] == 0) pit = PyFloat_AS_DOUBLE(self->pitch); else pit = Stream_getData((Stream *)self->pitch_stream)[i]; if (self->modebuffer[2] == 0) pos = PyFloat_AS_DOUBLE(self->pos); else pos = Stream_getData((Stream *)self->pos_stream)[i]; if (self->modebuffer[3] == 0) dur = PyFloat_AS_DOUBLE(self->dur); else dur = Stream_getData((Stream *)self->dur_stream)[i]; if (self->modebuffer[4] == 0) dev = PyFloat_AS_DOUBLE(self->dev); else dev = Stream_getData((Stream *)self->dev_stream)[i]; if (pit < 0.0) pit = -pit; if (pos < 0.0) pos = 0.0; else if (pos >= size) pos = (MYFLT)size; if (dur < 0.0001) dur = 0.0001; if (dev < 0.0) dev = 0.0; else if (dev > 1.0) dev = 1.0; self->gpos[j] = pos; self->glen[j] = dur * self->sr * pit * self->srScale; if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0) self->flags[j] = 0; self->phase[j] = 0.0; self->inc[j] = 1.0 / (dur * self->sr); self->devFactor = (rand() / (MYFLT)RAND_MAX * 2.0 - 1.0) * dev + 1.0; break; } } } /* compute active grains */ for (j=0; jnum; j++) { if (self->flags[j]) { phase = self->phase[j]; /* compute envelope */ index = phase * envsize; ipart = (int)index; amp = envlist[ipart] + (envlist[ipart+1] - envlist[ipart]) * (index - ipart); /* compute sampling */ index = phase * self->glen[j] + self->gpos[j]; ipart = (int)index; val = (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart)) * amp; self->buffer_streams[i] += val; phase += self->inc[j]; if (phase >= 1.0) self->flags[j] = 0; else self->phase[j] = phase; } } flag = 0; } } static void MainParticle_transform_mono_a(MainParticle *self) { MYFLT dens, index, amp, phase, val; int i, j, ipart, flag = 0; MYFLT pit = 0, pos = 0, dur = 0, dev = 0; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); MYFLT *density = Stream_getData((Stream *)self->dens_stream); for (i=0; ibufsize*self->chnls; i++) { self->buffer_streams[i] = 0.0; } for (i=0; ibufsize; i++) { if (density[i] < 0.0) dens = 0.0; else dens = density[i]; self->timer += dens * self->oneOnSr * self->devFactor; if (self->timer >= 1.0) { self->timer -= 1.0; flag = 1; } /* need to start a new grain */ if (flag) { for (j=0; jflags[j] == 0) { self->flags[j] = 1; if (j >= self->num) self->num = j + 1; if (self->modebuffer[1] == 0) pit = PyFloat_AS_DOUBLE(self->pitch); else pit = Stream_getData((Stream *)self->pitch_stream)[i]; if (self->modebuffer[2] == 0) pos = PyFloat_AS_DOUBLE(self->pos); else pos = Stream_getData((Stream *)self->pos_stream)[i]; if (self->modebuffer[3] == 0) dur = PyFloat_AS_DOUBLE(self->dur); else dur = Stream_getData((Stream *)self->dur_stream)[i]; if (self->modebuffer[4] == 0) dev = PyFloat_AS_DOUBLE(self->dev); else dev = Stream_getData((Stream *)self->dev_stream)[i]; if (pit < 0.0) pit = -pit; if (pos < 0.0) pos = 0.0; else if (pos >= size) pos = (MYFLT)size; if (dur < 0.0001) dur = 0.0001; if (dev < 0.0) dev = 0.0; else if (dev > 1.0) dev = 1.0; self->gpos[j] = pos; self->glen[j] = dur * self->sr * pit * self->srScale; if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0) self->flags[j] = 0; self->phase[j] = 0.0; self->inc[j] = 1.0 / (dur * self->sr); self->devFactor = (rand() / (MYFLT)RAND_MAX * 2.0 - 1.0) * dev + 1.0; break; } } } /* compute active grains */ for (j=0; jnum; j++) { if (self->flags[j]) { phase = self->phase[j]; /* compute envelope */ index = phase * envsize; ipart = (int)index; amp = envlist[ipart] + (envlist[ipart+1] - envlist[ipart]) * (index - ipart); /* compute sampling */ index = phase * self->glen[j] + self->gpos[j]; ipart = (int)index; val = (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart)) * amp; self->buffer_streams[i] += val; phase += self->inc[j]; if (phase >= 1.0) self->flags[j] = 0; else self->phase[j] = phase; } } flag = 0; } } static void MainParticle_transform_i(MainParticle *self) { MYFLT dens, inc, index, amp, phase, val, min = 0; int i, j, l, l1, ipart, flag = 0; MYFLT pit = 0, pos = 0, dur = 0, dev = 0, pan = 0; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); dens = PyFloat_AS_DOUBLE(self->dens); if (dens < 0.0) dens = 0.0; inc = dens * self->oneOnSr * self->devFactor; for (i=0; ibufsize*self->chnls; i++) { self->buffer_streams[i] = 0.0; } for (i=0; ibufsize; i++) { self->timer += inc; if (self->timer >= 1.0) { self->timer -= 1.0; flag = 1; } /* need to start a new grain */ if (flag) { for (j=0; jflags[j] == 0) { self->flags[j] = 1; if (j >= self->num) self->num = j + 1; if (self->modebuffer[1] == 0) pit = PyFloat_AS_DOUBLE(self->pitch); else pit = Stream_getData((Stream *)self->pitch_stream)[i]; if (self->modebuffer[2] == 0) pos = PyFloat_AS_DOUBLE(self->pos); else pos = Stream_getData((Stream *)self->pos_stream)[i]; if (self->modebuffer[3] == 0) dur = PyFloat_AS_DOUBLE(self->dur); else dur = Stream_getData((Stream *)self->dur_stream)[i]; if (self->modebuffer[4] == 0) dev = PyFloat_AS_DOUBLE(self->dev); else dev = Stream_getData((Stream *)self->dev_stream)[i]; if (self->modebuffer[5] == 0) pan = PyFloat_AS_DOUBLE(self->pan); else pan = Stream_getData((Stream *)self->pan_stream)[i]; if (pit < 0.0) pit = -pit; if (pos < 0.0) pos = 0.0; else if (pos >= size) pos = (MYFLT)size; if (dur < 0.0001) dur = 0.0001; if (dev < 0.0) dev = 0.0; else if (dev > 1.0) dev = 1.0; if (pan < 0.0) pan = 0.0; else if (pan > 1.0) pan = 1.0; self->gpos[j] = pos; self->glen[j] = dur * self->sr * pit * self->srScale; if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0) self->flags[j] = 0; self->phase[j] = 0.0; self->inc[j] = 1.0 / (dur * self->sr); self->devFactor = (rand() / (MYFLT)RAND_MAX * 2.0 - 1.0) * dev + 1.0; if (self->chnls == 2) { self->k1[j] = 0; self->k2[j] = self->bufsize; self->amp1[j] = MYSQRT(1.0 - pan); self->amp2[j] = MYSQRT(pan); } else { self->amp1[j] = MYSQRT(1.0 - pan); self->amp2[j] = MYSQRT(pan); min = 0; self->k1[j] = 0; self->k2[j] = self->bufsize; for (l=self->chnls; l>0; l--) { l1 = l - 1; min = l1 / (MYFLT)self->chnls; if (pan > min) { self->k1[j] = l1 * self->bufsize; if (l == self->chnls) self->k2[j] = 0; else self->k2[j] = l * self->bufsize; break; } } } break; } } } /* compute active grains */ for (j=0; jnum; j++) { if (self->flags[j]) { phase = self->phase[j]; /* compute envelope */ index = phase * envsize; ipart = (int)index; amp = envlist[ipart] + (envlist[ipart+1] - envlist[ipart]) * (index - ipart); /* compute sampling */ index = phase * self->glen[j] + self->gpos[j]; ipart = (int)index; val = (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart)) * amp; self->buffer_streams[i+self->k1[j]] += val * self->amp1[j]; self->buffer_streams[i+self->k2[j]] += val * self->amp2[j]; phase += self->inc[j]; if (phase >= 1.0) self->flags[j] = 0; else self->phase[j] = phase; } } flag = 0; } } static void MainParticle_transform_a(MainParticle *self) { MYFLT dens, index, amp, phase, val, min = 0; int i, j, l, l1, ipart, flag = 0; MYFLT pit = 0, pos = 0, dur = 0, dev = 0, pan = 0; MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); MYFLT *envlist = TableStream_getData(self->env); int envsize = TableStream_getSize(self->env); MYFLT *density = Stream_getData((Stream *)self->dens_stream); for (i=0; ibufsize*self->chnls; i++) { self->buffer_streams[i] = 0.0; } for (i=0; ibufsize; i++) { if (density[i] < 0.0) dens = 0.0; else dens = density[i]; self->timer += dens * self->oneOnSr * self->devFactor; if (self->timer >= 1.0) { self->timer -= 1.0; flag = 1; } /* need to start a new grain */ if (flag) { for (j=0; jflags[j] == 0) { self->flags[j] = 1; if (j >= self->num) self->num = j + 1; if (self->modebuffer[1] == 0) pit = PyFloat_AS_DOUBLE(self->pitch); else pit = Stream_getData((Stream *)self->pitch_stream)[i]; if (self->modebuffer[2] == 0) pos = PyFloat_AS_DOUBLE(self->pos); else pos = Stream_getData((Stream *)self->pos_stream)[i]; if (self->modebuffer[3] == 0) dur = PyFloat_AS_DOUBLE(self->dur); else dur = Stream_getData((Stream *)self->dur_stream)[i]; if (self->modebuffer[4] == 0) dev = PyFloat_AS_DOUBLE(self->dev); else dev = Stream_getData((Stream *)self->dev_stream)[i]; if (self->modebuffer[5] == 0) pan = PyFloat_AS_DOUBLE(self->pan); else pan = Stream_getData((Stream *)self->pan_stream)[i]; if (pit < 0.0) pit = -pit; if (pos < 0.0) pos = 0.0; else if (pos >= size) pos = (MYFLT)size; if (dur < 0.0001) dur = 0.0001; if (dev < 0.0) dev = 0.0; else if (dev > 1.0) dev = 1.0; if (pan < 0.0) pan = 0.0; else if (pan > 1.0) pan = 1.0; self->gpos[j] = pos; self->glen[j] = dur * self->sr * pit * self->srScale; if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0) self->flags[j] = 0; self->phase[j] = 0.0; self->inc[j] = 1.0 / (dur * self->sr); self->devFactor = (rand() / (MYFLT)RAND_MAX * 2.0 - 1.0) * dev + 1.0; if (self->chnls == 2) { self->k1[j] = 0; self->k2[j] = self->bufsize; self->amp1[j] = MYSQRT(1.0 - pan); self->amp2[j] = MYSQRT(pan); } else { self->amp1[j] = MYSQRT(1.0 - pan); self->amp2[j] = MYSQRT(pan); min = 0; self->k1[j] = 0; self->k2[j] = self->bufsize; for (l=self->chnls; l>0; l--) { l1 = l - 1; min = l1 / (MYFLT)self->chnls; if (pan > min) { self->k1[j] = l1 * self->bufsize; if (l == self->chnls) self->k2[j] = 0; else self->k2[j] = l * self->bufsize; break; } } } break; } } } /* compute active grains */ for (j=0; jnum; j++) { if (self->flags[j]) { phase = self->phase[j]; /* compute envelope */ index = phase * envsize; ipart = (int)index; amp = envlist[ipart] + (envlist[ipart+1] - envlist[ipart]) * (index - ipart); /* compute sampling */ index = phase * self->glen[j] + self->gpos[j]; ipart = (int)index; val = (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart)) * amp; self->buffer_streams[i+self->k1[j]] += val * self->amp1[j]; self->buffer_streams[i+self->k2[j]] += val * self->amp2[j]; phase += self->inc[j]; if (phase >= 1.0) self->flags[j] = 0; else self->phase[j] = phase; } } flag = 0; } } static void MainParticle_setProcMode(MainParticle *self) { int procmode = self->modebuffer[0]; switch (procmode) { case 0: if (self->chnls == 1) self->proc_func_ptr = MainParticle_transform_mono_i; else self->proc_func_ptr = MainParticle_transform_i; break; case 1: if (self->chnls == 1) self->proc_func_ptr = MainParticle_transform_mono_a; else self->proc_func_ptr = MainParticle_transform_a; break; } } static void MainParticle_compute_next_data_frame(MainParticle *self) { (*self->proc_func_ptr)(self); } static int MainParticle_traverse(MainParticle *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->env); Py_VISIT(self->dens); Py_VISIT(self->dens_stream); Py_VISIT(self->pitch); Py_VISIT(self->pitch_stream); Py_VISIT(self->pos); Py_VISIT(self->pos_stream); Py_VISIT(self->dur); Py_VISIT(self->dur_stream); Py_VISIT(self->dev); Py_VISIT(self->dev_stream); Py_VISIT(self->pan); Py_VISIT(self->pan_stream); return 0; } static int MainParticle_clear(MainParticle *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->env); Py_CLEAR(self->dens); Py_CLEAR(self->dens_stream); Py_CLEAR(self->pitch); Py_CLEAR(self->pitch_stream); Py_CLEAR(self->pos); Py_CLEAR(self->pos_stream); Py_CLEAR(self->dur); Py_CLEAR(self->dur_stream); Py_CLEAR(self->dev); Py_CLEAR(self->dev_stream); Py_CLEAR(self->pan); Py_CLEAR(self->pan_stream); return 0; } static void MainParticle_dealloc(MainParticle* self) { pyo_DEALLOC free(self->gpos); free(self->glen); free(self->inc); free(self->flags); free(self->k1); free(self->k2); free(self->phase); free(self->amp1); free(self->amp2); free(self->buffer_streams); MainParticle_clear(self); self->ob_type->tp_free((PyObject*)self); } MYFLT * MainParticle_getSamplesBuffer(MainParticle *self) { return (MYFLT *)self->buffer_streams; } static PyObject * MainParticle_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *tabletmp, *envtmp, *denstmp=NULL, *pitchtmp=NULL, *postmp=NULL, *durtmp=NULL, *devtmp=NULL, *pantmp=NULL; MainParticle *self; self = (MainParticle *)type->tp_alloc(type, 0); self->dens = PyFloat_FromDouble(50); self->pitch = PyFloat_FromDouble(1); self->pos = PyFloat_FromDouble(0.0); self->dur = PyFloat_FromDouble(0.1); self->dev = PyFloat_FromDouble(0); self->pan = PyFloat_FromDouble(0.5); self->timer = self->devFactor = 1.0; self->srScale = 1.0; self->num = 0; self->chnls = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->modebuffer[5] = 0; INIT_OBJECT_COMMON self->oneOnSr = 1.0 / self->sr; self->srOnRandMax = self->sr / (MYFLT)RAND_MAX; Stream_setFunctionPtr(self->stream, MainParticle_compute_next_data_frame); self->mode_func_ptr = MainParticle_setProcMode; static char *kwlist[] = {"table", "env", "dens", "pitch", "pos", "dur", "dev", "pan", "chnls", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOOOOOi", kwlist, &tabletmp, &envtmp, &denstmp, &pitchtmp, &postmp, &durtmp, &devtmp, &pantmp, &self->chnls)) Py_RETURN_NONE; if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of MainParticle must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); self->srScale = TableStream_getSamplingRate(self->table) / self->sr; if ( PyObject_HasAttrString((PyObject *)envtmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"env\" argument of MainParticle must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->env); self->env = PyObject_CallMethod((PyObject *)envtmp, "getTableStream", ""); if (denstmp) { PyObject_CallMethod((PyObject *)self, "setDens", "O", denstmp); } if (pitchtmp) { PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp); } if (postmp) { PyObject_CallMethod((PyObject *)self, "setPos", "O", postmp); } if (durtmp) { PyObject_CallMethod((PyObject *)self, "setDur", "O", durtmp); } if (devtmp) { PyObject_CallMethod((PyObject *)self, "setDev", "O", devtmp); } if (pantmp) { PyObject_CallMethod((PyObject *)self, "setPan", "O", pantmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (self->chnls < 1) self->chnls = 1; self->gpos = (MYFLT *)realloc(self->gpos, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT)); self->glen = (MYFLT *)realloc(self->glen, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT)); self->inc = (MYFLT *)realloc(self->inc, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT)); self->phase = (MYFLT *)realloc(self->phase, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT)); self->amp1 = (MYFLT *)realloc(self->amp1, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT)); self->amp2 = (MYFLT *)realloc(self->amp2, MAINPARTICLE_MAX_GRAINS * sizeof(MYFLT)); self->flags = (int *)realloc(self->flags, MAINPARTICLE_MAX_GRAINS * sizeof(int)); self->k1 = (int *)realloc(self->k1, MAINPARTICLE_MAX_GRAINS * sizeof(int)); self->k2 = (int *)realloc(self->k2, MAINPARTICLE_MAX_GRAINS * sizeof(int)); for (i=0; igpos[i] = self->glen[i] = self->inc[i] = self->phase[i] = self->amp1[i] = self->amp2[i] = 0.0; self->flags[i] = self->k1[i] = self->k2[i] = 0; } self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->bufsize * self->chnls * sizeof(MYFLT)); for (i=0; ibufsize*self->chnls; i++) { self->buffer_streams[i] = 0.0; } Server_generateSeed((Server *)self->server, MAINPARTICLE_ID); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * MainParticle_getServer(MainParticle* self) { GET_SERVER }; static PyObject * MainParticle_getStream(MainParticle* self) { GET_STREAM }; static PyObject * MainParticle_play(MainParticle *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * MainParticle_stop(MainParticle *self) { STOP }; static PyObject * MainParticle_setDens(MainParticle *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->dens); if (isNumber == 1) { self->dens = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->dens = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->dens, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->dens_stream); self->dens_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * MainParticle_setPitch(MainParticle *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pitch); if (isNumber == 1) { self->pitch = PyNumber_Float(tmp); self->modebuffer[1] = 0; } else { self->pitch = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pitch, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pitch_stream); self->pitch_stream = (Stream *)streamtmp; self->modebuffer[1] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * MainParticle_setPos(MainParticle *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pos); if (isNumber == 1) { self->pos = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->pos = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pos, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pos_stream); self->pos_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * MainParticle_setDur(MainParticle *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->dur); if (isNumber == 1) { self->dur = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->dur = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->dur, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->dur_stream); self->dur_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * MainParticle_setDev(MainParticle *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->dev); if (isNumber == 1) { self->dev = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->dev = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->dev, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->dev_stream); self->dev_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * MainParticle_setPan(MainParticle *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pan); if (isNumber == 1) { self->pan = PyNumber_Float(tmp); self->modebuffer[5] = 0; } else { self->pan = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pan, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pan_stream); self->pan_stream = (Stream *)streamtmp; self->modebuffer[5] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * MainParticle_getTable(MainParticle* self) { Py_INCREF(self->table); return self->table; }; static PyObject * MainParticle_setTable(MainParticle *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); self->srScale = TableStream_getSamplingRate(self->table) / self->sr; Py_INCREF(Py_None); return Py_None; } static PyObject * MainParticle_getEnv(MainParticle* self) { Py_INCREF(self->env); return self->env; }; static PyObject * MainParticle_setEnv(MainParticle *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->env); self->env = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyMemberDef MainParticle_members[] = { {"server", T_OBJECT_EX, offsetof(MainParticle, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(MainParticle, stream), 0, "Stream object."}, {"table", T_OBJECT_EX, offsetof(MainParticle, table), 0, "Sound table."}, {"env", T_OBJECT_EX, offsetof(MainParticle, env), 0, "Envelope table."}, {"dens", T_OBJECT_EX, offsetof(MainParticle, dens), 0, "Density of grains per second."}, {"pitch", T_OBJECT_EX, offsetof(MainParticle, pitch), 0, "Speed of the reading pointer."}, {"pos", T_OBJECT_EX, offsetof(MainParticle, pos), 0, "Position in the sound table."}, {"dur", T_OBJECT_EX, offsetof(MainParticle, dur), 0, "Duration of each grains."}, {"dev", T_OBJECT_EX, offsetof(MainParticle, dev), 0, "Grain start point deviation factor."}, {"pan", T_OBJECT_EX, offsetof(MainParticle, pan), 0, "Grain panning factor."}, {NULL} /* Sentinel */ }; static PyMethodDef MainParticle_methods[] = { {"getTable", (PyCFunction)MainParticle_getTable, METH_NOARGS, "Returns sound table object."}, {"setTable", (PyCFunction)MainParticle_setTable, METH_O, "Sets sound table."}, {"getEnv", (PyCFunction)MainParticle_getEnv, METH_NOARGS, "Returns envelope table object."}, {"setEnv", (PyCFunction)MainParticle_setEnv, METH_O, "Sets envelope table."}, {"getServer", (PyCFunction)MainParticle_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)MainParticle_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)MainParticle_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)MainParticle_stop, METH_NOARGS, "Stops computing."}, {"setDens", (PyCFunction)MainParticle_setDens, METH_O, "Sets the density of grains per second."}, {"setPitch", (PyCFunction)MainParticle_setPitch, METH_O, "Sets global pitch factor."}, {"setPos", (PyCFunction)MainParticle_setPos, METH_O, "Sets position in the sound table."}, {"setDur", (PyCFunction)MainParticle_setDur, METH_O, "Sets the grain duration."}, {"setDev", (PyCFunction)MainParticle_setDev, METH_O, "Sets grain start point deviation factor."}, {"setPan", (PyCFunction)MainParticle_setPan, METH_O, "Sets grain panning factor."}, {NULL} /* Sentinel */ }; PyTypeObject MainParticleType = { PyObject_HEAD_INIT(NULL) 0, /*ob_pitch*/ "_pyo.MainParticle_base", /*tp_name*/ sizeof(MainParticle), /*tp_basicpitch*/ 0, /*tp_itempitch*/ (destructor)MainParticle_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "MainParticle objects. Accumulation of multiples grains of sound.", /* tp_doc */ (traverseproc)MainParticle_traverse, /* tp_traverse */ (inquiry)MainParticle_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ MainParticle_methods, /* tp_methods */ MainParticle_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MainParticle_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD MainParticle *mainSplitter; int modebuffer[2]; int chnl; // panning order } Particle; static void Particle_postprocessing_ii(Particle *self) { POST_PROCESSING_II }; static void Particle_postprocessing_ai(Particle *self) { POST_PROCESSING_AI }; static void Particle_postprocessing_ia(Particle *self) { POST_PROCESSING_IA }; static void Particle_postprocessing_aa(Particle *self) { POST_PROCESSING_AA }; static void Particle_postprocessing_ireva(Particle *self) { POST_PROCESSING_IREVA }; static void Particle_postprocessing_areva(Particle *self) { POST_PROCESSING_AREVA }; static void Particle_postprocessing_revai(Particle *self) { POST_PROCESSING_REVAI }; static void Particle_postprocessing_revaa(Particle *self) { POST_PROCESSING_REVAA }; static void Particle_postprocessing_revareva(Particle *self) { POST_PROCESSING_REVAREVA }; static void Particle_setProcMode(Particle *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Particle_postprocessing_ii; break; case 1: self->muladd_func_ptr = Particle_postprocessing_ai; break; case 2: self->muladd_func_ptr = Particle_postprocessing_revai; break; case 10: self->muladd_func_ptr = Particle_postprocessing_ia; break; case 11: self->muladd_func_ptr = Particle_postprocessing_aa; break; case 12: self->muladd_func_ptr = Particle_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Particle_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Particle_postprocessing_areva; break; case 22: self->muladd_func_ptr = Particle_postprocessing_revareva; break; } } static void Particle_compute_next_data_frame(Particle *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = MainParticle_getSamplesBuffer((MainParticle *)self->mainSplitter); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int Particle_traverse(Particle *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainSplitter); return 0; } static int Particle_clear(Particle *self) { pyo_CLEAR Py_CLEAR(self->mainSplitter); return 0; } static void Particle_dealloc(Particle* self) { pyo_DEALLOC Particle_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Particle_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; Particle *self; self = (Particle *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Particle_compute_next_data_frame); self->mode_func_ptr = Particle_setProcMode; static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainSplitter); Py_INCREF(maintmp); self->mainSplitter = (MainParticle *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Particle_getServer(Particle* self) { GET_SERVER }; static PyObject * Particle_getStream(Particle* self) { GET_STREAM }; static PyObject * Particle_setMul(Particle *self, PyObject *arg) { SET_MUL }; static PyObject * Particle_setAdd(Particle *self, PyObject *arg) { SET_ADD }; static PyObject * Particle_setSub(Particle *self, PyObject *arg) { SET_SUB }; static PyObject * Particle_setDiv(Particle *self, PyObject *arg) { SET_DIV }; static PyObject * Particle_play(Particle *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Particle_out(Particle *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Particle_stop(Particle *self) { STOP }; static PyObject * Particle_multiply(Particle *self, PyObject *arg) { MULTIPLY }; static PyObject * Particle_inplace_multiply(Particle *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Particle_add(Particle *self, PyObject *arg) { ADD }; static PyObject * Particle_inplace_add(Particle *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Particle_sub(Particle *self, PyObject *arg) { SUB }; static PyObject * Particle_inplace_sub(Particle *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Particle_div(Particle *self, PyObject *arg) { DIV }; static PyObject * Particle_inplace_div(Particle *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Particle_members[] = { {"server", T_OBJECT_EX, offsetof(Particle, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Particle, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Particle, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Particle, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Particle_methods[] = { {"getServer", (PyCFunction)Particle_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Particle_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Particle_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Particle_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Particle_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Particle_setMul, METH_O, "Sets Particle mul factor."}, {"setAdd", (PyCFunction)Particle_setAdd, METH_O, "Sets Particle add factor."}, {"setSub", (PyCFunction)Particle_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Particle_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Particle_as_number = { (binaryfunc)Particle_add, /*nb_add*/ (binaryfunc)Particle_sub, /*nb_subtract*/ (binaryfunc)Particle_multiply, /*nb_multiply*/ (binaryfunc)Particle_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Particle_inplace_add, /*inplace_add*/ (binaryfunc)Particle_inplace_sub, /*inplace_subtract*/ (binaryfunc)Particle_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Particle_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ParticleType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Particle_base", /*tp_name*/ sizeof(Particle), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Particle_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Particle_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Particle objects. Reads one band from a MainParticle object.", /* tp_doc */ (traverseproc)Particle_traverse, /* tp_traverse */ (inquiry)Particle_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Particle_methods, /* tp_methods */ Particle_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Particle_new, /* tp_new */ };pyo/src/objects/sigmodule.c0000644000175000017500000011245112652732202015236 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD PyObject *value; Stream *value_stream; int modebuffer[3]; } Sig; static void Sig_postprocessing_ii(Sig *self) { POST_PROCESSING_II }; static void Sig_postprocessing_ai(Sig *self) { POST_PROCESSING_AI }; static void Sig_postprocessing_ia(Sig *self) { POST_PROCESSING_IA }; static void Sig_postprocessing_aa(Sig *self) { POST_PROCESSING_AA }; static void Sig_postprocessing_ireva(Sig *self) { POST_PROCESSING_IREVA }; static void Sig_postprocessing_areva(Sig *self) { POST_PROCESSING_AREVA }; static void Sig_postprocessing_revai(Sig *self) { POST_PROCESSING_REVAI }; static void Sig_postprocessing_revaa(Sig *self) { POST_PROCESSING_REVAA }; static void Sig_postprocessing_revareva(Sig *self) { POST_PROCESSING_REVAREVA }; static void Sig_setProcMode(Sig *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Sig_postprocessing_ii; break; case 1: self->muladd_func_ptr = Sig_postprocessing_ai; break; case 2: self->muladd_func_ptr = Sig_postprocessing_revai; break; case 10: self->muladd_func_ptr = Sig_postprocessing_ia; break; case 11: self->muladd_func_ptr = Sig_postprocessing_aa; break; case 12: self->muladd_func_ptr = Sig_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Sig_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Sig_postprocessing_areva; break; case 22: self->muladd_func_ptr = Sig_postprocessing_revareva; break; } } static void Sig_compute_next_data_frame(Sig *self) { int i; if (self->modebuffer[2] == 0) { MYFLT val = PyFloat_AS_DOUBLE(self->value); for (i=0; ibufsize; i++) { self->data[i] = val; } } else { MYFLT *vals = Stream_getData((Stream *)self->value_stream); for (i=0; ibufsize; i++) { self->data[i] = vals[i]; } } (*self->muladd_func_ptr)(self); } static int Sig_traverse(Sig *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->value); Py_VISIT(self->value_stream); return 0; } static int Sig_clear(Sig *self) { pyo_CLEAR Py_CLEAR(self->value); Py_CLEAR(self->value_stream); return 0; } static void Sig_dealloc(Sig* self) { pyo_DEALLOC Sig_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Sig_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *valuetmp=NULL, *multmp=NULL, *addtmp=NULL; Sig *self; self = (Sig *)type->tp_alloc(type, 0); self->value = PyFloat_FromDouble(0.0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Sig_compute_next_data_frame); self->mode_func_ptr = Sig_setProcMode; static char *kwlist[] = {"value", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &valuetmp, &multmp, &addtmp)) Py_RETURN_NONE; if (valuetmp) { PyObject_CallMethod((PyObject *)self, "setValue", "O", valuetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); Sig_compute_next_data_frame((Sig *)self); return (PyObject *)self; } static PyObject * Sig_setValue(Sig *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->value); if (isNumber == 1) { self->value = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->value = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->value, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->value_stream); self->value_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * Sig_getServer(Sig* self) { GET_SERVER }; static PyObject * Sig_getStream(Sig* self) { GET_STREAM }; static PyObject * Sig_setMul(Sig *self, PyObject *arg) { SET_MUL }; static PyObject * Sig_setAdd(Sig *self, PyObject *arg) { SET_ADD }; static PyObject * Sig_setSub(Sig *self, PyObject *arg) { SET_SUB }; static PyObject * Sig_setDiv(Sig *self, PyObject *arg) { SET_DIV }; static PyObject * Sig_play(Sig *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Sig_out(Sig *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Sig_stop(Sig *self) { STOP }; static PyObject * Sig_multiply(Sig *self, PyObject *arg) { MULTIPLY }; static PyObject * Sig_inplace_multiply(Sig *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Sig_add(Sig *self, PyObject *arg) { ADD }; static PyObject * Sig_inplace_add(Sig *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Sig_sub(Sig *self, PyObject *arg) { SUB }; static PyObject * Sig_inplace_sub(Sig *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Sig_div(Sig *self, PyObject *arg) { DIV }; static PyObject * Sig_inplace_div(Sig *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Sig_members[] = { {"server", T_OBJECT_EX, offsetof(Sig, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Sig, stream), 0, "Stream object."}, {"value", T_OBJECT_EX, offsetof(Sig, value), 0, "Target value."}, {"mul", T_OBJECT_EX, offsetof(Sig, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Sig, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Sig_methods[] = { {"getServer", (PyCFunction)Sig_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Sig_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Sig_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Sig_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Sig_stop, METH_NOARGS, "Stops computing."}, {"setValue", (PyCFunction)Sig_setValue, METH_O, "Sets Sig value."}, {"setMul", (PyCFunction)Sig_setMul, METH_O, "Sets Sig mul factor."}, {"setAdd", (PyCFunction)Sig_setAdd, METH_O, "Sets Sig add factor."}, {"setSub", (PyCFunction)Sig_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Sig_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Sig_as_number = { (binaryfunc)Sig_add, /*nb_add*/ (binaryfunc)Sig_sub, /*nb_subtract*/ (binaryfunc)Sig_multiply, /*nb_multiply*/ (binaryfunc)Sig_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Sig_inplace_add, /*inplace_add*/ (binaryfunc)Sig_inplace_sub, /*inplace_subtract*/ (binaryfunc)Sig_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Sig_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SigType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Sig_base", /*tp_name*/ sizeof(Sig), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Sig_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Sig_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Sig objects. Converts number into a signal stream.", /* tp_doc */ (traverseproc)Sig_traverse, /* tp_traverse */ (inquiry)Sig_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Sig_methods, /* tp_methods */ Sig_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Sig_new, /* tp_new */ }; /***************************/ /* SigTo - Sig + ramp time */ /***************************/ typedef struct { pyo_audio_HEAD PyObject *value; Stream *value_stream; MYFLT lastValue; MYFLT currentValue; MYFLT time; long timeStep; MYFLT stepVal; long timeCount; int modebuffer[3]; } SigTo; static void SigTo_generates_i(SigTo *self) { int i; MYFLT value; if (self->modebuffer[2] == 0) { value = PyFloat_AS_DOUBLE(self->value); if (value != self->lastValue) { self->timeCount = 0; self->timeStep = (long)(self->time * self->sr); self->stepVal = (value - self->currentValue) / self->timeStep; self->lastValue = value; } if (self->timeStep <= 0) { for (i=0; ibufsize; i++) self->data[i] = self->currentValue = self->lastValue = value; } else { for (i=0; ibufsize; i++) { if (self->timeCount == (self->timeStep - 1)) { self->currentValue = value; self->timeCount++; } else if (self->timeCount < self->timeStep) { self->currentValue += self->stepVal; self->timeCount++; } self->data[i] = self->currentValue; } } } else { MYFLT *vals = Stream_getData((Stream *)self->value_stream); if (self->timeStep <= 0) { for (i=0; ibufsize; i++) { value = vals[i]; self->data[i] = self->currentValue = self->lastValue = value; } } else { for (i=0; ibufsize; i++) { value = vals[i]; if (value != self->lastValue) { self->timeCount = 0; self->timeStep = (long)(self->time * self->sr); self->stepVal = (value - self->currentValue) / self->timeStep; self->lastValue = value; } if (self->timeCount == (self->timeStep - 1)) { self->currentValue = value; self->timeCount++; } else if (self->timeCount < self->timeStep) { self->currentValue += self->stepVal; self->timeCount++; } self->data[i] = self->currentValue; } } } } static void SigTo_postprocessing_ii(SigTo *self) { POST_PROCESSING_II }; static void SigTo_postprocessing_ai(SigTo *self) { POST_PROCESSING_AI }; static void SigTo_postprocessing_ia(SigTo *self) { POST_PROCESSING_IA }; static void SigTo_postprocessing_aa(SigTo *self) { POST_PROCESSING_AA }; static void SigTo_postprocessing_ireva(SigTo *self) { POST_PROCESSING_IREVA }; static void SigTo_postprocessing_areva(SigTo *self) { POST_PROCESSING_AREVA }; static void SigTo_postprocessing_revai(SigTo *self) { POST_PROCESSING_REVAI }; static void SigTo_postprocessing_revaa(SigTo *self) { POST_PROCESSING_REVAA }; static void SigTo_postprocessing_revareva(SigTo *self) { POST_PROCESSING_REVAREVA }; static void SigTo_setProcMode(SigTo *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = SigTo_generates_i; switch (muladdmode) { case 0: self->muladd_func_ptr = SigTo_postprocessing_ii; break; case 1: self->muladd_func_ptr = SigTo_postprocessing_ai; break; case 2: self->muladd_func_ptr = SigTo_postprocessing_revai; break; case 10: self->muladd_func_ptr = SigTo_postprocessing_ia; break; case 11: self->muladd_func_ptr = SigTo_postprocessing_aa; break; case 12: self->muladd_func_ptr = SigTo_postprocessing_revaa; break; case 20: self->muladd_func_ptr = SigTo_postprocessing_ireva; break; case 21: self->muladd_func_ptr = SigTo_postprocessing_areva; break; case 22: self->muladd_func_ptr = SigTo_postprocessing_revareva; break; } } static void SigTo_compute_next_data_frame(SigTo *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int SigTo_traverse(SigTo *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->value); Py_VISIT(self->value_stream); return 0; } static int SigTo_clear(SigTo *self) { pyo_CLEAR Py_CLEAR(self->value); Py_CLEAR(self->value_stream); return 0; } static void SigTo_dealloc(SigTo* self) { pyo_DEALLOC SigTo_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SigTo_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT inittmp = 0.0; PyObject *valuetmp=NULL, *timetmp=NULL, *multmp=NULL, *addtmp=NULL; SigTo *self; self = (SigTo *)type->tp_alloc(type, 0); self->value = PyFloat_FromDouble(0.0); self->time = 0.025; self->timeCount = 0; self->stepVal = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, SigTo_compute_next_data_frame); self->mode_func_ptr = SigTo_setProcMode; static char *kwlist[] = {"value", "time", "init", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OFOO, kwlist, &valuetmp, &timetmp, &inittmp, &multmp, &addtmp)) Py_RETURN_NONE; if (valuetmp) { PyObject_CallMethod((PyObject *)self, "setValue", "O", valuetmp); } if (timetmp) { PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->lastValue = self->currentValue = inittmp; self->timeStep = (long)(self->time * self->sr); (*self->mode_func_ptr)(self); for(i=0; ibufsize; i++) { self->data[i] = self->currentValue; } return (PyObject *)self; } static PyObject * SigTo_setValue(SigTo *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->value); if (isNumber == 1) { self->value = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->value = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->value, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->value_stream); self->value_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * SigTo_setTime(SigTo *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); if (isNumber == 1) { self->time = PyFloat_AsDouble(tmp); } Py_INCREF(Py_None); return Py_None; } static PyObject * SigTo_getServer(SigTo* self) { GET_SERVER }; static PyObject * SigTo_getStream(SigTo* self) { GET_STREAM }; static PyObject * SigTo_setMul(SigTo *self, PyObject *arg) { SET_MUL }; static PyObject * SigTo_setAdd(SigTo *self, PyObject *arg) { SET_ADD }; static PyObject * SigTo_setSub(SigTo *self, PyObject *arg) { SET_SUB }; static PyObject * SigTo_setDiv(SigTo *self, PyObject *arg) { SET_DIV }; static PyObject * SigTo_play(SigTo *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SigTo_stop(SigTo *self) { STOP }; static PyObject * SigTo_multiply(SigTo *self, PyObject *arg) { MULTIPLY }; static PyObject * SigTo_inplace_multiply(SigTo *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * SigTo_add(SigTo *self, PyObject *arg) { ADD }; static PyObject * SigTo_inplace_add(SigTo *self, PyObject *arg) { INPLACE_ADD }; static PyObject * SigTo_sub(SigTo *self, PyObject *arg) { SUB }; static PyObject * SigTo_inplace_sub(SigTo *self, PyObject *arg) { INPLACE_SUB }; static PyObject * SigTo_div(SigTo *self, PyObject *arg) { DIV }; static PyObject * SigTo_inplace_div(SigTo *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef SigTo_members[] = { {"server", T_OBJECT_EX, offsetof(SigTo, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SigTo, stream), 0, "Stream object."}, {"value", T_OBJECT_EX, offsetof(SigTo, value), 0, "Target value."}, {"mul", T_OBJECT_EX, offsetof(SigTo, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(SigTo, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef SigTo_methods[] = { {"getServer", (PyCFunction)SigTo_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SigTo_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SigTo_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)SigTo_stop, METH_NOARGS, "Stops computing."}, {"setValue", (PyCFunction)SigTo_setValue, METH_O, "Sets SigTo value."}, {"setTime", (PyCFunction)SigTo_setTime, METH_O, "Sets ramp time in seconds."}, {"setMul", (PyCFunction)SigTo_setMul, METH_O, "Sets SigTo mul factor."}, {"setAdd", (PyCFunction)SigTo_setAdd, METH_O, "Sets SigTo add factor."}, {"setSub", (PyCFunction)SigTo_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)SigTo_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods SigTo_as_number = { (binaryfunc)SigTo_add, /*nb_add*/ (binaryfunc)SigTo_sub, /*nb_subtract*/ (binaryfunc)SigTo_multiply, /*nb_multiply*/ (binaryfunc)SigTo_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)SigTo_inplace_add, /*inplace_add*/ (binaryfunc)SigTo_inplace_sub, /*inplace_subtract*/ (binaryfunc)SigTo_inplace_multiply, /*inplace_multiply*/ (binaryfunc)SigTo_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SigToType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SigTo_base", /*tp_name*/ sizeof(SigTo), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SigTo_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &SigTo_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SigTo objects. Converts number into a signal stream and apply a ramp from last value.", /* tp_doc */ (traverseproc)SigTo_traverse, /* tp_traverse */ (inquiry)SigTo_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SigTo_methods, /* tp_methods */ SigTo_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SigTo_new, /* tp_new */ }; /***************************/ /* VarPort - Sig + ramp time + portamento + callback */ /***************************/ typedef struct { pyo_audio_HEAD PyObject *callable; PyObject *arg; MYFLT value; MYFLT time; MYFLT lastValue; MYFLT currentValue; long timeStep; long timeout; MYFLT stepVal; long timeCount; int modebuffer[2]; int flag; } VarPort; static void VarPort_generates_i(VarPort *self) { int i; PyObject *tuple, *result; if (self->value != self->lastValue) { self->flag = 1; self->timeCount = 0; self->stepVal = (self->value - self->currentValue) / (self->timeStep+1); self->lastValue = self->value; } if (self->flag == 1) { for (i=0; ibufsize; i++) { if (self->timeCount >= self->timeStep) self->currentValue = self->value; else if (self->timeCount < self->timeStep) { self->currentValue += self->stepVal; } self->timeCount++; self->data[i] = self->currentValue; } } else { for (i=0; ibufsize; i++) { self->data[i] = self->currentValue; } } if (self->timeCount >= self->timeout && self->flag == 1) { self->flag = 0; if (self->callable != Py_None) { if (self->arg != Py_None) { tuple = PyTuple_New(1); PyTuple_SET_ITEM(tuple, 0, self->arg); } else { tuple = PyTuple_New(0); } result = PyObject_Call(self->callable, tuple, NULL); if (result == NULL) { PyErr_Print(); return; } } } } static void VarPort_postprocessing_ii(VarPort *self) { POST_PROCESSING_II }; static void VarPort_postprocessing_ai(VarPort *self) { POST_PROCESSING_AI }; static void VarPort_postprocessing_ia(VarPort *self) { POST_PROCESSING_IA }; static void VarPort_postprocessing_aa(VarPort *self) { POST_PROCESSING_AA }; static void VarPort_postprocessing_ireva(VarPort *self) { POST_PROCESSING_IREVA }; static void VarPort_postprocessing_areva(VarPort *self) { POST_PROCESSING_AREVA }; static void VarPort_postprocessing_revai(VarPort *self) { POST_PROCESSING_REVAI }; static void VarPort_postprocessing_revaa(VarPort *self) { POST_PROCESSING_REVAA }; static void VarPort_postprocessing_revareva(VarPort *self) { POST_PROCESSING_REVAREVA }; static void VarPort_setProcMode(VarPort *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = VarPort_generates_i; switch (muladdmode) { case 0: self->muladd_func_ptr = VarPort_postprocessing_ii; break; case 1: self->muladd_func_ptr = VarPort_postprocessing_ai; break; case 2: self->muladd_func_ptr = VarPort_postprocessing_revai; break; case 10: self->muladd_func_ptr = VarPort_postprocessing_ia; break; case 11: self->muladd_func_ptr = VarPort_postprocessing_aa; break; case 12: self->muladd_func_ptr = VarPort_postprocessing_revaa; break; case 20: self->muladd_func_ptr = VarPort_postprocessing_ireva; break; case 21: self->muladd_func_ptr = VarPort_postprocessing_areva; break; case 22: self->muladd_func_ptr = VarPort_postprocessing_revareva; break; } } static void VarPort_compute_next_data_frame(VarPort *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int VarPort_traverse(VarPort *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->callable); Py_VISIT(self->arg); return 0; } static int VarPort_clear(VarPort *self) { pyo_CLEAR Py_CLEAR(self->callable); Py_CLEAR(self->arg); return 0; } static void VarPort_dealloc(VarPort* self) { pyo_DEALLOC VarPort_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * VarPort_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT inittmp = 0.0; PyObject *valuetmp=NULL, *timetmp=NULL, *calltmp=NULL, *argtmp=NULL, *multmp=NULL, *addtmp=NULL; VarPort *self; self = (VarPort *)type->tp_alloc(type, 0); self->flag = 1; self->time = 0.025; self->timeStep = (long)(self->time * self->sr); self->timeout = (long)((self->time + 0.1) * self->sr); self->timeCount = 0; self->stepVal = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->callable = Py_None; self->arg = Py_None; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, VarPort_compute_next_data_frame); self->mode_func_ptr = VarPort_setProcMode; static char *kwlist[] = {"value", "time", "init", "callable", "arg", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OFOOOO, kwlist, &valuetmp, &timetmp, &inittmp, &calltmp, &argtmp, &multmp, &addtmp)) Py_RETURN_NONE; if (valuetmp) { PyObject_CallMethod((PyObject *)self, "setValue", "O", valuetmp); } if (timetmp) { PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } if (calltmp) { Py_DECREF(self->callable); Py_INCREF(calltmp); self->callable = calltmp; } if (argtmp) { Py_DECREF(self->arg); Py_INCREF(argtmp); self->arg = argtmp; } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->lastValue = self->currentValue = inittmp; (*self->mode_func_ptr)(self); for(i=0; ibufsize; i++) { self->data[i] = self->currentValue; } return (PyObject *)self; } static PyObject * VarPort_setValue(VarPort *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); if (isNumber == 1) self->value = PyFloat_AsDouble(tmp); else self->value = self->lastValue; Py_INCREF(Py_None); return Py_None; } static PyObject * VarPort_setTime(VarPort *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); if (isNumber == 1) { self->time = PyFloat_AsDouble(tmp); self->timeStep = (long)(self->time * self->sr); self->timeout = (long)((self->time + 0.1) * self->sr); } Py_INCREF(Py_None); return Py_None; } static PyObject * VarPort_setFunction(VarPort *self, PyObject *arg) { PyObject *tmp; if (! PyCallable_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The function attribute must be callable."); Py_INCREF(Py_None); return Py_None; } tmp = arg; Py_XDECREF(self->callable); Py_INCREF(tmp); self->callable = tmp; Py_INCREF(Py_None); return Py_None; } static PyObject * VarPort_getServer(VarPort* self) { GET_SERVER }; static PyObject * VarPort_getStream(VarPort* self) { GET_STREAM }; static PyObject * VarPort_setMul(VarPort *self, PyObject *arg) { SET_MUL }; static PyObject * VarPort_setAdd(VarPort *self, PyObject *arg) { SET_ADD }; static PyObject * VarPort_setSub(VarPort *self, PyObject *arg) { SET_SUB }; static PyObject * VarPort_setDiv(VarPort *self, PyObject *arg) { SET_DIV }; static PyObject * VarPort_play(VarPort *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * VarPort_stop(VarPort *self) { STOP }; static PyObject * VarPort_multiply(VarPort *self, PyObject *arg) { MULTIPLY }; static PyObject * VarPort_inplace_multiply(VarPort *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * VarPort_add(VarPort *self, PyObject *arg) { ADD }; static PyObject * VarPort_inplace_add(VarPort *self, PyObject *arg) { INPLACE_ADD }; static PyObject * VarPort_sub(VarPort *self, PyObject *arg) { SUB }; static PyObject * VarPort_inplace_sub(VarPort *self, PyObject *arg) { INPLACE_SUB }; static PyObject * VarPort_div(VarPort *self, PyObject *arg) { DIV }; static PyObject * VarPort_inplace_div(VarPort *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef VarPort_members[] = { {"server", T_OBJECT_EX, offsetof(VarPort, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(VarPort, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(VarPort, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(VarPort, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef VarPort_methods[] = { {"getServer", (PyCFunction)VarPort_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)VarPort_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)VarPort_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)VarPort_stop, METH_NOARGS, "Stops computing."}, {"setValue", (PyCFunction)VarPort_setValue, METH_O, "Sets VarPort value."}, {"setTime", (PyCFunction)VarPort_setTime, METH_O, "Sets ramp time in seconds."}, {"setFunction", (PyCFunction)VarPort_setFunction, METH_O, "Sets function to be called."}, {"setMul", (PyCFunction)VarPort_setMul, METH_O, "Sets VarPort mul factor."}, {"setAdd", (PyCFunction)VarPort_setAdd, METH_O, "Sets VarPort add factor."}, {"setSub", (PyCFunction)VarPort_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)VarPort_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods VarPort_as_number = { (binaryfunc)VarPort_add, /*nb_add*/ (binaryfunc)VarPort_sub, /*nb_subtract*/ (binaryfunc)VarPort_multiply, /*nb_multiply*/ (binaryfunc)VarPort_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)VarPort_inplace_add, /*inplace_add*/ (binaryfunc)VarPort_inplace_sub, /*inplace_subtract*/ (binaryfunc)VarPort_inplace_multiply, /*inplace_multiply*/ (binaryfunc)VarPort_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject VarPortType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.VarPort_base", /*tp_name*/ sizeof(VarPort), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)VarPort_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &VarPort_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "VarPort objects. Converts number into a signal stream and apply a ramp from last value.", /* tp_doc */ (traverseproc)VarPort_traverse, /* tp_traverse */ (inquiry)VarPort_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ VarPort_methods, /* tp_methods */ VarPort_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ VarPort_new, /* tp_new */ }; pyo/src/objects/sfplayermodule.c0000644000175000017500000024221512652732202016303 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "sndfile.h" #include "interpolation.h" /* SfPlayer object */ typedef struct { pyo_audio_HEAD PyObject *speed; Stream *speed_stream; int modebuffer[1]; SNDFILE *sf; SF_INFO info; char *path; int loop; int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */ int sndSize; /* number of frames */ int sndChnls; int sndSr; MYFLT srScale; MYFLT startPos; double pointerPos; MYFLT *samplesBuffer; MYFLT *trigsBuffer; TriggerStream *trig_stream; int init; MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int); } SfPlayer; MYFLT max_arr(MYFLT *a,int n) { int i; MYFLT m; m=*a; for (i=1; i *(a+i)) m = *(a+i); } return m; } static void SfPlayer_readframes_i(SfPlayer *self) { MYFLT sp, frac, bufpos, delta, startPos; int i, j, totlen, buflen, shortbuflen, pad, bufindex; sf_count_t index; if (self->modebuffer[0] == 0) sp = PyFloat_AS_DOUBLE(self->speed); else sp = Stream_getData((Stream *)self->speed_stream)[0]; delta = MYFABS(sp) * self->srScale; buflen = (int)(self->bufsize * delta + 0.5) + 64; totlen = self->sndChnls*buflen; MYFLT buffer[totlen]; MYFLT buffer2[self->sndChnls][buflen]; if (sp > 0) { /* forward reading */ if (self->pointerPos >= self->sndSize) { self->pointerPos -= self->sndSize - self->startPos; if (self->loop == 0) { PyObject_CallMethod((PyObject *)self, "stop", NULL); for (i=0; i<(self->bufsize * self->sndChnls); i++) { self->samplesBuffer[i] = 0.0; } for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } return; } } index = (int)self->pointerPos; sf_seek(self->sf, index, SEEK_SET); /* sets position pointer in the file */ /* fill a buffer with enough samples to satisfy speed reading */ /* if not enough samples left in the file */ if ((index+buflen) > self->sndSize) { shortbuflen = self->sndSize - index; pad = (buflen-shortbuflen)*self->sndChnls; SF_READ(self->sf, buffer, shortbuflen*self->sndChnls); if (self->loop == 0) { /* with zero padding if noloop */ for (i=0; isndChnls] = 0.; } } else { /* wrap around and read new samples if loop */ MYFLT buftemp[pad]; sf_seek(self->sf, (int)self->startPos, SEEK_SET); SF_READ(self->sf, buftemp, pad); for (i=0; i<(pad); i++) { buffer[i+shortbuflen*self->sndChnls] = buftemp[i]; } } } else /* without zero padding */ SF_READ(self->sf, buffer, totlen); /* de-interleave samples */ for (i=0; isndChnls][(int)(i/self->sndChnls)] = buffer[i]; } /* fill samplesBuffer with samples */ for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; bufpos = self->pointerPos - index; bufindex = (int)bufpos; frac = bufpos - bufindex; for (j=0; jsndChnls; j++) { self->samplesBuffer[i+(j*self->bufsize)] = (*self->interp_func_ptr)(buffer2[j], bufindex, frac, buflen); } self->pointerPos += delta; } if (self->pointerPos >= self->sndSize) self->trigsBuffer[0] = 1.0; } else if (sp < 0){ /* backward reading */ startPos = self->startPos; if (startPos == 0.) startPos = self->sndSize - 1; if (self->pointerPos == 0.0) self->pointerPos = self->sndSize - 1; if (self->pointerPos <= 0) { self->pointerPos += startPos; if (self->loop == 0) { PyObject_CallMethod((PyObject *)self, "stop", NULL); for (i=0; i<(self->bufsize * self->sndChnls); i++) { self->samplesBuffer[i] = 0.0; } for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } return; } } index = (int)self->pointerPos + 1; /* fill a buffer with enough samples to satisfy speed reading */ /* if not enough samples to read in the file */ if ((index-buflen) < 0) { shortbuflen = index; int pad = buflen - shortbuflen; int padlen = pad*self->sndChnls; if (self->loop == 0) { /* with zero padding if noloop */ for (i=0; isf, (int)startPos-pad, SEEK_SET); SF_READ(self->sf, buftemp, padlen); for (i=0; isndChnls]; sf_seek(self->sf, 0, SEEK_SET); /* sets position pointer in the file */ SF_READ(self->sf, buftemp2, shortbuflen*self->sndChnls); for (i=0; i<(shortbuflen*self->sndChnls); i++) { buffer[i+padlen] = buftemp2[i]; } } else /* without zero padding */ sf_seek(self->sf, index-buflen, SEEK_SET); /* sets position pointer in the file */ SF_READ(self->sf, buffer, totlen); /* de-interleave samples */ for (i=0; isndChnls][(int)(i/self->sndChnls)] = buffer[i]; } /* reverse arrays */ MYFLT swap; for (i=0; isndChnls; i++) { int a; int b = buflen; for (a=0; a<--b; a++) { //increment a and decrement b until they meet eachother swap = buffer2[i][a]; //put what's in a into swap space buffer2[i][a] = buffer2[i][b]; //put what's in b into a buffer2[i][b] = swap; //put what's in the swap (a) into b } } /* fill stream buffer with samples */ for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; bufpos = index - self->pointerPos; bufindex = (int)bufpos; frac = bufpos - bufindex; for (j=0; jsndChnls; j++) { self->samplesBuffer[i+(j*self->bufsize)] = (*self->interp_func_ptr)(buffer2[j], bufindex, frac, buflen); } self->pointerPos -= delta; } if (self->pointerPos <= 0) { if (self->init == 0) self->trigsBuffer[0] = 1.0; else self->init = 0; } } else { /* speed == 0.0 */ for (i = 0; i < (self->bufsize*self->sndChnls); i++) { self->samplesBuffer[i] = 0.0; } } } static void SfPlayer_setProcMode(SfPlayer *self) { self->proc_func_ptr = SfPlayer_readframes_i; } static void SfPlayer_compute_next_data_frame(SfPlayer *self) { (*self->proc_func_ptr)(self); } static int SfPlayer_traverse(SfPlayer *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->speed); Py_VISIT(self->speed_stream); Py_VISIT(self->trig_stream); return 0; } static int SfPlayer_clear(SfPlayer *self) { pyo_CLEAR Py_CLEAR(self->speed); Py_CLEAR(self->speed_stream); Py_CLEAR(self->trig_stream); return 0; } static void SfPlayer_dealloc(SfPlayer* self) { pyo_DEALLOC if (self->sf != NULL) sf_close(self->sf); free(self->trigsBuffer); free(self->samplesBuffer); SfPlayer_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SfPlayer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT offset = 0.; PyObject *speedtmp=NULL; SfPlayer *self; self = (SfPlayer *)type->tp_alloc(type, 0); self->speed = PyFloat_FromDouble(1); self->loop = 0; self->interp = 2; self->init = 1; self->modebuffer[0] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, SfPlayer_compute_next_data_frame); self->mode_func_ptr = SfPlayer_setProcMode; static char *kwlist[] = {"path", "speed", "loop", "offset", "interp", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_S__OIFI, kwlist, &self->path, &speedtmp, &self->loop, &offset, &self->interp)) Py_RETURN_NONE; if (speedtmp) { PyObject_CallMethod((PyObject *)self, "setSpeed", "O", speedtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); SET_INTERP_POINTER /* Open the sound file. */ self->info.format = 0; self->sf = sf_open(self->path, SFM_READ, &self->info); if (self->sf == NULL) { printf("Failed to open the file.\n"); } self->sndSize = self->info.frames; self->sndSr = self->info.samplerate; self->sndChnls = self->info.channels; self->srScale = self->sndSr / self->sr; self->samplesBuffer = (MYFLT *)realloc(self->samplesBuffer, self->bufsize * self->sndChnls * sizeof(MYFLT)); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); self->startPos = offset * self->sr * self->srScale; if (self->startPos < 0.0 || self->startPos >= self->sndSize) self->startPos = 0.0; self->pointerPos = self->startPos; return (PyObject *)self; } static PyObject * SfPlayer_getServer(SfPlayer* self) { GET_SERVER }; static PyObject * SfPlayer_getStream(SfPlayer* self) { GET_STREAM }; static PyObject * SfPlayer_getTriggerStream(SfPlayer* self) { GET_TRIGGER_STREAM }; static PyObject * SfPlayer_play(SfPlayer *self, PyObject *args, PyObject *kwds) { self->init = 1; self->pointerPos = self->startPos; PLAY }; static PyObject * SfPlayer_out(SfPlayer *self, PyObject *args, PyObject *kwds) { self->init = 1; self->pointerPos = self->startPos; OUT }; static PyObject * SfPlayer_stop(SfPlayer *self) { STOP }; static PyObject * SfPlayer_setSpeed(SfPlayer *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->speed); if (isNumber == 1) { self->speed = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->speed = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->speed, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->speed_stream); self->speed_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SfPlayer_setSound(SfPlayer *self, PyObject *arg) { /* Need to perform a check to be sure that the new sound is of the same number of channels. */ ASSERT_ARG_NOT_NULL self->path = PyString_AsString(arg); sf_close(self->sf); /* Open the sound file. */ self->info.format = 0; self->sf = sf_open(self->path, SFM_READ, &self->info); if (self->sf == NULL) { printf("Failed to open the file.\n"); } self->sndSize = self->info.frames; self->sndSr = self->info.samplerate; //self->sndChnls = self->info.channels; self->srScale = self->sndSr / self->sr; //self->samplesBuffer = (MYFLT *)realloc(self->samplesBuffer, self->bufsize * self->sndChnls * sizeof(MYFLT)); self->startPos = 0.0; self->pointerPos = self->startPos; Py_INCREF(Py_None); return Py_None; } static PyObject * SfPlayer_setLoop(SfPlayer *self, PyObject *arg) { ASSERT_ARG_NOT_NULL self->loop = PyInt_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * SfPlayer_setOffset(SfPlayer *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->startPos = PyFloat_AsDouble(arg) * self->sr * self->srScale; if (self->startPos < 0.0 || self->startPos >= self->sndSize) self->startPos = 0.0; } Py_INCREF(Py_None); return Py_None; } static PyObject * SfPlayer_setInterp(SfPlayer *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->interp = PyInt_AsLong(PyNumber_Int(arg)); } SET_INTERP_POINTER Py_INCREF(Py_None); return Py_None; } MYFLT * SfPlayer_getSamplesBuffer(SfPlayer *self) { return (MYFLT *)self->samplesBuffer; } static PyMemberDef SfPlayer_members[] = { {"server", T_OBJECT_EX, offsetof(SfPlayer, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SfPlayer, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(SfPlayer, trig_stream), 0, "Trigger Stream object."}, {"speed", T_OBJECT_EX, offsetof(SfPlayer, speed), 0, "Frequency in cycle per second."}, {NULL} /* Sentinel */ }; static PyMethodDef SfPlayer_methods[] = { {"getServer", (PyCFunction)SfPlayer_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SfPlayer_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)SfPlayer_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"play", (PyCFunction)SfPlayer_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)SfPlayer_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)SfPlayer_stop, METH_NOARGS, "Stops computing."}, {"setSound", (PyCFunction)SfPlayer_setSound, METH_O, "Sets sfplayer sound path."}, {"setSpeed", (PyCFunction)SfPlayer_setSpeed, METH_O, "Sets sfplayer reading speed."}, {"setLoop", (PyCFunction)SfPlayer_setLoop, METH_O, "Sets sfplayer loop mode (0 = no loop, 1 = loop)."}, {"setOffset", (PyCFunction)SfPlayer_setOffset, METH_O, "Sets sfplayer start position."}, {"setInterp", (PyCFunction)SfPlayer_setInterp, METH_O, "Sets sfplayer interpolation mode."}, {NULL} /* Sentinel */ }; PyTypeObject SfPlayerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SfPlayer_base", /*tp_name*/ sizeof(SfPlayer), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SfPlayer_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SfPlayer objects. Reads a soundfile directly from disk.", /* tp_doc */ (traverseproc)SfPlayer_traverse, /* tp_traverse */ (inquiry)SfPlayer_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SfPlayer_methods, /* tp_methods */ SfPlayer_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SfPlayer_new, /* tp_new */ }; /************************************************************************************************/ /* Sfplay streamer object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD SfPlayer *mainPlayer; int modebuffer[2]; int chnl; } SfPlay; static void SfPlay_postprocessing_ii(SfPlay *self) { POST_PROCESSING_II }; static void SfPlay_postprocessing_ai(SfPlay *self) { POST_PROCESSING_AI }; static void SfPlay_postprocessing_ia(SfPlay *self) { POST_PROCESSING_IA }; static void SfPlay_postprocessing_aa(SfPlay *self) { POST_PROCESSING_AA }; static void SfPlay_postprocessing_ireva(SfPlay *self) { POST_PROCESSING_IREVA }; static void SfPlay_postprocessing_areva(SfPlay *self) { POST_PROCESSING_AREVA }; static void SfPlay_postprocessing_revai(SfPlay *self) { POST_PROCESSING_REVAI }; static void SfPlay_postprocessing_revaa(SfPlay *self) { POST_PROCESSING_REVAA }; static void SfPlay_postprocessing_revareva(SfPlay *self) { POST_PROCESSING_REVAREVA }; static void SfPlay_setProcMode(SfPlay *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = SfPlay_postprocessing_ii; break; case 1: self->muladd_func_ptr = SfPlay_postprocessing_ai; break; case 2: self->muladd_func_ptr = SfPlay_postprocessing_revai; break; case 10: self->muladd_func_ptr = SfPlay_postprocessing_ia; break; case 11: self->muladd_func_ptr = SfPlay_postprocessing_aa; break; case 12: self->muladd_func_ptr = SfPlay_postprocessing_revaa; break; case 20: self->muladd_func_ptr = SfPlay_postprocessing_ireva; break; case 21: self->muladd_func_ptr = SfPlay_postprocessing_areva; break; case 22: self->muladd_func_ptr = SfPlay_postprocessing_revareva; break; } } static void SfPlay_compute_next_data_frame(SfPlay *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = SfPlayer_getSamplesBuffer((SfPlayer *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int SfPlay_traverse(SfPlay *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int SfPlay_clear(SfPlay *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void SfPlay_dealloc(SfPlay* self) { pyo_DEALLOC SfPlay_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SfPlay_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; SfPlay *self; self = (SfPlay *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, SfPlay_compute_next_data_frame); self->mode_func_ptr = SfPlay_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (SfPlayer *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * SfPlay_getServer(SfPlay* self) { GET_SERVER }; static PyObject * SfPlay_getStream(SfPlay* self) { GET_STREAM }; static PyObject * SfPlay_setMul(SfPlay *self, PyObject *arg) { SET_MUL }; static PyObject * SfPlay_setAdd(SfPlay *self, PyObject *arg) { SET_ADD }; static PyObject * SfPlay_setSub(SfPlay *self, PyObject *arg) { SET_SUB }; static PyObject * SfPlay_setDiv(SfPlay *self, PyObject *arg) { SET_DIV }; static PyObject * SfPlay_play(SfPlay *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SfPlay_out(SfPlay *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * SfPlay_stop(SfPlay *self) { STOP }; static PyObject * SfPlay_multiply(SfPlay *self, PyObject *arg) { MULTIPLY }; static PyObject * SfPlay_inplace_multiply(SfPlay *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * SfPlay_add(SfPlay *self, PyObject *arg) { ADD }; static PyObject * SfPlay_inplace_add(SfPlay *self, PyObject *arg) { INPLACE_ADD }; static PyObject * SfPlay_sub(SfPlay *self, PyObject *arg) { SUB }; static PyObject * SfPlay_inplace_sub(SfPlay *self, PyObject *arg) { INPLACE_SUB }; static PyObject * SfPlay_div(SfPlay *self, PyObject *arg) { DIV }; static PyObject * SfPlay_inplace_div(SfPlay *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef SfPlay_members[] = { {"server", T_OBJECT_EX, offsetof(SfPlay, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SfPlay, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(SfPlay, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(SfPlay, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef SfPlay_methods[] = { {"getServer", (PyCFunction)SfPlay_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SfPlay_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SfPlay_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)SfPlay_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)SfPlay_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)SfPlay_setMul, METH_O, "Sets SfPlay mul factor."}, {"setAdd", (PyCFunction)SfPlay_setAdd, METH_O, "Sets SfPlay add factor."}, {"setSub", (PyCFunction)SfPlay_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)SfPlay_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods SfPlay_as_number = { (binaryfunc)SfPlay_add, /*nb_add*/ (binaryfunc)SfPlay_sub, /*nb_subtract*/ (binaryfunc)SfPlay_multiply, /*nb_multiply*/ (binaryfunc)SfPlay_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)SfPlay_inplace_add, /*inplace_add*/ (binaryfunc)SfPlay_inplace_sub, /*inplace_subtract*/ (binaryfunc)SfPlay_inplace_multiply, /*inplace_multiply*/ (binaryfunc)SfPlay_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SfPlayType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SfPlay_base", /*tp_name*/ sizeof(SfPlay), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SfPlay_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &SfPlay_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SfPlay objects. Reads a channel from a soundfile directly from disk.", /* tp_doc */ (traverseproc)SfPlay_traverse, /* tp_traverse */ (inquiry)SfPlay_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SfPlay_methods, /* tp_methods */ SfPlay_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SfPlay_new, /* tp_new */ }; /************************************************************************************************/ /* SfMarkerShuffler object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD PyObject *speed; Stream *speed_stream; int modebuffer[1]; SNDFILE *sf; SF_INFO info; char *path; int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */ int sndSize; /* number of frames */ int sndChnls; int sndSr; int lastDir; MYFLT srScale; MYFLT startPos; MYFLT endPos; MYFLT nextStartPos; MYFLT nextEndPos; double pointerPos; MYFLT *samplesBuffer; MYFLT *markers; int markers_size; MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int); } SfMarkerShuffler; /*** PROTOTYPES ***/ static void SfMarkerShuffler_chooseNewMark(SfMarkerShuffler *self, int dir); /******************/ static void SfMarkerShuffler_readframes_i(SfMarkerShuffler *self) { MYFLT sp, frac, bufpos, delta, tmp; int i, j, totlen, buflen, shortbuflen, bufindex; sf_count_t index; if (self->modebuffer[0] == 0) sp = PyFloat_AS_DOUBLE(self->speed); else sp = Stream_getData((Stream *)self->speed_stream)[0]; delta = MYFABS(sp) * self->srScale; buflen = (int)(self->bufsize * delta + 0.5) + 64; totlen = self->sndChnls*buflen; MYFLT buffer[totlen]; MYFLT buffer2[self->sndChnls][buflen]; if (sp > 0) { /* reading forward */ if (self->startPos == -1 || self->lastDir == 0) { self->lastDir = 1; SfMarkerShuffler_chooseNewMark((SfMarkerShuffler *)self, 1); self->pointerPos = self->startPos; } if (self->lastDir != 1) { tmp = self->startPos; self->startPos = self->endPos; self->endPos = tmp; self->lastDir = 1; } index = (int)self->pointerPos; sf_seek(self->sf, index, SEEK_SET); /* sets position pointer in the file */ /* fill a buffer with enough samples to satisfy speed reading */ /* if not enough samples to read in the file */ if ((index+buflen) > self->endPos) { shortbuflen = self->endPos - index; SF_READ(self->sf, buffer, shortbuflen*self->sndChnls); /* wrap around and read new samples from new marker */ int pad = buflen - shortbuflen; int padlen = pad*self->sndChnls; MYFLT buftemp[padlen]; sf_seek(self->sf, (int)self->nextStartPos, SEEK_SET); SF_READ(self->sf, buftemp, padlen); for (i=0; isndChnls] = buftemp[i]; } } else /* without wraparound */ SF_READ(self->sf, buffer, totlen); /* de-interleave samples */ for (i=0; isndChnls][(int)(i/self->sndChnls)] = buffer[i]; } /* fill data with samples */ for (i=0; ibufsize; i++) { bufpos = self->pointerPos - index; bufindex = (int)bufpos; frac = bufpos - bufindex; for (j=0; jsndChnls; j++) { self->samplesBuffer[i+(j*self->bufsize)] = (*self->interp_func_ptr)(buffer2[j], bufindex, frac, buflen); } self->pointerPos += delta; } if (self->pointerPos >= self->endPos) { MYFLT off = self->pointerPos - self->endPos; SfMarkerShuffler_chooseNewMark((SfMarkerShuffler *)self, 1); self->pointerPos = self->startPos + off; } } else if (sp < 0) { /* reading backward */ if (self->startPos == -1 || self->lastDir != -1) { self->lastDir = self->startPos = -1; SfMarkerShuffler_chooseNewMark((SfMarkerShuffler *)self, 0); self->pointerPos = self->startPos; } index = (int)self->pointerPos + 1; /* fill a buffer with enough samples to satisfy speed reading */ /* if not enough samples to read in the file */ if ((index-buflen) < self->endPos) { shortbuflen = index - self->endPos; int pad = buflen - shortbuflen; int padlen = pad*self->sndChnls; /* wrap around and read new samples from new marker */ MYFLT buftemp[padlen]; sf_seek(self->sf, (int)self->nextStartPos-pad, SEEK_SET); SF_READ(self->sf, buftemp, padlen); for (i=0; isndChnls]; sf_seek(self->sf, self->endPos, SEEK_SET); /* sets position pointer in the file */ SF_READ(self->sf, buftemp2, shortbuflen*self->sndChnls); for (i=0; i<(shortbuflen*self->sndChnls); i++) { buffer[i+padlen] = buftemp2[i]; } } else { /* without wraparound */ sf_seek(self->sf, index-buflen, SEEK_SET); /* sets position pointer in the file */ SF_READ(self->sf, buffer, totlen); } /* de-interleave samples */ for (i=0; isndChnls][(int)(i/self->sndChnls)] = buffer[i]; } /* reverse arrays */ MYFLT swap; for (i=0; isndChnls; i++) { int a; int b = buflen; for (a=0; a<--b; a++) { //increment a and decrement b until they meet eachother swap = buffer2[i][a]; //put what's in a into swap space buffer2[i][a] = buffer2[i][b]; //put what's in b into a buffer2[i][b] = swap; //put what's in the swap (a) into b } } /* fill stream buffer with samples */ for (i=0; ibufsize; i++) { bufpos = index - self->pointerPos; bufindex = (int)bufpos; frac = bufpos - bufindex; for (j=0; jsndChnls; j++) { self->samplesBuffer[i+(j*self->bufsize)] = (*self->interp_func_ptr)(buffer2[j], bufindex, frac, buflen); } self->pointerPos -= delta; } if (self->pointerPos <= self->endPos) { MYFLT off = self->endPos - self->pointerPos; SfMarkerShuffler_chooseNewMark((SfMarkerShuffler *)self, 0); self->pointerPos = self->startPos - off; } } else { /* speed == 0 */ self->lastDir = 0; for (i = 0; i < (self->bufsize*self->sndChnls); i++) { self->samplesBuffer[i] = 0.0; } } } static void SfMarkerShuffler_setProcMode(SfMarkerShuffler *self) { self->proc_func_ptr = SfMarkerShuffler_readframes_i; } static void SfMarkerShuffler_compute_next_data_frame(SfMarkerShuffler *self) { (*self->proc_func_ptr)(self); } static void SfMarkerShuffler_chooseNewMark(SfMarkerShuffler *self, int dir) { int mark; if (dir == 1) { if (self->startPos == -1) { mark = (int)(self->markers_size * (rand()/((MYFLT)(RAND_MAX)+1))); self->startPos = self->markers[mark] * self->srScale; self->endPos = self->markers[mark+1] * self->srScale; } else { self->startPos = self->nextStartPos; self->endPos = self->nextEndPos; } mark = (int)(self->markers_size * (rand()/((MYFLT)(RAND_MAX)+1))); self->nextStartPos = self->markers[mark] * self->srScale; self->nextEndPos = self->markers[mark+1] * self->srScale; } else { if (self->startPos == -1) { mark = self->markers_size - (int)(self->markers_size * (rand()/((MYFLT)(RAND_MAX)+1))); self->startPos = self->markers[mark] * self->srScale; self->endPos = self->markers[mark-1] * self->srScale; } else { self->startPos = self->nextStartPos; self->endPos = self->nextEndPos; } mark = self->markers_size - (int)(self->markers_size * (rand()/((MYFLT)(RAND_MAX)+1))); self->nextStartPos = self->markers[mark] * self->srScale; self->nextEndPos = self->markers[mark-1] * self->srScale; } } static void SfMarkerShuffler_setMarkers(SfMarkerShuffler *self, PyObject *markerstmp) { Py_ssize_t i; Py_ssize_t len = PyList_Size(markerstmp); self->markers = (MYFLT *)realloc(self->markers, (len + 2) * sizeof(MYFLT)); self->markers[0] = 0.; for (i=0; imarkers[i+1] = PyFloat_AsDouble(PyList_GetItem(markerstmp, i)); } self->markers[len+1] = self->sndSize; self->markers_size = (int)len+1; } static int SfMarkerShuffler_traverse(SfMarkerShuffler *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->speed); Py_VISIT(self->speed_stream); return 0; } static int SfMarkerShuffler_clear(SfMarkerShuffler *self) { pyo_CLEAR Py_CLEAR(self->speed); Py_CLEAR(self->speed_stream); return 0; } static void SfMarkerShuffler_dealloc(SfMarkerShuffler* self) { pyo_DEALLOC if (self->sf != NULL) sf_close(self->sf); free(self->samplesBuffer); free(self->markers); SfMarkerShuffler_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SfMarkerShuffler_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *speedtmp=NULL, *markerstmp=NULL; SfMarkerShuffler *self; self = (SfMarkerShuffler *)type->tp_alloc(type, 0); self->speed = PyFloat_FromDouble(1); self->interp = 2; self->startPos = -1; self->endPos = -1; self->modebuffer[0] = 0; self->lastDir = 1; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, SfMarkerShuffler_compute_next_data_frame); self->mode_func_ptr = SfMarkerShuffler_setProcMode; static char *kwlist[] = {"path", "markers", "speed", "interp", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "sO|Oi", kwlist, &self->path, &markerstmp, &speedtmp, &self->interp)) Py_RETURN_NONE; if (speedtmp) { PyObject_CallMethod((PyObject *)self, "setSpeed", "O", speedtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); if (self->interp == 0) self->interp = 2; if (self->interp == 1) self->interp_func_ptr = nointerp; else if (self->interp == 2) self->interp_func_ptr = linear; else if (self->interp == 3) self->interp_func_ptr = cosine; else if (self->interp == 4) self->interp_func_ptr = cubic; /* Open the sound file. */ self->info.format = 0; self->sf = sf_open(self->path, SFM_READ, &self->info); if (self->sf == NULL) { printf("Failed to open the file.\n"); Py_RETURN_NONE; } self->sndSize = self->info.frames; self->sndSr = self->info.samplerate; self->sndChnls = self->info.channels; self->srScale = self->sndSr / self->sr; Py_INCREF(markerstmp); SfMarkerShuffler_setMarkers((SfMarkerShuffler *)self, markerstmp); self->samplesBuffer = (MYFLT *)realloc(self->samplesBuffer, self->bufsize * self->sndChnls * sizeof(MYFLT)); Server_generateSeed((Server *)self->server, SFMARKERSHUFFLER_ID); return (PyObject *)self; } static PyObject * SfMarkerShuffler_getServer(SfMarkerShuffler* self) { GET_SERVER }; static PyObject * SfMarkerShuffler_getStream(SfMarkerShuffler* self) { GET_STREAM }; static PyObject * SfMarkerShuffler_play(SfMarkerShuffler *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SfMarkerShuffler_out(SfMarkerShuffler *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * SfMarkerShuffler_stop(SfMarkerShuffler *self) { STOP }; static PyObject * SfMarkerShuffler_setSpeed(SfMarkerShuffler *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->speed); if (isNumber == 1) { self->speed = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->speed = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->speed, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->speed_stream); self->speed_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * SfMarkerShuffler_setInterp(SfMarkerShuffler *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->interp = PyInt_AsLong(PyNumber_Int(arg)); } if (self->interp == 0) self->interp = 2; if (self->interp == 1) self->interp_func_ptr = nointerp; else if (self->interp == 2) self->interp_func_ptr = linear; else if (self->interp == 3) self->interp_func_ptr = cosine; else if (self->interp == 4) self->interp_func_ptr = cubic; Py_INCREF(Py_None); return Py_None; } MYFLT * SfMarkerShuffler_getSamplesBuffer(SfMarkerShuffler *self) { return (MYFLT *)self->samplesBuffer; } static PyMemberDef SfMarkerShuffler_members[] = { {"server", T_OBJECT_EX, offsetof(SfMarkerShuffler, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SfMarkerShuffler, stream), 0, "Stream object."}, {"speed", T_OBJECT_EX, offsetof(SfMarkerShuffler, speed), 0, "Frequency in cycle per second."}, {NULL} /* Sentinel */ }; static PyMethodDef SfMarkerShuffler_methods[] = { {"getServer", (PyCFunction)SfMarkerShuffler_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SfMarkerShuffler_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SfMarkerShuffler_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)SfMarkerShuffler_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)SfMarkerShuffler_stop, METH_NOARGS, "Stops computing."}, {"setSpeed", (PyCFunction)SfMarkerShuffler_setSpeed, METH_O, "Sets sfplayer reading speed."}, {"setInterp", (PyCFunction)SfMarkerShuffler_setInterp, METH_O, "Sets sfplayer interpolation mode."}, {NULL} /* Sentinel */ }; PyTypeObject SfMarkerShufflerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SfMarkerShuffler_base", /*tp_name*/ sizeof(SfMarkerShuffler), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SfMarkerShuffler_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SfMarkerShuffler objects. Shuffle an AIFF soundfile from markers points.", /* tp_doc */ (traverseproc)SfMarkerShuffler_traverse, /* tp_traverse */ (inquiry)SfMarkerShuffler_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SfMarkerShuffler_methods, /* tp_methods */ SfMarkerShuffler_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SfMarkerShuffler_new, /* tp_new */ }; /************************************************************************************************/ /* SfMarkerShuffle streamer object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD SfMarkerShuffler *mainPlayer; int modebuffer[2]; int chnl; } SfMarkerShuffle; static void SfMarkerShuffle_postprocessing_ii(SfMarkerShuffle *self) { POST_PROCESSING_II }; static void SfMarkerShuffle_postprocessing_ai(SfMarkerShuffle *self) { POST_PROCESSING_AI }; static void SfMarkerShuffle_postprocessing_ia(SfMarkerShuffle *self) { POST_PROCESSING_IA }; static void SfMarkerShuffle_postprocessing_aa(SfMarkerShuffle *self) { POST_PROCESSING_AA }; static void SfMarkerShuffle_postprocessing_ireva(SfMarkerShuffle *self) { POST_PROCESSING_IREVA }; static void SfMarkerShuffle_postprocessing_areva(SfMarkerShuffle *self) { POST_PROCESSING_AREVA }; static void SfMarkerShuffle_postprocessing_revai(SfMarkerShuffle *self) { POST_PROCESSING_REVAI }; static void SfMarkerShuffle_postprocessing_revaa(SfMarkerShuffle *self) { POST_PROCESSING_REVAA }; static void SfMarkerShuffle_postprocessing_revareva(SfMarkerShuffle *self) { POST_PROCESSING_REVAREVA }; static void SfMarkerShuffle_setProcMode(SfMarkerShuffle *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = SfMarkerShuffle_postprocessing_ii; break; case 1: self->muladd_func_ptr = SfMarkerShuffle_postprocessing_ai; break; case 2: self->muladd_func_ptr = SfMarkerShuffle_postprocessing_revai; break; case 10: self->muladd_func_ptr = SfMarkerShuffle_postprocessing_ia; break; case 11: self->muladd_func_ptr = SfMarkerShuffle_postprocessing_aa; break; case 12: self->muladd_func_ptr = SfMarkerShuffle_postprocessing_revaa; break; case 20: self->muladd_func_ptr = SfMarkerShuffle_postprocessing_ireva; break; case 21: self->muladd_func_ptr = SfMarkerShuffle_postprocessing_areva; break; case 22: self->muladd_func_ptr = SfMarkerShuffle_postprocessing_revareva; break; } } static void SfMarkerShuffle_compute_next_data_frame(SfMarkerShuffle *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = SfMarkerShuffler_getSamplesBuffer((SfMarkerShuffler *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int SfMarkerShuffle_traverse(SfMarkerShuffle *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int SfMarkerShuffle_clear(SfMarkerShuffle *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void SfMarkerShuffle_dealloc(SfMarkerShuffle* self) { pyo_DEALLOC SfMarkerShuffle_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SfMarkerShuffle_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; SfMarkerShuffle *self; self = (SfMarkerShuffle *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, SfMarkerShuffle_compute_next_data_frame); self->mode_func_ptr = SfMarkerShuffle_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (SfMarkerShuffler *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * SfMarkerShuffle_getServer(SfMarkerShuffle* self) { GET_SERVER }; static PyObject * SfMarkerShuffle_getStream(SfMarkerShuffle* self) { GET_STREAM }; static PyObject * SfMarkerShuffle_setMul(SfMarkerShuffle *self, PyObject *arg) { SET_MUL }; static PyObject * SfMarkerShuffle_setAdd(SfMarkerShuffle *self, PyObject *arg) { SET_ADD }; static PyObject * SfMarkerShuffle_setSub(SfMarkerShuffle *self, PyObject *arg) { SET_SUB }; static PyObject * SfMarkerShuffle_setDiv(SfMarkerShuffle *self, PyObject *arg) { SET_DIV }; static PyObject * SfMarkerShuffle_play(SfMarkerShuffle *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SfMarkerShuffle_out(SfMarkerShuffle *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * SfMarkerShuffle_stop(SfMarkerShuffle *self) { STOP }; static PyObject * SfMarkerShuffle_multiply(SfMarkerShuffle *self, PyObject *arg) { MULTIPLY }; static PyObject * SfMarkerShuffle_inplace_multiply(SfMarkerShuffle *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * SfMarkerShuffle_add(SfMarkerShuffle *self, PyObject *arg) { ADD }; static PyObject * SfMarkerShuffle_inplace_add(SfMarkerShuffle *self, PyObject *arg) { INPLACE_ADD }; static PyObject * SfMarkerShuffle_sub(SfMarkerShuffle *self, PyObject *arg) { SUB }; static PyObject * SfMarkerShuffle_inplace_sub(SfMarkerShuffle *self, PyObject *arg) { INPLACE_SUB }; static PyObject * SfMarkerShuffle_div(SfMarkerShuffle *self, PyObject *arg) { DIV }; static PyObject * SfMarkerShuffle_inplace_div(SfMarkerShuffle *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef SfMarkerShuffle_members[] = { {"server", T_OBJECT_EX, offsetof(SfMarkerShuffle, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SfMarkerShuffle, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(SfMarkerShuffle, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(SfMarkerShuffle, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef SfMarkerShuffle_methods[] = { {"getServer", (PyCFunction)SfMarkerShuffle_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SfMarkerShuffle_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SfMarkerShuffle_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)SfMarkerShuffle_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)SfMarkerShuffle_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)SfMarkerShuffle_setMul, METH_O, "Sets SfMarkerShuffle mul factor."}, {"setAdd", (PyCFunction)SfMarkerShuffle_setAdd, METH_O, "Sets SfMarkerShuffle add factor."}, {"setSub", (PyCFunction)SfMarkerShuffle_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)SfMarkerShuffle_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods SfMarkerShuffle_as_number = { (binaryfunc)SfMarkerShuffle_add, /*nb_add*/ (binaryfunc)SfMarkerShuffle_sub, /*nb_subtract*/ (binaryfunc)SfMarkerShuffle_multiply, /*nb_multiply*/ (binaryfunc)SfMarkerShuffle_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)SfMarkerShuffle_inplace_add, /*inplace_add*/ (binaryfunc)SfMarkerShuffle_inplace_sub, /*inplace_subtract*/ (binaryfunc)SfMarkerShuffle_inplace_multiply, /*inplace_multiply*/ (binaryfunc)SfMarkerShuffle_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SfMarkerShuffleType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SfMarkerShuffle_base", /*tp_name*/ sizeof(SfMarkerShuffle), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SfMarkerShuffle_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &SfMarkerShuffle_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SfMarkerShuffle objects. Reads a channel from a soundfile directly from disk.", /* tp_doc */ (traverseproc)SfMarkerShuffle_traverse, /* tp_traverse */ (inquiry)SfMarkerShuffle_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SfMarkerShuffle_methods, /* tp_methods */ SfMarkerShuffle_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SfMarkerShuffle_new, /* tp_new */ }; /************************************************************************************************/ /* SfMarkerLooper object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD PyObject *speed; Stream *speed_stream; PyObject *mark; Stream *mark_stream; int modebuffer[2]; SNDFILE *sf; SF_INFO info; char *path; int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */ int sndSize; /* number of frames */ int sndChnls; int sndSr; MYFLT srScale; MYFLT startPos; MYFLT endPos; MYFLT nextStartPos; MYFLT nextEndPos; double pointerPos; MYFLT *samplesBuffer; MYFLT *markers; int markers_size; int old_mark; int lastDir; MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int); } SfMarkerLooper; /*** PROTOTYPES ***/ static void SfMarkerLooper_chooseNewMark(SfMarkerLooper *self, int dir); /******************/ static void SfMarkerLooper_readframes_i(SfMarkerLooper *self) { MYFLT sp, frac, bufpos, delta, tmp; int i, j, totlen, buflen, shortbuflen, bufindex; sf_count_t index; if (self->modebuffer[0] == 0) sp = PyFloat_AS_DOUBLE(self->speed); else sp = Stream_getData((Stream *)self->speed_stream)[0]; delta = MYFABS(sp) * self->srScale; buflen = (int)(self->bufsize * delta + 0.5) + 64; totlen = self->sndChnls*buflen; MYFLT buffer[totlen]; MYFLT buffer2[self->sndChnls][buflen]; if (sp > 0) { /* reading forward */ if (self->startPos == -1 || self->lastDir == 0) { self->lastDir = 1; SfMarkerLooper_chooseNewMark((SfMarkerLooper *)self, 1); self->pointerPos = self->startPos; } if (self->lastDir != 1) { tmp = self->startPos; self->startPos = self->endPos; self->endPos = tmp; self->lastDir = 1; } index = (int)self->pointerPos; sf_seek(self->sf, index, SEEK_SET); /* sets position pointer in the file */ /* fill a buffer with enough samples to satisfy speed reading */ /* if not enough samples to read in the file */ if ((index+buflen) > self->endPos) { shortbuflen = self->endPos - index; SF_READ(self->sf, buffer, shortbuflen*self->sndChnls); /* wrap around and read new samples if loop */ int pad = buflen - shortbuflen; int padlen = pad*self->sndChnls; MYFLT buftemp[padlen]; sf_seek(self->sf, (int)self->nextStartPos, SEEK_SET); SF_READ(self->sf, buftemp, padlen); for (i=0; i<(padlen); i++) { buffer[i+shortbuflen*self->sndChnls] = buftemp[i]; } } else /* without zero padding */ SF_READ(self->sf, buffer, totlen); /* de-interleave samples */ for (i=0; isndChnls][(int)(i/self->sndChnls)] = buffer[i]; } /* fill data with samples */ for (i=0; ibufsize; i++) { bufpos = self->pointerPos - index; bufindex = (int)bufpos; frac = bufpos - bufindex; for (j=0; jsndChnls; j++) { self->samplesBuffer[i+(j*self->bufsize)] = (*self->interp_func_ptr)(buffer2[j], bufindex, frac, buflen); } self->pointerPos += delta; } if (self->pointerPos >= self->endPos) { MYFLT off = self->pointerPos - self->endPos; SfMarkerLooper_chooseNewMark((SfMarkerLooper *)self, 1); self->pointerPos = self->startPos + off; } } else if (sp < 0) { /* reading backward */ if (self->startPos == -1 || self->lastDir != -1) { self->lastDir = self->startPos = -1; SfMarkerLooper_chooseNewMark((SfMarkerLooper *)self, 0); self->pointerPos = self->startPos; } index = (int)self->pointerPos + 1; /* fill a buffer with enough samples to satisfy speed reading */ /* if not enough samples to read in the file */ if ((index-buflen) < self->endPos) { shortbuflen = index - self->endPos; int pad = buflen - shortbuflen; int padlen = pad*self->sndChnls; /* wrap around and read new samples if loop */ MYFLT buftemp[padlen]; sf_seek(self->sf, (int)self->nextStartPos-pad, SEEK_SET); SF_READ(self->sf, buftemp, padlen); for (i=0; isndChnls]; sf_seek(self->sf, self->endPos, SEEK_SET); /* sets position pointer in the file */ SF_READ(self->sf, buftemp2, shortbuflen*self->sndChnls); for (i=0; i<(shortbuflen*self->sndChnls); i++) { buffer[i+padlen] = buftemp2[i]; } } else { /* without zero padding */ sf_seek(self->sf, index-buflen, SEEK_SET); /* sets position pointer in the file */ SF_READ(self->sf, buffer, totlen); } /* de-interleave samples */ for (i=0; isndChnls][(int)(i/self->sndChnls)] = buffer[i]; } /* reverse arrays */ MYFLT swap; for (i=0; isndChnls; i++) { int a; int b = buflen; for (a=0; a<--b; a++) { //increment a and decrement b until they meet eachother swap = buffer2[i][a]; //put what's in a into swap space buffer2[i][a] = buffer2[i][b]; //put what's in b into a buffer2[i][b] = swap; //put what's in the swap (a) into b } } /* fill stream buffer with samples */ for (i=0; ibufsize; i++) { bufpos = index - self->pointerPos; bufindex = (int)bufpos; frac = bufpos - bufindex; for (j=0; jsndChnls; j++) { self->samplesBuffer[i+(j*self->bufsize)] = (*self->interp_func_ptr)(buffer2[j], bufindex, frac, buflen); } self->pointerPos -= delta; } if (self->pointerPos <= self->endPos) { MYFLT off = self->endPos - self->pointerPos; SfMarkerLooper_chooseNewMark((SfMarkerLooper *)self, 0); self->pointerPos = self->startPos - off; } } else { /* speed == 0 */ self->lastDir = 0; for (i = 0; i < (self->bufsize*self->sndChnls); i++) { self->samplesBuffer[i] = 0.0; } } } static void SfMarkerLooper_setProcMode(SfMarkerLooper *self) { self->proc_func_ptr = SfMarkerLooper_readframes_i; } static void SfMarkerLooper_compute_next_data_frame(SfMarkerLooper *self) { (*self->proc_func_ptr)(self); } static void SfMarkerLooper_chooseNewMark(SfMarkerLooper *self, int dir) { int mark; if (self->modebuffer[1] == 0) mark = (int)(PyFloat_AS_DOUBLE(self->mark)); else mark = (int)(Stream_getData((Stream *)self->mark_stream)[0]); if (mark < 0 || mark >= self->markers_size) { mark = self->markers_size / 2; } self->old_mark = mark; if (dir == 1) { if (self->startPos == -1) { self->startPos = self->markers[mark] * self->srScale; self->endPos = self->markers[mark+1] * self->srScale; } else { self->startPos = self->nextStartPos; self->endPos = self->nextEndPos; } self->nextStartPos = self->markers[mark] * self->srScale; self->nextEndPos = self->markers[mark+1] * self->srScale; } else { mark = self->markers_size - mark; if (self->startPos == -1) { self->startPos = self->markers[mark] * self->srScale; self->endPos = self->markers[mark-1] * self->srScale; } else { self->startPos = self->nextStartPos; self->endPos = self->nextEndPos; } self->nextStartPos = self->markers[mark] * self->srScale; self->nextEndPos = self->markers[mark-1] * self->srScale; } } static void SfMarkerLooper_setMarkers(SfMarkerLooper *self, PyObject *markerstmp) { Py_ssize_t i; Py_ssize_t len = PyList_Size(markerstmp); self->markers = (MYFLT *)realloc(self->markers, (len + 2) * sizeof(MYFLT)); self->markers[0] = 0.; for (i=0; imarkers[i+1] = PyFloat_AsDouble(PyList_GetItem(markerstmp, i)); } self->markers[len+1] = self->sndSize; self->markers_size = (int)len+1; } static int SfMarkerLooper_traverse(SfMarkerLooper *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->speed); Py_VISIT(self->speed_stream); Py_VISIT(self->mark); Py_VISIT(self->mark_stream); return 0; } static int SfMarkerLooper_clear(SfMarkerLooper *self) { pyo_CLEAR Py_CLEAR(self->speed); Py_CLEAR(self->speed_stream); Py_CLEAR(self->mark); Py_CLEAR(self->mark_stream); return 0; } static void SfMarkerLooper_dealloc(SfMarkerLooper* self) { pyo_DEALLOC if (self->sf != NULL) sf_close(self->sf); free(self->samplesBuffer); free(self->markers); SfMarkerLooper_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SfMarkerLooper_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *speedtmp=NULL, *marktmp=NULL, *markerstmp=NULL; SfMarkerLooper *self; self = (SfMarkerLooper *)type->tp_alloc(type, 0); self->speed = PyFloat_FromDouble(1); self->mark = PyFloat_FromDouble(0); self->interp = 2; self->startPos = -1; self->endPos = -1; self->old_mark = -1; self->lastDir = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, SfMarkerLooper_compute_next_data_frame); self->mode_func_ptr = SfMarkerLooper_setProcMode; static char *kwlist[] = {"path", "markers", "speed", "mark", "interp", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "sO|OOi", kwlist, &self->path, &markerstmp, &speedtmp, &marktmp, &self->interp)) Py_RETURN_NONE; if (speedtmp) { PyObject_CallMethod((PyObject *)self, "setSpeed", "O", speedtmp); } if (marktmp) { PyObject_CallMethod((PyObject *)self, "setMark", "O", marktmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); if (self->interp == 0) self->interp = 2; if (self->interp == 1) self->interp_func_ptr = nointerp; else if (self->interp == 2) self->interp_func_ptr = linear; else if (self->interp == 3) self->interp_func_ptr = cosine; else if (self->interp == 4) self->interp_func_ptr = cubic; /* Open the sound file. */ self->info.format = 0; self->sf = sf_open(self->path, SFM_READ, &self->info); if (self->sf == NULL) { printf("Failed to open the file.\n"); Py_RETURN_NONE; } self->sndSize = self->info.frames; self->sndSr = self->info.samplerate; self->sndChnls = self->info.channels; self->srScale = self->sndSr / self->sr; Py_INCREF(markerstmp); SfMarkerLooper_setMarkers((SfMarkerLooper *)self, markerstmp); self->samplesBuffer = (MYFLT *)realloc(self->samplesBuffer, self->bufsize * self->sndChnls * sizeof(MYFLT)); Server_generateSeed((Server *)self->server, SFMARKERLOOPER_ID); return (PyObject *)self; } static PyObject * SfMarkerLooper_getServer(SfMarkerLooper* self) { GET_SERVER }; static PyObject * SfMarkerLooper_getStream(SfMarkerLooper* self) { GET_STREAM }; static PyObject * SfMarkerLooper_play(SfMarkerLooper *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SfMarkerLooper_out(SfMarkerLooper *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * SfMarkerLooper_stop(SfMarkerLooper *self) { STOP }; static PyObject * SfMarkerLooper_setSpeed(SfMarkerLooper *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->speed); if (isNumber == 1) { self->speed = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->speed = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->speed, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->speed_stream); self->speed_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * SfMarkerLooper_setMark(SfMarkerLooper *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->mark); if (isNumber == 1) { self->mark = PyNumber_Float(tmp); self->modebuffer[1] = 0; } else { self->mark = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->mark, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->mark_stream); self->mark_stream = (Stream *)streamtmp; self->modebuffer[1] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * SfMarkerLooper_setInterp(SfMarkerLooper *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->interp = PyInt_AsLong(PyNumber_Int(arg)); } if (self->interp == 0) self->interp = 2; if (self->interp == 1) self->interp_func_ptr = nointerp; else if (self->interp == 2) self->interp_func_ptr = linear; else if (self->interp == 3) self->interp_func_ptr = cosine; else if (self->interp == 4) self->interp_func_ptr = cubic; Py_INCREF(Py_None); return Py_None; } MYFLT * SfMarkerLooper_getSamplesBuffer(SfMarkerLooper *self) { return (MYFLT *)self->samplesBuffer; } static PyMemberDef SfMarkerLooper_members[] = { {"server", T_OBJECT_EX, offsetof(SfMarkerLooper, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SfMarkerLooper, stream), 0, "Stream object."}, {"speed", T_OBJECT_EX, offsetof(SfMarkerLooper, speed), 0, "Frequency in cycle per second."}, {"mark", T_OBJECT_EX, offsetof(SfMarkerLooper, mark), 0, "Marker to loop."}, {NULL} /* Sentinel */ }; static PyMethodDef SfMarkerLooper_methods[] = { {"getServer", (PyCFunction)SfMarkerLooper_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SfMarkerLooper_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SfMarkerLooper_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)SfMarkerLooper_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)SfMarkerLooper_stop, METH_NOARGS, "Stops computing."}, {"setSpeed", (PyCFunction)SfMarkerLooper_setSpeed, METH_O, "Sets sfplayer reading speed."}, {"setMark", (PyCFunction)SfMarkerLooper_setMark, METH_O, "Sets marker to loop."}, {"setInterp", (PyCFunction)SfMarkerLooper_setInterp, METH_O, "Sets sfplayer interpolation mode."}, {NULL} /* Sentinel */ }; PyTypeObject SfMarkerLooperType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SfMarkerLooper_base", /*tp_name*/ sizeof(SfMarkerLooper), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SfMarkerLooper_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SfMarkerLooper objects. Shuffle an AIFF soundfile from markers points.", /* tp_doc */ (traverseproc)SfMarkerLooper_traverse, /* tp_traverse */ (inquiry)SfMarkerLooper_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SfMarkerLooper_methods, /* tp_methods */ SfMarkerLooper_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SfMarkerLooper_new, /* tp_new */ }; /************************************************************************************************/ /* SfMarkerLoop streamer object per channel */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD SfMarkerLooper *mainPlayer; int modebuffer[2]; int chnl; } SfMarkerLoop; static void SfMarkerLoop_postprocessing_ii(SfMarkerLoop *self) { POST_PROCESSING_II }; static void SfMarkerLoop_postprocessing_ai(SfMarkerLoop *self) { POST_PROCESSING_AI }; static void SfMarkerLoop_postprocessing_ia(SfMarkerLoop *self) { POST_PROCESSING_IA }; static void SfMarkerLoop_postprocessing_aa(SfMarkerLoop *self) { POST_PROCESSING_AA }; static void SfMarkerLoop_postprocessing_ireva(SfMarkerLoop *self) { POST_PROCESSING_IREVA }; static void SfMarkerLoop_postprocessing_areva(SfMarkerLoop *self) { POST_PROCESSING_AREVA }; static void SfMarkerLoop_postprocessing_revai(SfMarkerLoop *self) { POST_PROCESSING_REVAI }; static void SfMarkerLoop_postprocessing_revaa(SfMarkerLoop *self) { POST_PROCESSING_REVAA }; static void SfMarkerLoop_postprocessing_revareva(SfMarkerLoop *self) { POST_PROCESSING_REVAREVA }; static void SfMarkerLoop_setProcMode(SfMarkerLoop *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = SfMarkerLoop_postprocessing_ii; break; case 1: self->muladd_func_ptr = SfMarkerLoop_postprocessing_ai; break; case 2: self->muladd_func_ptr = SfMarkerLoop_postprocessing_revai; break; case 10: self->muladd_func_ptr = SfMarkerLoop_postprocessing_ia; break; case 11: self->muladd_func_ptr = SfMarkerLoop_postprocessing_aa; break; case 12: self->muladd_func_ptr = SfMarkerLoop_postprocessing_revaa; break; case 20: self->muladd_func_ptr = SfMarkerLoop_postprocessing_ireva; break; case 21: self->muladd_func_ptr = SfMarkerLoop_postprocessing_areva; break; case 22: self->muladd_func_ptr = SfMarkerLoop_postprocessing_revareva; break; } } static void SfMarkerLoop_compute_next_data_frame(SfMarkerLoop *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = SfMarkerLooper_getSamplesBuffer((SfMarkerLooper *)self->mainPlayer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int SfMarkerLoop_traverse(SfMarkerLoop *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainPlayer); return 0; } static int SfMarkerLoop_clear(SfMarkerLoop *self) { pyo_CLEAR Py_CLEAR(self->mainPlayer); return 0; } static void SfMarkerLoop_dealloc(SfMarkerLoop* self) { pyo_DEALLOC SfMarkerLoop_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SfMarkerLoop_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; SfMarkerLoop *self; self = (SfMarkerLoop *)type->tp_alloc(type, 0); self->chnl = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, SfMarkerLoop_compute_next_data_frame); self->mode_func_ptr = SfMarkerLoop_setProcMode; static char *kwlist[] = {"mainPlayer", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainPlayer); Py_INCREF(maintmp); self->mainPlayer = (SfMarkerLooper *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * SfMarkerLoop_getServer(SfMarkerLoop* self) { GET_SERVER }; static PyObject * SfMarkerLoop_getStream(SfMarkerLoop* self) { GET_STREAM }; static PyObject * SfMarkerLoop_setMul(SfMarkerLoop *self, PyObject *arg) { SET_MUL }; static PyObject * SfMarkerLoop_setAdd(SfMarkerLoop *self, PyObject *arg) { SET_ADD }; static PyObject * SfMarkerLoop_setSub(SfMarkerLoop *self, PyObject *arg) { SET_SUB }; static PyObject * SfMarkerLoop_setDiv(SfMarkerLoop *self, PyObject *arg) { SET_DIV }; static PyObject * SfMarkerLoop_play(SfMarkerLoop *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SfMarkerLoop_out(SfMarkerLoop *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * SfMarkerLoop_stop(SfMarkerLoop *self) { STOP }; static PyObject * SfMarkerLoop_multiply(SfMarkerLoop *self, PyObject *arg) { MULTIPLY }; static PyObject * SfMarkerLoop_inplace_multiply(SfMarkerLoop *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * SfMarkerLoop_add(SfMarkerLoop *self, PyObject *arg) { ADD }; static PyObject * SfMarkerLoop_inplace_add(SfMarkerLoop *self, PyObject *arg) { INPLACE_ADD }; static PyObject * SfMarkerLoop_sub(SfMarkerLoop *self, PyObject *arg) { SUB }; static PyObject * SfMarkerLoop_inplace_sub(SfMarkerLoop *self, PyObject *arg) { INPLACE_SUB }; static PyObject * SfMarkerLoop_div(SfMarkerLoop *self, PyObject *arg) { DIV }; static PyObject * SfMarkerLoop_inplace_div(SfMarkerLoop *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef SfMarkerLoop_members[] = { {"server", T_OBJECT_EX, offsetof(SfMarkerLoop, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SfMarkerLoop, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(SfMarkerLoop, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(SfMarkerLoop, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef SfMarkerLoop_methods[] = { {"getServer", (PyCFunction)SfMarkerLoop_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SfMarkerLoop_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SfMarkerLoop_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)SfMarkerLoop_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)SfMarkerLoop_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)SfMarkerLoop_setMul, METH_O, "Sets SfMarkerLoop mul factor."}, {"setAdd", (PyCFunction)SfMarkerLoop_setAdd, METH_O, "Sets SfMarkerLoop add factor."}, {"setSub", (PyCFunction)SfMarkerLoop_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)SfMarkerLoop_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods SfMarkerLoop_as_number = { (binaryfunc)SfMarkerLoop_add, /*nb_add*/ (binaryfunc)SfMarkerLoop_sub, /*nb_subtract*/ (binaryfunc)SfMarkerLoop_multiply, /*nb_multiply*/ (binaryfunc)SfMarkerLoop_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)SfMarkerLoop_inplace_add, /*inplace_add*/ (binaryfunc)SfMarkerLoop_inplace_sub, /*inplace_subtract*/ (binaryfunc)SfMarkerLoop_inplace_multiply, /*inplace_multiply*/ (binaryfunc)SfMarkerLoop_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SfMarkerLoopType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SfMarkerLoop_base", /*tp_name*/ sizeof(SfMarkerLoop), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SfMarkerLoop_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &SfMarkerLoop_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SfMarkerLoop objects. Reads a channel from a soundfile directly from disk.", /* tp_doc */ (traverseproc)SfMarkerLoop_traverse, /* tp_traverse */ (inquiry)SfMarkerLoop_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SfMarkerLoop_methods, /* tp_methods */ SfMarkerLoop_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SfMarkerLoop_new, /* tp_new */ };pyo/src/objects/trigmodule.c0000644000175000017500000100115712652732202015422 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "tablemodule.h" #include "interpolation.h" typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *max; Stream *max_stream; MYFLT value; int modebuffer[3]; // need at least 2 slots for mul & add } TrigRandInt; static void TrigRandInt_generate_i(TrigRandInt *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT ma = PyFloat_AS_DOUBLE(self->max); for (i=0; ibufsize; i++) { if (in[i] == 1) self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma)); self->data[i] = self->value; } } static void TrigRandInt_generate_a(TrigRandInt *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *ma = Stream_getData((Stream *)self->max_stream); for (i=0; ibufsize; i++) { if (in[i] == 1) self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma[i])); self->data[i] = self->value; } } static void TrigRandInt_postprocessing_ii(TrigRandInt *self) { POST_PROCESSING_II }; static void TrigRandInt_postprocessing_ai(TrigRandInt *self) { POST_PROCESSING_AI }; static void TrigRandInt_postprocessing_ia(TrigRandInt *self) { POST_PROCESSING_IA }; static void TrigRandInt_postprocessing_aa(TrigRandInt *self) { POST_PROCESSING_AA }; static void TrigRandInt_postprocessing_ireva(TrigRandInt *self) { POST_PROCESSING_IREVA }; static void TrigRandInt_postprocessing_areva(TrigRandInt *self) { POST_PROCESSING_AREVA }; static void TrigRandInt_postprocessing_revai(TrigRandInt *self) { POST_PROCESSING_REVAI }; static void TrigRandInt_postprocessing_revaa(TrigRandInt *self) { POST_PROCESSING_REVAA }; static void TrigRandInt_postprocessing_revareva(TrigRandInt *self) { POST_PROCESSING_REVAREVA }; static void TrigRandInt_setProcMode(TrigRandInt *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = TrigRandInt_generate_i; break; case 1: self->proc_func_ptr = TrigRandInt_generate_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = TrigRandInt_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigRandInt_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigRandInt_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigRandInt_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigRandInt_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigRandInt_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigRandInt_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigRandInt_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigRandInt_postprocessing_revareva; break; } } static void TrigRandInt_compute_next_data_frame(TrigRandInt *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int TrigRandInt_traverse(TrigRandInt *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->max); Py_VISIT(self->max_stream); return 0; } static int TrigRandInt_clear(TrigRandInt *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->max); Py_CLEAR(self->max_stream); return 0; } static void TrigRandInt_dealloc(TrigRandInt* self) { pyo_DEALLOC TrigRandInt_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigRandInt_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT ma; PyObject *inputtmp, *input_streamtmp, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL; TrigRandInt *self; self = (TrigRandInt *)type->tp_alloc(type, 0); self->max = PyFloat_FromDouble(100.); self->value = 0.; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigRandInt_compute_next_data_frame); self->mode_func_ptr = TrigRandInt_setProcMode; static char *kwlist[] = {"input", "max", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &maxtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (maxtmp) { PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Server_generateSeed((Server *)self->server, TRIGRANDINT_ID); if (self->modebuffer[2] == 0) ma = PyFloat_AsDouble(self->max); else ma = Stream_getData((Stream *)self->max_stream)[0]; self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma)); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigRandInt_getServer(TrigRandInt* self) { GET_SERVER }; static PyObject * TrigRandInt_getStream(TrigRandInt* self) { GET_STREAM }; static PyObject * TrigRandInt_setMul(TrigRandInt *self, PyObject *arg) { SET_MUL }; static PyObject * TrigRandInt_setAdd(TrigRandInt *self, PyObject *arg) { SET_ADD }; static PyObject * TrigRandInt_setSub(TrigRandInt *self, PyObject *arg) { SET_SUB }; static PyObject * TrigRandInt_setDiv(TrigRandInt *self, PyObject *arg) { SET_DIV }; static PyObject * TrigRandInt_play(TrigRandInt *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigRandInt_out(TrigRandInt *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrigRandInt_stop(TrigRandInt *self) { STOP }; static PyObject * TrigRandInt_multiply(TrigRandInt *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigRandInt_inplace_multiply(TrigRandInt *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigRandInt_add(TrigRandInt *self, PyObject *arg) { ADD }; static PyObject * TrigRandInt_inplace_add(TrigRandInt *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigRandInt_sub(TrigRandInt *self, PyObject *arg) { SUB }; static PyObject * TrigRandInt_inplace_sub(TrigRandInt *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigRandInt_div(TrigRandInt *self, PyObject *arg) { DIV }; static PyObject * TrigRandInt_inplace_div(TrigRandInt *self, PyObject *arg) { INPLACE_DIV }; static PyObject * TrigRandInt_setMax(TrigRandInt *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->max); if (isNumber == 1) { self->max = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->max = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->max_stream); self->max_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef TrigRandInt_members[] = { {"server", T_OBJECT_EX, offsetof(TrigRandInt, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigRandInt, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(TrigRandInt, input), 0, "Input sound object."}, {"max", T_OBJECT_EX, offsetof(TrigRandInt, max), 0, "Maximum possible value."}, {"mul", T_OBJECT_EX, offsetof(TrigRandInt, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigRandInt, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigRandInt_methods[] = { {"getServer", (PyCFunction)TrigRandInt_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigRandInt_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigRandInt_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrigRandInt_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrigRandInt_stop, METH_NOARGS, "Stops computing."}, {"setMax", (PyCFunction)TrigRandInt_setMax, METH_O, "Sets maximum possible value."}, {"setMul", (PyCFunction)TrigRandInt_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TrigRandInt_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TrigRandInt_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigRandInt_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigRandInt_as_number = { (binaryfunc)TrigRandInt_add, /*nb_add*/ (binaryfunc)TrigRandInt_sub, /*nb_subtract*/ (binaryfunc)TrigRandInt_multiply, /*nb_multiply*/ (binaryfunc)TrigRandInt_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigRandInt_inplace_add, /*inplace_add*/ (binaryfunc)TrigRandInt_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigRandInt_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigRandInt_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigRandIntType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigRandInt_base", /*tp_name*/ sizeof(TrigRandInt), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigRandInt_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigRandInt_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigRandInt objects. Generates a new random integer value on a trigger signal.", /* tp_doc */ (traverseproc)TrigRandInt_traverse, /* tp_traverse */ (inquiry)TrigRandInt_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigRandInt_methods, /* tp_methods */ TrigRandInt_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigRandInt_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *min; PyObject *max; Stream *min_stream; Stream *max_stream; MYFLT value; MYFLT currentValue; MYFLT time; int timeStep; MYFLT stepVal; int timeCount; int modebuffer[4]; // need at least 2 slots for mul & add } TrigRand; static void TrigRand_generate_ii(TrigRand *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT ma = PyFloat_AS_DOUBLE(self->max); MYFLT range = ma - mi; for (i=0; ibufsize; i++) { if (in[i] == 1) { self->timeCount = 0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; if (self->time <= 0.0) self->currentValue = self->value; else self->stepVal = (self->value - self->currentValue) / self->timeStep; } if (self->timeCount == (self->timeStep - 1)) { self->currentValue = self->value; self->timeCount++; } else if (self->timeCount < self->timeStep) { self->currentValue += self->stepVal; self->timeCount++; } self->data[i] = self->currentValue; } } static void TrigRand_generate_ai(TrigRand *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT ma = PyFloat_AS_DOUBLE(self->max); for (i=0; ibufsize; i++) { MYFLT range = ma - mi[i]; if (in[i] == 1) { self->timeCount = 0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i]; if (self->time <= 0.0) self->currentValue = self->value; else self->stepVal = (self->value - self->currentValue) / self->timeStep; } if (self->timeCount == (self->timeStep - 1)) { self->currentValue = self->value; self->timeCount++; } else if (self->timeCount < self->timeStep) { self->currentValue += self->stepVal; self->timeCount++; } self->data[i] = self->currentValue; } } static void TrigRand_generate_ia(TrigRand *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT *ma = Stream_getData((Stream *)self->max_stream); for (i=0; ibufsize; i++) { MYFLT range = ma[i] - mi; if (in[i] == 1) { self->timeCount = 0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi; if (self->time <= 0.0) self->currentValue = self->value; else self->stepVal = (self->value - self->currentValue) / self->timeStep; } if (self->timeCount == (self->timeStep - 1)) { self->currentValue = self->value; self->timeCount++; } else if (self->timeCount < self->timeStep) { self->currentValue += self->stepVal; self->timeCount++; } self->data[i] = self->currentValue; } } static void TrigRand_generate_aa(TrigRand *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT *ma = Stream_getData((Stream *)self->max_stream); for (i=0; ibufsize; i++) { MYFLT range = ma[i] - mi[i]; if (in[i] == 1) { self->timeCount = 0; self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i]; if (self->time <= 0.0) self->currentValue = self->value; else self->stepVal = (self->value - self->currentValue) / self->timeStep; } if (self->timeCount == (self->timeStep - 1)) { self->currentValue = self->value; self->timeCount++; } else if (self->timeCount < self->timeStep) { self->currentValue += self->stepVal; self->timeCount++; } self->data[i] = self->currentValue; } } static void TrigRand_postprocessing_ii(TrigRand *self) { POST_PROCESSING_II }; static void TrigRand_postprocessing_ai(TrigRand *self) { POST_PROCESSING_AI }; static void TrigRand_postprocessing_ia(TrigRand *self) { POST_PROCESSING_IA }; static void TrigRand_postprocessing_aa(TrigRand *self) { POST_PROCESSING_AA }; static void TrigRand_postprocessing_ireva(TrigRand *self) { POST_PROCESSING_IREVA }; static void TrigRand_postprocessing_areva(TrigRand *self) { POST_PROCESSING_AREVA }; static void TrigRand_postprocessing_revai(TrigRand *self) { POST_PROCESSING_REVAI }; static void TrigRand_postprocessing_revaa(TrigRand *self) { POST_PROCESSING_REVAA }; static void TrigRand_postprocessing_revareva(TrigRand *self) { POST_PROCESSING_REVAREVA }; static void TrigRand_setProcMode(TrigRand *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = TrigRand_generate_ii; break; case 1: self->proc_func_ptr = TrigRand_generate_ai; break; case 10: self->proc_func_ptr = TrigRand_generate_ia; break; case 11: self->proc_func_ptr = TrigRand_generate_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = TrigRand_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigRand_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigRand_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigRand_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigRand_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigRand_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigRand_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigRand_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigRand_postprocessing_revareva; break; } } static void TrigRand_compute_next_data_frame(TrigRand *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int TrigRand_traverse(TrigRand *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->min); Py_VISIT(self->min_stream); Py_VISIT(self->max); Py_VISIT(self->max_stream); return 0; } static int TrigRand_clear(TrigRand *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->min); Py_CLEAR(self->min_stream); Py_CLEAR(self->max); Py_CLEAR(self->max_stream); return 0; } static void TrigRand_dealloc(TrigRand* self) { pyo_DEALLOC TrigRand_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigRand_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT inittmp = 0.0; PyObject *inputtmp, *input_streamtmp, *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL; TrigRand *self; self = (TrigRand *)type->tp_alloc(type, 0); self->min = PyFloat_FromDouble(0.); self->max = PyFloat_FromDouble(1.); self->value = self->currentValue = 0.; self->time = 0.0; self->timeCount = 0; self->stepVal = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigRand_compute_next_data_frame); self->mode_func_ptr = TrigRand_setProcMode; static char *kwlist[] = {"input", "min", "max", "port", "init", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOFFOO, kwlist, &inputtmp, &mintmp, &maxtmp, &self->time, &inittmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (mintmp) { PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp); } if (maxtmp) { PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Server_generateSeed((Server *)self->server, TRIGRAND_ID); self->value = self->currentValue = inittmp; self->timeStep = (int)(self->time * self->sr); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigRand_getServer(TrigRand* self) { GET_SERVER }; static PyObject * TrigRand_getStream(TrigRand* self) { GET_STREAM }; static PyObject * TrigRand_setMul(TrigRand *self, PyObject *arg) { SET_MUL }; static PyObject * TrigRand_setAdd(TrigRand *self, PyObject *arg) { SET_ADD }; static PyObject * TrigRand_setSub(TrigRand *self, PyObject *arg) { SET_SUB }; static PyObject * TrigRand_setDiv(TrigRand *self, PyObject *arg) { SET_DIV }; static PyObject * TrigRand_play(TrigRand *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigRand_out(TrigRand *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrigRand_stop(TrigRand *self) { STOP }; static PyObject * TrigRand_multiply(TrigRand *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigRand_inplace_multiply(TrigRand *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigRand_add(TrigRand *self, PyObject *arg) { ADD }; static PyObject * TrigRand_inplace_add(TrigRand *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigRand_sub(TrigRand *self, PyObject *arg) { SUB }; static PyObject * TrigRand_inplace_sub(TrigRand *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigRand_div(TrigRand *self, PyObject *arg) { DIV }; static PyObject * TrigRand_inplace_div(TrigRand *self, PyObject *arg) { INPLACE_DIV }; static PyObject * TrigRand_setMin(TrigRand *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->min); if (isNumber == 1) { self->min = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->min = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->min, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->min_stream); self->min_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * TrigRand_setMax(TrigRand *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->max); if (isNumber == 1) { self->max = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->max = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->max_stream); self->max_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * TrigRand_setPort(TrigRand *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); if (isNumber == 1) { self->time = PyFloat_AsDouble(tmp); self->timeStep = (int)(self->time * self->sr); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef TrigRand_members[] = { {"server", T_OBJECT_EX, offsetof(TrigRand, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigRand, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(TrigRand, input), 0, "Input sound object."}, {"min", T_OBJECT_EX, offsetof(TrigRand, min), 0, "Minimum possible value."}, {"max", T_OBJECT_EX, offsetof(TrigRand, max), 0, "Maximum possible value."}, {"mul", T_OBJECT_EX, offsetof(TrigRand, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigRand, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigRand_methods[] = { {"getServer", (PyCFunction)TrigRand_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigRand_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigRand_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrigRand_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrigRand_stop, METH_NOARGS, "Stops computing."}, {"setMin", (PyCFunction)TrigRand_setMin, METH_O, "Sets minimum possible value."}, {"setMax", (PyCFunction)TrigRand_setMax, METH_O, "Sets maximum possible value."}, {"setPort", (PyCFunction)TrigRand_setPort, METH_O, "Sets a new ramp time value."}, {"setMul", (PyCFunction)TrigRand_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TrigRand_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TrigRand_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigRand_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigRand_as_number = { (binaryfunc)TrigRand_add, /*nb_add*/ (binaryfunc)TrigRand_sub, /*nb_subtract*/ (binaryfunc)TrigRand_multiply, /*nb_multiply*/ (binaryfunc)TrigRand_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigRand_inplace_add, /*inplace_add*/ (binaryfunc)TrigRand_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigRand_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigRand_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigRandType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigRand_base", /*tp_name*/ sizeof(TrigRand), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigRand_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigRand_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigRand objects. Generates a new random value on a trigger signal.", /* tp_doc */ (traverseproc)TrigRand_traverse, /* tp_traverse */ (inquiry)TrigRand_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigRand_methods, /* tp_methods */ TrigRand_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigRand_new, /* tp_new */ }; /*********************************************************************************************/ /* TrigChoice ********************************************************************************/ /*********************************************************************************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int chSize; MYFLT *choice; MYFLT value; MYFLT currentValue; MYFLT time; int timeStep; MYFLT stepVal; int timeCount; int modebuffer[2]; // need at least 2 slots for mul & add } TrigChoice; static void TrigChoice_generate(TrigChoice *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { if (in[i] == 1) { self->timeCount = 0; self->value = self->choice[(int)((rand()/((MYFLT)(RAND_MAX))) * self->chSize)]; if (self->time <= 0.0) self->currentValue = self->value; else self->stepVal = (self->value - self->currentValue) / self->timeStep; } if (self->timeCount == (self->timeStep - 1)) { self->currentValue = self->value; self->timeCount++; } else if (self->timeCount < self->timeStep) { self->currentValue += self->stepVal; self->timeCount++; } self->data[i] = self->currentValue; } } static void TrigChoice_postprocessing_ii(TrigChoice *self) { POST_PROCESSING_II }; static void TrigChoice_postprocessing_ai(TrigChoice *self) { POST_PROCESSING_AI }; static void TrigChoice_postprocessing_ia(TrigChoice *self) { POST_PROCESSING_IA }; static void TrigChoice_postprocessing_aa(TrigChoice *self) { POST_PROCESSING_AA }; static void TrigChoice_postprocessing_ireva(TrigChoice *self) { POST_PROCESSING_IREVA }; static void TrigChoice_postprocessing_areva(TrigChoice *self) { POST_PROCESSING_AREVA }; static void TrigChoice_postprocessing_revai(TrigChoice *self) { POST_PROCESSING_REVAI }; static void TrigChoice_postprocessing_revaa(TrigChoice *self) { POST_PROCESSING_REVAA }; static void TrigChoice_postprocessing_revareva(TrigChoice *self) { POST_PROCESSING_REVAREVA }; static void TrigChoice_setProcMode(TrigChoice *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = TrigChoice_generate; switch (muladdmode) { case 0: self->muladd_func_ptr = TrigChoice_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigChoice_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigChoice_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigChoice_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigChoice_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigChoice_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigChoice_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigChoice_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigChoice_postprocessing_revareva; break; } } static void TrigChoice_compute_next_data_frame(TrigChoice *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int TrigChoice_traverse(TrigChoice *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int TrigChoice_clear(TrigChoice *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void TrigChoice_dealloc(TrigChoice* self) { pyo_DEALLOC free(self->choice); TrigChoice_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigChoice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT inittmp = 0.0; PyObject *inputtmp, *input_streamtmp, *choicetmp=NULL, *multmp=NULL, *addtmp=NULL; TrigChoice *self; self = (TrigChoice *)type->tp_alloc(type, 0); self->value = self->currentValue = 0.; self->time = 0.0; self->timeCount = 0; self->stepVal = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigChoice_compute_next_data_frame); self->mode_func_ptr = TrigChoice_setProcMode; static char *kwlist[] = {"input", "choice", "port", "init", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_FFOO, kwlist, &inputtmp, &choicetmp, &self->time, &inittmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (choicetmp) { PyObject_CallMethod((PyObject *)self, "setChoice", "O", choicetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Server_generateSeed((Server *)self->server, TRIGCHOICE_ID); self->value = self->currentValue = inittmp; self->timeStep = (int)(self->time * self->sr); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigChoice_getServer(TrigChoice* self) { GET_SERVER }; static PyObject * TrigChoice_getStream(TrigChoice* self) { GET_STREAM }; static PyObject * TrigChoice_setMul(TrigChoice *self, PyObject *arg) { SET_MUL }; static PyObject * TrigChoice_setAdd(TrigChoice *self, PyObject *arg) { SET_ADD }; static PyObject * TrigChoice_setSub(TrigChoice *self, PyObject *arg) { SET_SUB }; static PyObject * TrigChoice_setDiv(TrigChoice *self, PyObject *arg) { SET_DIV }; static PyObject * TrigChoice_play(TrigChoice *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigChoice_out(TrigChoice *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrigChoice_stop(TrigChoice *self) { STOP }; static PyObject * TrigChoice_multiply(TrigChoice *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigChoice_inplace_multiply(TrigChoice *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigChoice_add(TrigChoice *self, PyObject *arg) { ADD }; static PyObject * TrigChoice_inplace_add(TrigChoice *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigChoice_sub(TrigChoice *self, PyObject *arg) { SUB }; static PyObject * TrigChoice_inplace_sub(TrigChoice *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigChoice_div(TrigChoice *self, PyObject *arg) { DIV }; static PyObject * TrigChoice_inplace_div(TrigChoice *self, PyObject *arg) { INPLACE_DIV }; static PyObject * TrigChoice_setChoice(TrigChoice *self, PyObject *arg) { int i; PyObject *tmp; if (! PyList_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The choice attribute must be a list."); Py_INCREF(Py_None); return Py_None; } tmp = arg; self->chSize = PyList_Size(tmp); self->choice = (MYFLT *)realloc(self->choice, self->chSize * sizeof(MYFLT)); for (i=0; ichSize; i++) { self->choice[i] = PyFloat_AsDouble(PyList_GET_ITEM(tmp, i)); } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * TrigChoice_setPort(TrigChoice *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); if (isNumber == 1) { self->time = PyFloat_AsDouble(tmp); self->timeStep = (int)(self->time * self->sr); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef TrigChoice_members[] = { {"server", T_OBJECT_EX, offsetof(TrigChoice, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigChoice, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(TrigChoice, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(TrigChoice, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigChoice, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigChoice_methods[] = { {"getServer", (PyCFunction)TrigChoice_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigChoice_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigChoice_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrigChoice_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrigChoice_stop, METH_NOARGS, "Stops computing."}, {"setChoice", (PyCFunction)TrigChoice_setChoice, METH_O, "Sets possible values."}, {"setPort", (PyCFunction)TrigChoice_setPort, METH_O, "Sets new portamento time."}, {"setMul", (PyCFunction)TrigChoice_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TrigChoice_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TrigChoice_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigChoice_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigChoice_as_number = { (binaryfunc)TrigChoice_add, /*nb_add*/ (binaryfunc)TrigChoice_sub, /*nb_subtract*/ (binaryfunc)TrigChoice_multiply, /*nb_multiply*/ (binaryfunc)TrigChoice_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigChoice_inplace_add, /*inplace_add*/ (binaryfunc)TrigChoice_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigChoice_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigChoice_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigChoiceType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigChoice_base", /*tp_name*/ sizeof(TrigChoice), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigChoice_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigChoice_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigChoice objects. Generates a new random value pick in a user choice on a trigger signal.", /* tp_doc */ (traverseproc)TrigChoice_traverse, /* tp_traverse */ (inquiry)TrigChoice_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigChoice_methods, /* tp_methods */ TrigChoice_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigChoice_new, /* tp_new */ }; /*********************************************************************************************/ /* TrigFunc ********************************************************************************/ /*********************************************************************************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *arg; PyObject *func; } TrigFunc; static void TrigFunc_generate(TrigFunc *self) { int i; PyObject *tuple, *result; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { if (in[i] == 1) { if (self->arg == Py_None) { result = PyObject_Call(self->func, PyTuple_New(0), NULL); if (result == NULL) { PyErr_Print(); return; } } else { tuple = PyTuple_New(1); PyTuple_SET_ITEM(tuple, 0, self->arg); result = PyObject_Call(self->func, tuple, NULL); if (result == NULL) { PyErr_Print(); return; } } } } } static void TrigFunc_compute_next_data_frame(TrigFunc *self) { TrigFunc_generate(self); } static int TrigFunc_traverse(TrigFunc *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->func); Py_VISIT(self->arg); return 0; } static int TrigFunc_clear(TrigFunc *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->func); Py_CLEAR(self->arg); return 0; } static void TrigFunc_dealloc(TrigFunc* self) { pyo_DEALLOC TrigFunc_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigFunc_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *functmp=NULL, *argtmp=NULL; TrigFunc *self; self = (TrigFunc *)type->tp_alloc(type, 0); self->arg = Py_None; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigFunc_compute_next_data_frame); static char *kwlist[] = {"input", "function", "arg", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, &inputtmp, &functmp, &argtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (functmp) { PyObject_CallMethod((PyObject *)self, "setFunction", "O", functmp); } if (argtmp) { PyObject_CallMethod((PyObject *)self, "setArg", "O", argtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); return (PyObject *)self; } static PyObject * TrigFunc_getServer(TrigFunc* self) { GET_SERVER }; static PyObject * TrigFunc_getStream(TrigFunc* self) { GET_STREAM }; static PyObject * TrigFunc_play(TrigFunc *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigFunc_stop(TrigFunc *self) { STOP }; static PyObject * TrigFunc_setFunction(TrigFunc *self, PyObject *arg) { PyObject *tmp; if (! PyCallable_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The function attribute must be callable."); Py_INCREF(Py_None); return Py_None; } tmp = arg; Py_XDECREF(self->func); Py_INCREF(tmp); self->func = tmp; Py_INCREF(Py_None); return Py_None; } static PyObject * TrigFunc_setArg(TrigFunc *self, PyObject *arg) { PyObject *tmp; tmp = arg; Py_XDECREF(self->arg); Py_INCREF(tmp); self->arg = tmp; Py_INCREF(Py_None); return Py_None; } static PyMemberDef TrigFunc_members[] = { {"server", T_OBJECT_EX, offsetof(TrigFunc, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigFunc, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(TrigFunc, input), 0, "Input sound object."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigFunc_methods[] = { {"getServer", (PyCFunction)TrigFunc_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigFunc_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigFunc_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)TrigFunc_stop, METH_NOARGS, "Stops computing."}, {"setFunction", (PyCFunction)TrigFunc_setFunction, METH_O, "Sets function to be called."}, {"setArg", (PyCFunction)TrigFunc_setArg, METH_O, "Sets function's argument."}, {NULL} /* Sentinel */ }; PyTypeObject TrigFuncType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigFunc_base", /*tp_name*/ sizeof(TrigFunc), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigFunc_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigFunc objects. Called a function on a trigger signal.", /* tp_doc */ (traverseproc)TrigFunc_traverse, /* tp_traverse */ (inquiry)TrigFunc_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigFunc_methods, /* tp_methods */ TrigFunc_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigFunc_new, /* tp_new */ }; /*********************************************************************************************/ /* TrigEnv *********************************************************************************/ /*********************************************************************************************/ typedef struct { pyo_audio_HEAD PyObject *table; PyObject *input; Stream *input_stream; PyObject *dur; Stream *dur_stream; int modebuffer[3]; int active; MYFLT current_dur; // duration in samples MYFLT inc; // table size / current_dur double pointerPos; // reading position in sample MYFLT *trigsBuffer; TriggerStream *trig_stream; int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */ MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int); } TrigEnv; static void TrigEnv_readframes_i(TrigEnv *self) { MYFLT fpart; int i, ipart; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; if (in[i] == 1) { MYFLT dur = PyFloat_AS_DOUBLE(self->dur); self->current_dur = self->sr * dur; if (self->current_dur <= 0.0) { self->current_dur = 0.0; self->inc = 0.0; self->active = 0; } else { self->inc = (MYFLT)size / self->current_dur; self->active = 1; } self->pointerPos = 0.; } if (self->active == 1) { ipart = (int)self->pointerPos; fpart = self->pointerPos - ipart; self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); self->pointerPos += self->inc; } else self->data[i] = 0.; if (self->pointerPos > size && self->active == 1) { self->trigsBuffer[i] = 1.0; self->active = 0; } } } static void TrigEnv_readframes_a(TrigEnv *self) { MYFLT fpart, dur; int i, ipart; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *dur_st = Stream_getData((Stream *)self->dur_stream); MYFLT *tablelist = TableStream_getData(self->table); int size = TableStream_getSize(self->table); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; if (in[i] == 1) { dur = dur_st[i]; self->current_dur = self->sr * dur; if (self->current_dur <= 0.0) { self->current_dur = 0.0; self->inc = 0.0; self->active = 0; } else { self->inc = (MYFLT)size / self->current_dur; self->active = 1; } self->pointerPos = 0.; } if (self->active == 1) { ipart = (int)self->pointerPos; fpart = self->pointerPos - ipart; self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size); self->pointerPos += self->inc; } else self->data[i] = 0.; if (self->pointerPos > size && self->active == 1) { self->trigsBuffer[i] = 1.0; self->active = 0; } } } static void TrigEnv_postprocessing_ii(TrigEnv *self) { POST_PROCESSING_II }; static void TrigEnv_postprocessing_ai(TrigEnv *self) { POST_PROCESSING_AI }; static void TrigEnv_postprocessing_ia(TrigEnv *self) { POST_PROCESSING_IA }; static void TrigEnv_postprocessing_aa(TrigEnv *self) { POST_PROCESSING_AA }; static void TrigEnv_postprocessing_ireva(TrigEnv *self) { POST_PROCESSING_IREVA }; static void TrigEnv_postprocessing_areva(TrigEnv *self) { POST_PROCESSING_AREVA }; static void TrigEnv_postprocessing_revai(TrigEnv *self) { POST_PROCESSING_REVAI }; static void TrigEnv_postprocessing_revaa(TrigEnv *self) { POST_PROCESSING_REVAA }; static void TrigEnv_postprocessing_revareva(TrigEnv *self) { POST_PROCESSING_REVAREVA }; static void TrigEnv_setProcMode(TrigEnv *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = TrigEnv_readframes_i; break; case 1: self->proc_func_ptr = TrigEnv_readframes_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = TrigEnv_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigEnv_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigEnv_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigEnv_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigEnv_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigEnv_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigEnv_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigEnv_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigEnv_postprocessing_revareva; break; } } static void TrigEnv_compute_next_data_frame(TrigEnv *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int TrigEnv_traverse(TrigEnv *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->table); Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->dur); Py_VISIT(self->dur_stream); Py_VISIT(self->trig_stream); return 0; } static int TrigEnv_clear(TrigEnv *self) { pyo_CLEAR Py_CLEAR(self->table); Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->dur); Py_CLEAR(self->dur_stream); Py_CLEAR(self->trig_stream); return 0; } static void TrigEnv_dealloc(TrigEnv* self) { pyo_DEALLOC free(self->trigsBuffer); TrigEnv_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigEnv_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *tabletmp, *durtmp=NULL, *multmp=NULL, *addtmp=NULL; TrigEnv *self; self = (TrigEnv *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->pointerPos = 0.; self->active = 0; self->interp = 2; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigEnv_compute_next_data_frame); self->mode_func_ptr = TrigEnv_setProcMode; self->dur = PyFloat_FromDouble(1.); self->current_dur = self->sr; static char *kwlist[] = {"input", "table", "dur", "interp", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OiOO", kwlist, &inputtmp, &tabletmp, &durtmp, &self->interp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) { PyErr_SetString(PyExc_TypeError, "\"table\" argument of TrigEnv must be a PyoTableObject.\n"); Py_RETURN_NONE; } Py_XDECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); if (durtmp) { PyObject_CallMethod((PyObject *)self, "setDur", "O", durtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); (*self->mode_func_ptr)(self); SET_INTERP_POINTER return (PyObject *)self; } static PyObject * TrigEnv_getServer(TrigEnv* self) { GET_SERVER }; static PyObject * TrigEnv_getStream(TrigEnv* self) { GET_STREAM }; static PyObject * TrigEnv_getTriggerStream(TrigEnv* self) { GET_TRIGGER_STREAM }; static PyObject * TrigEnv_setMul(TrigEnv *self, PyObject *arg) { SET_MUL }; static PyObject * TrigEnv_setAdd(TrigEnv *self, PyObject *arg) { SET_ADD }; static PyObject * TrigEnv_setSub(TrigEnv *self, PyObject *arg) { SET_SUB }; static PyObject * TrigEnv_setDiv(TrigEnv *self, PyObject *arg) { SET_DIV }; static PyObject * TrigEnv_play(TrigEnv *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigEnv_out(TrigEnv *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrigEnv_stop(TrigEnv *self) { STOP }; static PyObject * TrigEnv_multiply(TrigEnv *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigEnv_inplace_multiply(TrigEnv *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigEnv_add(TrigEnv *self, PyObject *arg) { ADD }; static PyObject * TrigEnv_inplace_add(TrigEnv *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigEnv_sub(TrigEnv *self, PyObject *arg) { SUB }; static PyObject * TrigEnv_inplace_sub(TrigEnv *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigEnv_div(TrigEnv *self, PyObject *arg) { DIV }; static PyObject * TrigEnv_inplace_div(TrigEnv *self, PyObject *arg) { INPLACE_DIV }; static PyObject * TrigEnv_getTable(TrigEnv* self) { Py_INCREF(self->table); return self->table; }; static PyObject * TrigEnv_setTable(TrigEnv *self, PyObject *arg) { PyObject *tmp; ASSERT_ARG_NOT_NULL tmp = arg; Py_DECREF(self->table); self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", ""); Py_INCREF(Py_None); return Py_None; } static PyObject * TrigEnv_setDur(TrigEnv *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->dur); if (isNumber == 1) { self->dur = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->dur = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->dur, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->dur_stream); self->dur_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * TrigEnv_setInterp(TrigEnv *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->interp = PyInt_AsLong(PyNumber_Int(arg)); } SET_INTERP_POINTER Py_INCREF(Py_None); return Py_None; } static PyMemberDef TrigEnv_members[] = { {"server", T_OBJECT_EX, offsetof(TrigEnv, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigEnv, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(TrigEnv, trig_stream), 0, "Trigger Stream object."}, {"table", T_OBJECT_EX, offsetof(TrigEnv, table), 0, "Envelope table."}, {"dur", T_OBJECT_EX, offsetof(TrigEnv, dur), 0, "Envelope duration in seconds."}, {"mul", T_OBJECT_EX, offsetof(TrigEnv, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigEnv, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigEnv_methods[] = { {"getTable", (PyCFunction)TrigEnv_getTable, METH_NOARGS, "Returns waveform table object."}, {"getServer", (PyCFunction)TrigEnv_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigEnv_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)TrigEnv_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"play", (PyCFunction)TrigEnv_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrigEnv_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrigEnv_stop, METH_NOARGS, "Stops computing."}, {"setTable", (PyCFunction)TrigEnv_setTable, METH_O, "Sets envelope table."}, {"setDur", (PyCFunction)TrigEnv_setDur, METH_O, "Sets envelope duration in second."}, {"setInterp", (PyCFunction)TrigEnv_setInterp, METH_O, "Sets oscillator interpolation mode."}, {"setMul", (PyCFunction)TrigEnv_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)TrigEnv_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)TrigEnv_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigEnv_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigEnv_as_number = { (binaryfunc)TrigEnv_add, /*nb_add*/ (binaryfunc)TrigEnv_sub, /*nb_subtract*/ (binaryfunc)TrigEnv_multiply, /*nb_multiply*/ (binaryfunc)TrigEnv_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigEnv_inplace_add, /*inplace_add*/ (binaryfunc)TrigEnv_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigEnv_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigEnv_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigEnvType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigEnv_base", /*tp_name*/ sizeof(TrigEnv), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigEnv_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigEnv_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigEnv objects. Starts an envelope on a trigger signal.", /* tp_doc */ (traverseproc)TrigEnv_traverse, /* tp_traverse */ (inquiry)TrigEnv_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigEnv_methods, /* tp_methods */ TrigEnv_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigEnv_new, /* tp_new */ }; /*********************************************************************************************/ /* TrigLinseg *********************************************************************************/ /*********************************************************************************************/ typedef struct { pyo_audio_HEAD PyObject *pointslist; PyObject *input; Stream *input_stream; int modebuffer[2]; double currentTime; double currentValue; MYFLT sampleToSec; double increment; MYFLT *targets; MYFLT *times; int which; int flag; int newlist; int listsize; MYFLT *trigsBuffer; TriggerStream *trig_stream; } TrigLinseg; static void TrigLinseg_convert_pointslist(TrigLinseg *self) { int i; PyObject *tup; self->listsize = PyList_Size(self->pointslist); self->targets = (MYFLT *)realloc(self->targets, self->listsize * sizeof(MYFLT)); self->times = (MYFLT *)realloc(self->times, self->listsize * sizeof(MYFLT)); for (i=0; ilistsize; i++) { tup = PyList_GET_ITEM(self->pointslist, i); self->times[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 0)); self->targets[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1)); } } static void TrigLinseg_reinit(TrigLinseg *self) { if (self->newlist == 1) { TrigLinseg_convert_pointslist((TrigLinseg *)self); self->newlist = 0; } self->currentTime = 0.0; self->currentValue = self->targets[0]; self->which = 0; self->flag = 1; } static void TrigLinseg_generate(TrigLinseg *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; if (in[i] == 1) TrigLinseg_reinit((TrigLinseg *)self); if (self->flag == 1) { if (self->currentTime >= self->times[self->which]) { self->which++; if (self->which == self->listsize) { self->trigsBuffer[i] = 1.0; self->flag = 0; self->currentValue = self->targets[self->which-1]; } else if ((self->times[self->which] - self->times[self->which-1]) <= 0) self->increment = self->targets[self->which] - self->currentValue; else self->increment = (self->targets[self->which] - self->targets[self->which-1]) / ((self->times[self->which] - self->times[self->which-1]) / self->sampleToSec); } if (self->currentTime <= self->times[self->listsize-1]) self->currentValue += self->increment; self->data[i] = (MYFLT)self->currentValue; self->currentTime += self->sampleToSec; } else self->data[i] = (MYFLT)self->currentValue; } } static void TrigLinseg_postprocessing_ii(TrigLinseg *self) { POST_PROCESSING_II }; static void TrigLinseg_postprocessing_ai(TrigLinseg *self) { POST_PROCESSING_AI }; static void TrigLinseg_postprocessing_ia(TrigLinseg *self) { POST_PROCESSING_IA }; static void TrigLinseg_postprocessing_aa(TrigLinseg *self) { POST_PROCESSING_AA }; static void TrigLinseg_postprocessing_ireva(TrigLinseg *self) { POST_PROCESSING_IREVA }; static void TrigLinseg_postprocessing_areva(TrigLinseg *self) { POST_PROCESSING_AREVA }; static void TrigLinseg_postprocessing_revai(TrigLinseg *self) { POST_PROCESSING_REVAI }; static void TrigLinseg_postprocessing_revaa(TrigLinseg *self) { POST_PROCESSING_REVAA }; static void TrigLinseg_postprocessing_revareva(TrigLinseg *self) { POST_PROCESSING_REVAREVA }; static void TrigLinseg_setProcMode(TrigLinseg *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = TrigLinseg_generate; switch (muladdmode) { case 0: self->muladd_func_ptr = TrigLinseg_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigLinseg_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigLinseg_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigLinseg_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigLinseg_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigLinseg_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigLinseg_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigLinseg_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigLinseg_postprocessing_revareva; break; } } static void TrigLinseg_compute_next_data_frame(TrigLinseg *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int TrigLinseg_traverse(TrigLinseg *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->pointslist); Py_VISIT(self->trig_stream); Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int TrigLinseg_clear(TrigLinseg *self) { pyo_CLEAR Py_CLEAR(self->pointslist); Py_CLEAR(self->trig_stream); Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void TrigLinseg_dealloc(TrigLinseg* self) { pyo_DEALLOC free(self->targets); free(self->times); free(self->trigsBuffer); TrigLinseg_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigLinseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *pointslist=NULL, *multmp=NULL, *addtmp=NULL; TrigLinseg *self; self = (TrigLinseg *)type->tp_alloc(type, 0); self->newlist = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigLinseg_compute_next_data_frame); self->mode_func_ptr = TrigLinseg_setProcMode; self->sampleToSec = 1. / self->sr; static char *kwlist[] = {"input", "list", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &inputtmp, &pointslist, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_INCREF(pointslist); Py_XDECREF(self->pointslist); self->pointslist = pointslist; TrigLinseg_convert_pointslist((TrigLinseg *)self); if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigLinseg_getServer(TrigLinseg* self) { GET_SERVER }; static PyObject * TrigLinseg_getStream(TrigLinseg* self) { GET_STREAM }; static PyObject * TrigLinseg_getTriggerStream(TrigLinseg* self) { GET_TRIGGER_STREAM }; static PyObject * TrigLinseg_setMul(TrigLinseg *self, PyObject *arg) { SET_MUL }; static PyObject * TrigLinseg_setAdd(TrigLinseg *self, PyObject *arg) { SET_ADD }; static PyObject * TrigLinseg_setSub(TrigLinseg *self, PyObject *arg) { SET_SUB }; static PyObject * TrigLinseg_setDiv(TrigLinseg *self, PyObject *arg) { SET_DIV }; static PyObject * TrigLinseg_play(TrigLinseg *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigLinseg_stop(TrigLinseg *self) { STOP }; static PyObject * TrigLinseg_multiply(TrigLinseg *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigLinseg_inplace_multiply(TrigLinseg *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigLinseg_add(TrigLinseg *self, PyObject *arg) { ADD }; static PyObject * TrigLinseg_inplace_add(TrigLinseg *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigLinseg_sub(TrigLinseg *self, PyObject *arg) { SUB }; static PyObject * TrigLinseg_inplace_sub(TrigLinseg *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigLinseg_div(TrigLinseg *self, PyObject *arg) { DIV }; static PyObject * TrigLinseg_inplace_div(TrigLinseg *self, PyObject *arg) { INPLACE_DIV }; static PyObject * TrigLinseg_setList(TrigLinseg *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute."); return PyInt_FromLong(-1); } if (! PyList_Check(value)) { PyErr_SetString(PyExc_TypeError, "The points list attribute value must be a list of tuples."); return PyInt_FromLong(-1); } Py_INCREF(value); Py_DECREF(self->pointslist); self->pointslist = value; self->newlist = 1; Py_INCREF(Py_None); return Py_None; } static PyMemberDef TrigLinseg_members[] = { {"server", T_OBJECT_EX, offsetof(TrigLinseg, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigLinseg, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(TrigLinseg, trig_stream), 0, "Trigger Stream object."}, {"pointslist", T_OBJECT_EX, offsetof(TrigLinseg, pointslist), 0, "List of target points."}, {"mul", T_OBJECT_EX, offsetof(TrigLinseg, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigLinseg, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigLinseg_methods[] = { {"getServer", (PyCFunction)TrigLinseg_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigLinseg_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)TrigLinseg_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"play", (PyCFunction)TrigLinseg_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)TrigLinseg_stop, METH_NOARGS, "Starts fadeout and stops computing."}, {"setList", (PyCFunction)TrigLinseg_setList, METH_O, "Sets target points list."}, {"setMul", (PyCFunction)TrigLinseg_setMul, METH_O, "Sets TrigLinseg mul factor."}, {"setAdd", (PyCFunction)TrigLinseg_setAdd, METH_O, "Sets TrigLinseg add factor."}, {"setSub", (PyCFunction)TrigLinseg_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigLinseg_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigLinseg_as_number = { (binaryfunc)TrigLinseg_add, /*nb_add*/ (binaryfunc)TrigLinseg_sub, /*nb_subtract*/ (binaryfunc)TrigLinseg_multiply, /*nb_multiply*/ (binaryfunc)TrigLinseg_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigLinseg_inplace_add, /*inplace_add*/ (binaryfunc)TrigLinseg_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigLinseg_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigLinseg_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigLinsegType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigLinseg_base", /*tp_name*/ sizeof(TrigLinseg), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigLinseg_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigLinseg_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigLinseg objects. Generates a linear segments break-points line.", /* tp_doc */ (traverseproc)TrigLinseg_traverse, /* tp_traverse */ (inquiry)TrigLinseg_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigLinseg_methods, /* tp_methods */ TrigLinseg_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigLinseg_new, /* tp_new */ }; /*********************************************************************************************/ /* TrigExpseg *********************************************************************************/ /*********************************************************************************************/ typedef struct { pyo_audio_HEAD PyObject *pointslist; PyObject *input; Stream *input_stream; int modebuffer[2]; double currentTime; double currentValue; MYFLT sampleToSec; double inc; double pointer; MYFLT range; double steps; MYFLT *targets; MYFLT *times; int which; int flag; int newlist; int listsize; double exp; double exp_tmp; int inverse; int inverse_tmp; MYFLT *trigsBuffer; TriggerStream *trig_stream; } TrigExpseg; static void TrigExpseg_convert_pointslist(TrigExpseg *self) { int i; PyObject *tup; self->listsize = PyList_Size(self->pointslist); self->targets = (MYFLT *)realloc(self->targets, self->listsize * sizeof(MYFLT)); self->times = (MYFLT *)realloc(self->times, self->listsize * sizeof(MYFLT)); for (i=0; ilistsize; i++) { tup = PyList_GET_ITEM(self->pointslist, i); self->times[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 0)); self->targets[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1)); } } static void TrigExpseg_reinit(TrigExpseg *self) { if (self->newlist == 1) { TrigExpseg_convert_pointslist((TrigExpseg *)self); self->newlist = 0; } self->currentTime = 0.0; self->currentValue = self->targets[0]; self->which = 0; self->flag = 1; self->exp = self->exp_tmp; self->inverse = self->inverse_tmp; } static void TrigExpseg_generate(TrigExpseg *self) { int i; MYFLT scl; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; if (in[i] == 1) TrigExpseg_reinit((TrigExpseg *)self); if (self->flag == 1) { if (self->currentTime >= self->times[self->which]) { self->which++; if (self->which == self->listsize) { self->trigsBuffer[i] = 1.0; self->flag = 0; self->currentValue = self->targets[self->which-1]; } else { self->range = self->targets[self->which] - self->targets[self->which-1]; self->steps = (self->times[self->which] - self->times[self->which-1]) * self->sr; if (self->steps <= 0) self->inc = 1.0; else self->inc = 1.0 / self->steps; self->pointer = 0.0; } } if (self->currentTime <= self->times[self->listsize-1]) { if (self->pointer >= 1.0) self->pointer = 1.0; if (self->inverse == 1 && self->range < 0.0) scl = 1.0 - MYPOW(1.0 - self->pointer, self->exp); else scl = MYPOW(self->pointer, self->exp); self->currentValue = scl * self->range + self->targets[self->which-1]; self->pointer += self->inc; } self->data[i] = (MYFLT)self->currentValue; self->currentTime += self->sampleToSec; } else self->data[i] = (MYFLT)self->currentValue; } } static void TrigExpseg_postprocessing_ii(TrigExpseg *self) { POST_PROCESSING_II }; static void TrigExpseg_postprocessing_ai(TrigExpseg *self) { POST_PROCESSING_AI }; static void TrigExpseg_postprocessing_ia(TrigExpseg *self) { POST_PROCESSING_IA }; static void TrigExpseg_postprocessing_aa(TrigExpseg *self) { POST_PROCESSING_AA }; static void TrigExpseg_postprocessing_ireva(TrigExpseg *self) { POST_PROCESSING_IREVA }; static void TrigExpseg_postprocessing_areva(TrigExpseg *self) { POST_PROCESSING_AREVA }; static void TrigExpseg_postprocessing_revai(TrigExpseg *self) { POST_PROCESSING_REVAI }; static void TrigExpseg_postprocessing_revaa(TrigExpseg *self) { POST_PROCESSING_REVAA }; static void TrigExpseg_postprocessing_revareva(TrigExpseg *self) { POST_PROCESSING_REVAREVA }; static void TrigExpseg_setProcMode(TrigExpseg *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = TrigExpseg_generate; switch (muladdmode) { case 0: self->muladd_func_ptr = TrigExpseg_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigExpseg_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigExpseg_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigExpseg_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigExpseg_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigExpseg_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigExpseg_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigExpseg_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigExpseg_postprocessing_revareva; break; } } static void TrigExpseg_compute_next_data_frame(TrigExpseg *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int TrigExpseg_traverse(TrigExpseg *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->pointslist); Py_VISIT(self->trig_stream); Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int TrigExpseg_clear(TrigExpseg *self) { pyo_CLEAR Py_CLEAR(self->pointslist); Py_CLEAR(self->trig_stream); Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void TrigExpseg_dealloc(TrigExpseg* self) { pyo_DEALLOC free(self->targets); free(self->times); free(self->trigsBuffer); TrigExpseg_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigExpseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *pointslist=NULL, *multmp=NULL, *addtmp=NULL; TrigExpseg *self; self = (TrigExpseg *)type->tp_alloc(type, 0); self->newlist = 1; self->exp = self->exp_tmp = 10; self->inverse = self->inverse_tmp = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigExpseg_compute_next_data_frame); self->mode_func_ptr = TrigExpseg_setProcMode; self->sampleToSec = 1. / self->sr; static char *kwlist[] = {"input", "list", "exp", "inverse", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|diOO", kwlist, &inputtmp, &pointslist, &self->exp_tmp, &self->inverse_tmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_INCREF(pointslist); Py_XDECREF(self->pointslist); self->pointslist = pointslist; TrigExpseg_convert_pointslist((TrigExpseg *)self); if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT)); for (i=0; ibufsize; i++) { self->trigsBuffer[i] = 0.0; } MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL); TriggerStream_setData(self->trig_stream, self->trigsBuffer); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigExpseg_getServer(TrigExpseg* self) { GET_SERVER }; static PyObject * TrigExpseg_getStream(TrigExpseg* self) { GET_STREAM }; static PyObject * TrigExpseg_getTriggerStream(TrigExpseg* self) { GET_TRIGGER_STREAM }; static PyObject * TrigExpseg_setMul(TrigExpseg *self, PyObject *arg) { SET_MUL }; static PyObject * TrigExpseg_setAdd(TrigExpseg *self, PyObject *arg) { SET_ADD }; static PyObject * TrigExpseg_setSub(TrigExpseg *self, PyObject *arg) { SET_SUB }; static PyObject * TrigExpseg_setDiv(TrigExpseg *self, PyObject *arg) { SET_DIV }; static PyObject * TrigExpseg_play(TrigExpseg *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigExpseg_stop(TrigExpseg *self) { STOP }; static PyObject * TrigExpseg_multiply(TrigExpseg *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigExpseg_inplace_multiply(TrigExpseg *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigExpseg_add(TrigExpseg *self, PyObject *arg) { ADD }; static PyObject * TrigExpseg_inplace_add(TrigExpseg *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigExpseg_sub(TrigExpseg *self, PyObject *arg) { SUB }; static PyObject * TrigExpseg_inplace_sub(TrigExpseg *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigExpseg_div(TrigExpseg *self, PyObject *arg) { DIV }; static PyObject * TrigExpseg_inplace_div(TrigExpseg *self, PyObject *arg) { INPLACE_DIV }; static PyObject * TrigExpseg_setList(TrigExpseg *self, PyObject *value) { if (value == NULL) { PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute."); return PyInt_FromLong(-1); } if (! PyList_Check(value)) { PyErr_SetString(PyExc_TypeError, "The points list attribute value must be a list of tuples."); return PyInt_FromLong(-1); } Py_INCREF(value); Py_DECREF(self->pointslist); self->pointslist = value; self->newlist = 1; Py_INCREF(Py_None); return Py_None; } static PyObject * TrigExpseg_setExp(TrigExpseg *self, PyObject *arg) { ASSERT_ARG_NOT_NULL // TODO: PyNumber_Check() self->exp_tmp = PyFloat_AsDouble(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * TrigExpseg_setInverse(TrigExpseg *self, PyObject *arg) { ASSERT_ARG_NOT_NULL self->inverse_tmp = PyInt_AsLong(PyNumber_Int(arg)); Py_INCREF(Py_None); return Py_None; } static PyMemberDef TrigExpseg_members[] = { {"server", T_OBJECT_EX, offsetof(TrigExpseg, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigExpseg, stream), 0, "Stream object."}, {"trig_stream", T_OBJECT_EX, offsetof(TrigExpseg, trig_stream), 0, "Trigger Stream object."}, {"pointslist", T_OBJECT_EX, offsetof(TrigExpseg, pointslist), 0, "List of target points."}, {"mul", T_OBJECT_EX, offsetof(TrigExpseg, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigExpseg, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigExpseg_methods[] = { {"getServer", (PyCFunction)TrigExpseg_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigExpseg_getStream, METH_NOARGS, "Returns stream object."}, {"_getTriggerStream", (PyCFunction)TrigExpseg_getTriggerStream, METH_NOARGS, "Returns trigger stream object."}, {"play", (PyCFunction)TrigExpseg_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)TrigExpseg_stop, METH_NOARGS, "Starts fadeout and stops computing."}, {"setList", (PyCFunction)TrigExpseg_setList, METH_O, "Sets target points list."}, {"setExp", (PyCFunction)TrigExpseg_setExp, METH_O, "Sets exponent factor."}, {"setInverse", (PyCFunction)TrigExpseg_setInverse, METH_O, "Sets inverse factor."}, {"setMul", (PyCFunction)TrigExpseg_setMul, METH_O, "Sets TrigExpseg mul factor."}, {"setAdd", (PyCFunction)TrigExpseg_setAdd, METH_O, "Sets TrigExpseg add factor."}, {"setSub", (PyCFunction)TrigExpseg_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigExpseg_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigExpseg_as_number = { (binaryfunc)TrigExpseg_add, /*nb_add*/ (binaryfunc)TrigExpseg_sub, /*nb_subtract*/ (binaryfunc)TrigExpseg_multiply, /*nb_multiply*/ (binaryfunc)TrigExpseg_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigExpseg_inplace_add, /*inplace_add*/ (binaryfunc)TrigExpseg_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigExpseg_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigExpseg_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigExpsegType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigExpseg_base", /*tp_name*/ sizeof(TrigExpseg), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigExpseg_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigExpseg_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigExpseg objects. Generates a linear segments break-points line.", /* tp_doc */ (traverseproc)TrigExpseg_traverse, /* tp_traverse */ (inquiry)TrigExpseg_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigExpseg_methods, /* tp_methods */ TrigExpseg_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigExpseg_new, /* tp_new */ }; /****************/ /**** TrigXnoise *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *x1; PyObject *x2; Stream *x1_stream; Stream *x2_stream; MYFLT (*type_func_ptr)(); MYFLT xx1; MYFLT xx2; int type; MYFLT value; MYFLT lastPoissonX1; int poisson_tab; MYFLT poisson_buffer[2000]; MYFLT walkerValue; MYFLT loop_buffer[15]; int loopChoice; int loopCountPlay; int loopTime; int loopCountRec; int loopLen; int loopStop; int modebuffer[4]; // need at least 2 slots for mul & add } TrigXnoise; // no parameter static MYFLT TrigXnoise_uniform(TrigXnoise *self) { return RANDOM_UNIFORM; } static MYFLT TrigXnoise_linear_min(TrigXnoise *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; if (a < b) return a; else return b; } static MYFLT TrigXnoise_linear_max(TrigXnoise *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; if (a > b) return a; else return b; } static MYFLT TrigXnoise_triangle(TrigXnoise *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; return ((a + b) * 0.5); } // x1 = slope static MYFLT TrigXnoise_expon_min(TrigXnoise *self) { if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT val = -MYLOG(RANDOM_UNIFORM) / self->xx1; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } static MYFLT TrigXnoise_expon_max(TrigXnoise *self) { if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT val = 1.0 - (-MYLOG(RANDOM_UNIFORM) / self->xx1); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = bandwidth static MYFLT TrigXnoise_biexpon(TrigXnoise *self) { MYFLT polar, val; if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT sum = RANDOM_UNIFORM * 2.0; if (sum > 1.0) { polar = -1; sum = 2.0 - sum; } else polar = 1; val = 0.5 * (polar * MYLOG(sum) / self->xx1) + 0.5; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } static MYFLT TrigXnoise_cauchy(TrigXnoise *self) { MYFLT rnd, val, dir; do { rnd = RANDOM_UNIFORM; } while (rnd == 0.5); if (rand() < (RAND_MAX / 2)) dir = -1; else dir = 1; val = 0.5 * (MYTAN(rnd) * self->xx1 * dir) + 0.5; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = locator, x2 = shape static MYFLT TrigXnoise_weibull(TrigXnoise *self) { MYFLT rnd, val; if (self->xx2 <= 0.0) self->xx2 = 0.00001; rnd = 1.0 / (1.0 - RANDOM_UNIFORM); val = self->xx1 * MYPOW(MYLOG(rnd), (1.0 / self->xx2)); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = locator, x2 = bandwidth static MYFLT TrigXnoise_gaussian(TrigXnoise *self) { MYFLT rnd, val; rnd = (RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM); val = (self->xx2 * (rnd - 3.0) * 0.33 + self->xx1); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = gravity center, x2 = compress/expand static MYFLT TrigXnoise_poisson(TrigXnoise *self) { int i, j, factorial; long tot; MYFLT val; if (self->xx1 < 0.1) self->xx1 = 0.1; if (self->xx2 < 0.1) self->xx2 = 0.1; if (self->xx1 != self->lastPoissonX1) { self->lastPoissonX1 = self->xx1; self->poisson_tab = 0; factorial = 1; for (i=1; i<12; i++) { factorial *= i; tot = (long)(1000.0 * (MYPOW(2.7182818, -self->xx1) * MYPOW(self->xx1, i) / factorial)); for (j=0; jpoisson_buffer[self->poisson_tab] = i; self->poisson_tab++; } } } val = self->poisson_buffer[rand() % self->poisson_tab] / 12.0 * self->xx2; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = max value, x2 = max step static MYFLT TrigXnoise_walker(TrigXnoise *self) { int modulo, dir; if (self->xx2 < 0.002) self->xx2 = 0.002; modulo = (int)(self->xx2 * 1000.0); dir = rand() % 2; if (dir == 0) self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001); else self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001); if (self->walkerValue > self->xx1) self->walkerValue = self->xx1; if (self->walkerValue < 0.0) self->walkerValue = 0.0; return self->walkerValue; } // x1 = max value, x2 = max step static MYFLT TrigXnoise_loopseg(TrigXnoise *self) { int modulo, dir; if (self->loopChoice == 0) { self->loopCountPlay = self->loopTime = 0; if (self->xx2 < 0.002) self->xx2 = 0.002; modulo = (int)(self->xx2 * 1000.0); dir = rand() % 2; if (dir == 0) self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001); else self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001); if (self->walkerValue > self->xx1) self->walkerValue = self->xx1; if (self->walkerValue < 0.0) self->walkerValue = 0.0; self->loop_buffer[self->loopCountRec++] = self->walkerValue; if (self->loopCountRec < self->loopLen) self->loopChoice = 0; else { self->loopChoice = 1; self->loopStop = (rand() % 4) + 1; } } else { self->loopCountRec = 0; self->walkerValue = self->loop_buffer[self->loopCountPlay++]; if (self->loopCountPlay < self->loopLen) self->loopChoice = 1; else { self->loopCountPlay = 0; self->loopTime++; } if (self->loopTime == self->loopStop) { self->loopChoice = 0; self->loopLen = (rand() % 10) + 3; } } return self->walkerValue; } static void TrigXnoise_generate_ii(TrigXnoise *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); self->xx1 = PyFloat_AS_DOUBLE(self->x1); self->xx2 = PyFloat_AS_DOUBLE(self->x2); for (i=0; ibufsize; i++) { if (in[i] == 1) self->value = (*self->type_func_ptr)(self); self->data[i] = self->value; } } static void TrigXnoise_generate_ai(TrigXnoise *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *x1 = Stream_getData((Stream *)self->x1_stream); self->xx2 = PyFloat_AS_DOUBLE(self->x2); for (i=0; ibufsize; i++) { if (in[i] == 1) { self->xx1 = x1[i]; self->value = (*self->type_func_ptr)(self); } self->data[i] = self->value; } } static void TrigXnoise_generate_ia(TrigXnoise *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); self->xx1 = PyFloat_AS_DOUBLE(self->x1); MYFLT *x2 = Stream_getData((Stream *)self->x2_stream); for (i=0; ibufsize; i++) { if (in[i] == 1) { self->xx2 = x2[i]; self->value = (*self->type_func_ptr)(self); } self->data[i] = self->value; } } static void TrigXnoise_generate_aa(TrigXnoise *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *x1 = Stream_getData((Stream *)self->x1_stream); MYFLT *x2 = Stream_getData((Stream *)self->x2_stream); for (i=0; ibufsize; i++) { if (in[i] == 1) { self->xx1 = x1[i]; self->xx2 = x2[i]; self->value = (*self->type_func_ptr)(self); } self->data[i] = self->value; } } static void TrigXnoise_postprocessing_ii(TrigXnoise *self) { POST_PROCESSING_II }; static void TrigXnoise_postprocessing_ai(TrigXnoise *self) { POST_PROCESSING_AI }; static void TrigXnoise_postprocessing_ia(TrigXnoise *self) { POST_PROCESSING_IA }; static void TrigXnoise_postprocessing_aa(TrigXnoise *self) { POST_PROCESSING_AA }; static void TrigXnoise_postprocessing_ireva(TrigXnoise *self) { POST_PROCESSING_IREVA }; static void TrigXnoise_postprocessing_areva(TrigXnoise *self) { POST_PROCESSING_AREVA }; static void TrigXnoise_postprocessing_revai(TrigXnoise *self) { POST_PROCESSING_REVAI }; static void TrigXnoise_postprocessing_revaa(TrigXnoise *self) { POST_PROCESSING_REVAA }; static void TrigXnoise_postprocessing_revareva(TrigXnoise *self) { POST_PROCESSING_REVAREVA }; static void TrigXnoise_setRandomType(TrigXnoise *self) { switch (self->type) { case 0: self->type_func_ptr = TrigXnoise_uniform; break; case 1: self->type_func_ptr = TrigXnoise_linear_min; break; case 2: self->type_func_ptr = TrigXnoise_linear_max; break; case 3: self->type_func_ptr = TrigXnoise_triangle; break; case 4: self->type_func_ptr = TrigXnoise_expon_min; break; case 5: self->type_func_ptr = TrigXnoise_expon_max; break; case 6: self->type_func_ptr = TrigXnoise_biexpon; break; case 7: self->type_func_ptr = TrigXnoise_cauchy; break; case 8: self->type_func_ptr = TrigXnoise_weibull; break; case 9: self->type_func_ptr = TrigXnoise_gaussian; break; case 10: self->type_func_ptr = TrigXnoise_poisson; break; case 11: self->type_func_ptr = TrigXnoise_walker; break; case 12: self->type_func_ptr = TrigXnoise_loopseg; break; } } static void TrigXnoise_setProcMode(TrigXnoise *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = TrigXnoise_generate_ii; break; case 1: self->proc_func_ptr = TrigXnoise_generate_ai; break; case 10: self->proc_func_ptr = TrigXnoise_generate_ia; break; case 11: self->proc_func_ptr = TrigXnoise_generate_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = TrigXnoise_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigXnoise_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigXnoise_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigXnoise_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigXnoise_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigXnoise_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigXnoise_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigXnoise_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigXnoise_postprocessing_revareva; break; } } static void TrigXnoise_compute_next_data_frame(TrigXnoise *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int TrigXnoise_traverse(TrigXnoise *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->x1); Py_VISIT(self->x1_stream); Py_VISIT(self->x2); Py_VISIT(self->x2_stream); return 0; } static int TrigXnoise_clear(TrigXnoise *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->x1); Py_CLEAR(self->x1_stream); Py_CLEAR(self->x2); Py_CLEAR(self->x2_stream); return 0; } static void TrigXnoise_dealloc(TrigXnoise* self) { pyo_DEALLOC TrigXnoise_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigXnoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *x1tmp=NULL, *x2tmp=NULL, *multmp=NULL, *addtmp=NULL; TrigXnoise *self; self = (TrigXnoise *)type->tp_alloc(type, 0); self->x1 = PyFloat_FromDouble(0.5); self->x2 = PyFloat_FromDouble(0.5); self->xx1 = self->xx2 = self->walkerValue = 0.5; self->value = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Server_generateSeed((Server *)self->server, TRIGXNOISE_ID); self->poisson_tab = 0; self->lastPoissonX1 = -99.0; for (i=0; i<2000; i++) { self->poisson_buffer[i] = 0.0; } for (i=0; i<15; i++) { self->loop_buffer[i] = 0.0; } self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0; self->loopLen = (rand() % 10) + 3; Stream_setFunctionPtr(self->stream, TrigXnoise_compute_next_data_frame); self->mode_func_ptr = TrigXnoise_setProcMode; static char *kwlist[] = {"input", "type", "x1", "x2", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOOOO", kwlist, &inputtmp, &self->type, &x1tmp, &x2tmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (x1tmp) { PyObject_CallMethod((PyObject *)self, "setX1", "O", x1tmp); } if (x2tmp) { PyObject_CallMethod((PyObject *)self, "setX2", "O", x2tmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); TrigXnoise_setRandomType(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigXnoise_getServer(TrigXnoise* self) { GET_SERVER }; static PyObject * TrigXnoise_getStream(TrigXnoise* self) { GET_STREAM }; static PyObject * TrigXnoise_setMul(TrigXnoise *self, PyObject *arg) { SET_MUL }; static PyObject * TrigXnoise_setAdd(TrigXnoise *self, PyObject *arg) { SET_ADD }; static PyObject * TrigXnoise_setSub(TrigXnoise *self, PyObject *arg) { SET_SUB }; static PyObject * TrigXnoise_setDiv(TrigXnoise *self, PyObject *arg) { SET_DIV }; static PyObject * TrigXnoise_play(TrigXnoise *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigXnoise_out(TrigXnoise *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrigXnoise_stop(TrigXnoise *self) { STOP }; static PyObject * TrigXnoise_multiply(TrigXnoise *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigXnoise_inplace_multiply(TrigXnoise *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigXnoise_add(TrigXnoise *self, PyObject *arg) { ADD }; static PyObject * TrigXnoise_inplace_add(TrigXnoise *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigXnoise_sub(TrigXnoise *self, PyObject *arg) { SUB }; static PyObject * TrigXnoise_inplace_sub(TrigXnoise *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigXnoise_div(TrigXnoise *self, PyObject *arg) { DIV }; static PyObject * TrigXnoise_inplace_div(TrigXnoise *self, PyObject *arg) { INPLACE_DIV }; static PyObject * TrigXnoise_setType(TrigXnoise *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyInt_Check(arg); if (isNumber == 1) { self->type = PyInt_AsLong(arg); TrigXnoise_setRandomType(self); } Py_INCREF(Py_None); return Py_None; } static PyObject * TrigXnoise_setX1(TrigXnoise *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->x1); if (isNumber == 1) { self->x1 = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->x1 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->x1, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->x1_stream); self->x1_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * TrigXnoise_setX2(TrigXnoise *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->x2); if (isNumber == 1) { self->x2 = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->x2 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->x2, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->x2_stream); self->x2_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef TrigXnoise_members[] = { {"server", T_OBJECT_EX, offsetof(TrigXnoise, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigXnoise, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(TrigXnoise, input), 0, "Trigger input."}, {"x1", T_OBJECT_EX, offsetof(TrigXnoise, x1), 0, "first param."}, {"x2", T_OBJECT_EX, offsetof(TrigXnoise, x2), 0, "second param."}, {"mul", T_OBJECT_EX, offsetof(TrigXnoise, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigXnoise, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigXnoise_methods[] = { {"getServer", (PyCFunction)TrigXnoise_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigXnoise_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigXnoise_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrigXnoise_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrigXnoise_stop, METH_NOARGS, "Stops computing."}, {"setType", (PyCFunction)TrigXnoise_setType, METH_O, "Sets distribution type."}, {"setX1", (PyCFunction)TrigXnoise_setX1, METH_O, "Sets first param."}, {"setX2", (PyCFunction)TrigXnoise_setX2, METH_O, "Sets second param."}, {"setMul", (PyCFunction)TrigXnoise_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TrigXnoise_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TrigXnoise_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigXnoise_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigXnoise_as_number = { (binaryfunc)TrigXnoise_add, /*nb_add*/ (binaryfunc)TrigXnoise_sub, /*nb_subtract*/ (binaryfunc)TrigXnoise_multiply, /*nb_multiply*/ (binaryfunc)TrigXnoise_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigXnoise_inplace_add, /*inplace_add*/ (binaryfunc)TrigXnoise_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigXnoise_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigXnoise_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigXnoiseType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigXnoise_base", /*tp_name*/ sizeof(TrigXnoise), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigXnoise_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigXnoise_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigXnoise objects. Periodically generates a new random value.", /* tp_doc */ (traverseproc)TrigXnoise_traverse, /* tp_traverse */ (inquiry)TrigXnoise_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigXnoise_methods, /* tp_methods */ TrigXnoise_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigXnoise_new, /* tp_new */ }; /****************/ /**** TrigXnoiseMidi *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *x1; PyObject *x2; Stream *x1_stream; Stream *x2_stream; MYFLT (*type_func_ptr)(); int scale; // 0 = Midi, 1 = frequency, 2 = transpo int range_min; int range_max; int centralkey; MYFLT xx1; MYFLT xx2; int type; MYFLT value; MYFLT lastPoissonX1; int poisson_tab; MYFLT poisson_buffer[2000]; MYFLT walkerValue; MYFLT loop_buffer[15]; int loopChoice; int loopCountPlay; int loopTime; int loopCountRec; int loopLen; int loopStop; int modebuffer[4]; // need at least 2 slots for mul & add } TrigXnoiseMidi; static MYFLT TrigXnoiseMidi_convert(TrigXnoiseMidi *self) { int midival; MYFLT val; midival = (int)((self->value * (self->range_max-self->range_min)) + self->range_min); if (midival < 0) midival = 0; else if (midival > 127) midival = 127; if (self->scale == 0) val = (MYFLT)midival; else if (self->scale == 1) val = 8.1757989156437 * MYPOW(1.0594630943593, midival); else if (self->scale == 2) val = MYPOW(1.0594630943593, midival - self->centralkey); else val = midival; return val; } // no parameter static MYFLT TrigXnoiseMidi_uniform(TrigXnoiseMidi *self) { return RANDOM_UNIFORM; } static MYFLT TrigXnoiseMidi_linear_min(TrigXnoiseMidi *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; if (a < b) return a; else return b; } static MYFLT TrigXnoiseMidi_linear_max(TrigXnoiseMidi *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; if (a > b) return a; else return b; } static MYFLT TrigXnoiseMidi_triangle(TrigXnoiseMidi *self) { MYFLT a = RANDOM_UNIFORM; MYFLT b = RANDOM_UNIFORM; return ((a + b) * 0.5); } // x1 = slope static MYFLT TrigXnoiseMidi_expon_min(TrigXnoiseMidi *self) { if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT val = -MYLOG10(RANDOM_UNIFORM) / self->xx1; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } static MYFLT TrigXnoiseMidi_expon_max(TrigXnoiseMidi *self) { if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT val = 1.0 - (-MYLOG10(RANDOM_UNIFORM) / self->xx1); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = bandwidth static MYFLT TrigXnoiseMidi_biexpon(TrigXnoiseMidi *self) { MYFLT polar, val; if (self->xx1 <= 0.0) self->xx1 = 0.00001; MYFLT sum = RANDOM_UNIFORM * 2.0; if (sum > 1.0) { polar = -1; sum = 2.0 - sum; } else polar = 1; val = 0.5 * (polar * MYLOG10(sum) / self->xx1) + 0.5; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } static MYFLT TrigXnoiseMidi_cauchy(TrigXnoiseMidi *self) { MYFLT rnd, val, dir; do { rnd = RANDOM_UNIFORM; } while (rnd == 0.5); if (rand() < (RAND_MAX / 2)) dir = -1; else dir = 1; val = 0.5 * (MYTAN(rnd) * self->xx1 * dir) + 0.5; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = locator, x2 = shape static MYFLT TrigXnoiseMidi_weibull(TrigXnoiseMidi *self) { MYFLT rnd, val; if (self->xx2 <= 0.0) self->xx2 = 0.00001; rnd = 1.0 / (1.0 - RANDOM_UNIFORM); val = self->xx1 * MYPOW(MYLOG(rnd), (1.0 / self->xx2)); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = locator, x2 = bandwidth static MYFLT TrigXnoiseMidi_gaussian(TrigXnoiseMidi *self) { MYFLT rnd, val; rnd = (RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM); val = (self->xx2 * (rnd - 3.0) * 0.33 + self->xx1); if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = gravity center, x2 = compress/expand static MYFLT TrigXnoiseMidi_poisson(TrigXnoiseMidi *self) { int i, j, factorial; long tot; MYFLT val; if (self->xx1 < 0.1) self->xx1 = 0.1; if (self->xx2 < 0.1) self->xx2 = 0.1; if (self->xx1 != self->lastPoissonX1) { self->lastPoissonX1 = self->xx1; self->poisson_tab = 0; factorial = 1; for (i=1; i<12; i++) { factorial *= i; tot = (long)(1000.0 * (MYPOW(2.7182818, -self->xx1) * MYPOW(self->xx1, i) / factorial)); for (j=0; jpoisson_buffer[self->poisson_tab] = i; self->poisson_tab++; } } } val = self->poisson_buffer[rand() % self->poisson_tab] / 12.0 * self->xx2; if (val < 0.0) return 0.0; else if (val > 1.0) return 1.0; else return val; } // x1 = max value, x2 = max step static MYFLT TrigXnoiseMidi_walker(TrigXnoiseMidi *self) { int modulo, dir; if (self->xx2 < 0.002) self->xx2 = 0.002; modulo = (int)(self->xx2 * 1000.0); dir = rand() % 2; if (dir == 0) self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001); else self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001); if (self->walkerValue > self->xx1) self->walkerValue = self->xx1; if (self->walkerValue < 0.0) self->walkerValue = 0.0; return self->walkerValue; } // x1 = max value, x2 = max step static MYFLT TrigXnoiseMidi_loopseg(TrigXnoiseMidi *self) { int modulo, dir; if (self->loopChoice == 0) { self->loopCountPlay = self->loopTime = 0; if (self->xx2 < 0.002) self->xx2 = 0.002; modulo = (int)(self->xx2 * 1000.0); dir = rand() % 2; if (dir == 0) self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001); else self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001); if (self->walkerValue > self->xx1) self->walkerValue = self->xx1; if (self->walkerValue < 0.0) self->walkerValue = 0.0; self->loop_buffer[self->loopCountRec++] = self->walkerValue; if (self->loopCountRec < self->loopLen) self->loopChoice = 0; else { self->loopChoice = 1; self->loopStop = (rand() % 4) + 1; } } else { self->loopCountRec = 0; self->walkerValue = self->loop_buffer[self->loopCountPlay++]; if (self->loopCountPlay < self->loopLen) self->loopChoice = 1; else { self->loopCountPlay = 0; self->loopTime++; } if (self->loopTime == self->loopStop) { self->loopChoice = 0; self->loopLen = (rand() % 10) + 3; } } return self->walkerValue; } static void TrigXnoiseMidi_generate_ii(TrigXnoiseMidi *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); self->xx1 = PyFloat_AS_DOUBLE(self->x1); self->xx2 = PyFloat_AS_DOUBLE(self->x2); for (i=0; ibufsize; i++) { if (in[i] == 1) { self->value = (*self->type_func_ptr)(self); self->value = TrigXnoiseMidi_convert(self); } self->data[i] = self->value; } } static void TrigXnoiseMidi_generate_ai(TrigXnoiseMidi *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *x1 = Stream_getData((Stream *)self->x1_stream); self->xx2 = PyFloat_AS_DOUBLE(self->x2); for (i=0; ibufsize; i++) { if (in[i] == 1) { self->xx1 = x1[i]; self->value = (*self->type_func_ptr)(self); self->value = TrigXnoiseMidi_convert(self); } self->data[i] = self->value; } } static void TrigXnoiseMidi_generate_ia(TrigXnoiseMidi *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); self->xx1 = PyFloat_AS_DOUBLE(self->x1); MYFLT *x2 = Stream_getData((Stream *)self->x2_stream); for (i=0; ibufsize; i++) { if (in[i] == 1) { self->xx2 = x2[i]; self->value = (*self->type_func_ptr)(self); self->value = TrigXnoiseMidi_convert(self); } self->data[i] = self->value; } } static void TrigXnoiseMidi_generate_aa(TrigXnoiseMidi *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *x1 = Stream_getData((Stream *)self->x1_stream); MYFLT *x2 = Stream_getData((Stream *)self->x2_stream); for (i=0; ibufsize; i++) { if (in[i] == 1) { self->xx1 = x1[i]; self->xx2 = x2[i]; self->value = (*self->type_func_ptr)(self); self->value = TrigXnoiseMidi_convert(self); } self->data[i] = self->value; } } static void TrigXnoiseMidi_postprocessing_ii(TrigXnoiseMidi *self) { POST_PROCESSING_II }; static void TrigXnoiseMidi_postprocessing_ai(TrigXnoiseMidi *self) { POST_PROCESSING_AI }; static void TrigXnoiseMidi_postprocessing_ia(TrigXnoiseMidi *self) { POST_PROCESSING_IA }; static void TrigXnoiseMidi_postprocessing_aa(TrigXnoiseMidi *self) { POST_PROCESSING_AA }; static void TrigXnoiseMidi_postprocessing_ireva(TrigXnoiseMidi *self) { POST_PROCESSING_IREVA }; static void TrigXnoiseMidi_postprocessing_areva(TrigXnoiseMidi *self) { POST_PROCESSING_AREVA }; static void TrigXnoiseMidi_postprocessing_revai(TrigXnoiseMidi *self) { POST_PROCESSING_REVAI }; static void TrigXnoiseMidi_postprocessing_revaa(TrigXnoiseMidi *self) { POST_PROCESSING_REVAA }; static void TrigXnoiseMidi_postprocessing_revareva(TrigXnoiseMidi *self) { POST_PROCESSING_REVAREVA }; static void TrigXnoiseMidi_setRandomType(TrigXnoiseMidi *self) { switch (self->type) { case 0: self->type_func_ptr = TrigXnoiseMidi_uniform; break; case 1: self->type_func_ptr = TrigXnoiseMidi_linear_min; break; case 2: self->type_func_ptr = TrigXnoiseMidi_linear_max; break; case 3: self->type_func_ptr = TrigXnoiseMidi_triangle; break; case 4: self->type_func_ptr = TrigXnoiseMidi_expon_min; break; case 5: self->type_func_ptr = TrigXnoiseMidi_expon_max; break; case 6: self->type_func_ptr = TrigXnoiseMidi_biexpon; break; case 7: self->type_func_ptr = TrigXnoiseMidi_cauchy; break; case 8: self->type_func_ptr = TrigXnoiseMidi_weibull; break; case 9: self->type_func_ptr = TrigXnoiseMidi_gaussian; break; case 10: self->type_func_ptr = TrigXnoiseMidi_poisson; break; case 11: self->type_func_ptr = TrigXnoiseMidi_walker; break; case 12: self->type_func_ptr = TrigXnoiseMidi_loopseg; break; } } static void TrigXnoiseMidi_setProcMode(TrigXnoiseMidi *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = TrigXnoiseMidi_generate_ii; break; case 1: self->proc_func_ptr = TrigXnoiseMidi_generate_ai; break; case 10: self->proc_func_ptr = TrigXnoiseMidi_generate_ia; break; case 11: self->proc_func_ptr = TrigXnoiseMidi_generate_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_revareva; break; } } static void TrigXnoiseMidi_compute_next_data_frame(TrigXnoiseMidi *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int TrigXnoiseMidi_traverse(TrigXnoiseMidi *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->x1); Py_VISIT(self->x1_stream); Py_VISIT(self->x2); Py_VISIT(self->x2_stream); return 0; } static int TrigXnoiseMidi_clear(TrigXnoiseMidi *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->x1); Py_CLEAR(self->x1_stream); Py_CLEAR(self->x2); Py_CLEAR(self->x2_stream); return 0; } static void TrigXnoiseMidi_dealloc(TrigXnoiseMidi* self) { pyo_DEALLOC TrigXnoiseMidi_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigXnoiseMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *x1tmp=NULL, *x2tmp=NULL, *rangetmp=NULL, *multmp=NULL, *addtmp=NULL; TrigXnoiseMidi *self; self = (TrigXnoiseMidi *)type->tp_alloc(type, 0); self->x1 = PyFloat_FromDouble(0.5); self->x2 = PyFloat_FromDouble(0.5); self->xx1 = self->xx2 = self->walkerValue = 0.5; self->value = 0.0; self->scale = 0; self->range_min = 0; self->range_max = 127; self->centralkey = 64; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Server_generateSeed((Server *)self->server, TRIGXNOISEMIDI_ID); self->poisson_tab = 0; self->lastPoissonX1 = -99.0; for (i=0; i<2000; i++) { self->poisson_buffer[i] = 0.0; } for (i=0; i<15; i++) { self->loop_buffer[i] = 0.0; } self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0; self->loopLen = (rand() % 10) + 3; Stream_setFunctionPtr(self->stream, TrigXnoiseMidi_compute_next_data_frame); self->mode_func_ptr = TrigXnoiseMidi_setProcMode; static char *kwlist[] = {"input", "type", "x1", "x2", "scale", "range", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOOiOOO", kwlist, &inputtmp, &self->type, &x1tmp, &x2tmp, &self->scale, &rangetmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (x1tmp) { PyObject_CallMethod((PyObject *)self, "setX1", "O", x1tmp); } if (x2tmp) { PyObject_CallMethod((PyObject *)self, "setX2", "O", x2tmp); } if (rangetmp) { PyObject_CallMethod((PyObject *)self, "setRange", "O", rangetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); TrigXnoiseMidi_setRandomType(self); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigXnoiseMidi_getServer(TrigXnoiseMidi* self) { GET_SERVER }; static PyObject * TrigXnoiseMidi_getStream(TrigXnoiseMidi* self) { GET_STREAM }; static PyObject * TrigXnoiseMidi_setMul(TrigXnoiseMidi *self, PyObject *arg) { SET_MUL }; static PyObject * TrigXnoiseMidi_setAdd(TrigXnoiseMidi *self, PyObject *arg) { SET_ADD }; static PyObject * TrigXnoiseMidi_setSub(TrigXnoiseMidi *self, PyObject *arg) { SET_SUB }; static PyObject * TrigXnoiseMidi_setDiv(TrigXnoiseMidi *self, PyObject *arg) { SET_DIV }; static PyObject * TrigXnoiseMidi_play(TrigXnoiseMidi *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigXnoiseMidi_out(TrigXnoiseMidi *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrigXnoiseMidi_stop(TrigXnoiseMidi *self) { STOP }; static PyObject * TrigXnoiseMidi_multiply(TrigXnoiseMidi *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigXnoiseMidi_inplace_multiply(TrigXnoiseMidi *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigXnoiseMidi_add(TrigXnoiseMidi *self, PyObject *arg) { ADD }; static PyObject * TrigXnoiseMidi_inplace_add(TrigXnoiseMidi *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigXnoiseMidi_sub(TrigXnoiseMidi *self, PyObject *arg) { SUB }; static PyObject * TrigXnoiseMidi_inplace_sub(TrigXnoiseMidi *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigXnoiseMidi_div(TrigXnoiseMidi *self, PyObject *arg) { DIV }; static PyObject * TrigXnoiseMidi_inplace_div(TrigXnoiseMidi *self, PyObject *arg) { INPLACE_DIV }; static PyObject * TrigXnoiseMidi_setType(TrigXnoiseMidi *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyInt_Check(arg); if (isNumber == 1) { self->type = PyInt_AsLong(arg); TrigXnoiseMidi_setRandomType(self); } Py_INCREF(Py_None); return Py_None; } static PyObject * TrigXnoiseMidi_setScale(TrigXnoiseMidi *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isNumber = PyInt_Check(arg); if (isNumber == 1) { tmp = PyInt_AsLong(arg); if (tmp >= 0 && tmp <= 2) self->scale = tmp; else printf("scale attribute must be an integer {0, 1, 2}\n"); } Py_INCREF(Py_None); return Py_None; } static PyObject * TrigXnoiseMidi_setRange(TrigXnoiseMidi *self, PyObject *args) { if (args == NULL) { Py_INCREF(Py_None); return Py_None; } int isTuple = PyTuple_Check(args); if (isTuple == 1) { self->range_min = PyInt_AsLong(PyTuple_GET_ITEM(args, 0)); self->range_max = PyInt_AsLong(PyTuple_GET_ITEM(args, 1)); self->centralkey = (int)((self->range_max + self->range_min) / 2); } Py_INCREF(Py_None); return Py_None; } static PyObject * TrigXnoiseMidi_setX1(TrigXnoiseMidi *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->x1); if (isNumber == 1) { self->x1 = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->x1 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->x1, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->x1_stream); self->x1_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * TrigXnoiseMidi_setX2(TrigXnoiseMidi *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->x2); if (isNumber == 1) { self->x2 = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->x2 = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->x2, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->x2_stream); self->x2_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef TrigXnoiseMidi_members[] = { {"server", T_OBJECT_EX, offsetof(TrigXnoiseMidi, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigXnoiseMidi, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(TrigXnoiseMidi, input), 0, "Trigger input."}, {"x1", T_OBJECT_EX, offsetof(TrigXnoiseMidi, x1), 0, "first param."}, {"x2", T_OBJECT_EX, offsetof(TrigXnoiseMidi, x2), 0, "second param."}, {"mul", T_OBJECT_EX, offsetof(TrigXnoiseMidi, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigXnoiseMidi, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigXnoiseMidi_methods[] = { {"getServer", (PyCFunction)TrigXnoiseMidi_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigXnoiseMidi_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigXnoiseMidi_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrigXnoiseMidi_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrigXnoiseMidi_stop, METH_NOARGS, "Stops computing."}, {"setType", (PyCFunction)TrigXnoiseMidi_setType, METH_O, "Sets distribution type."}, {"setScale", (PyCFunction)TrigXnoiseMidi_setScale, METH_O, "Sets output scale."}, {"setRange", (PyCFunction)TrigXnoiseMidi_setRange, METH_VARARGS, "Sets range in midi notes (min, max)."}, {"setX1", (PyCFunction)TrigXnoiseMidi_setX1, METH_O, "Sets first param."}, {"setX2", (PyCFunction)TrigXnoiseMidi_setX2, METH_O, "Sets second param."}, {"setMul", (PyCFunction)TrigXnoiseMidi_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TrigXnoiseMidi_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TrigXnoiseMidi_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigXnoiseMidi_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigXnoiseMidi_as_number = { (binaryfunc)TrigXnoiseMidi_add, /*nb_add*/ (binaryfunc)TrigXnoiseMidi_sub, /*nb_subtract*/ (binaryfunc)TrigXnoiseMidi_multiply, /*nb_multiply*/ (binaryfunc)TrigXnoiseMidi_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigXnoiseMidi_inplace_add, /*inplace_add*/ (binaryfunc)TrigXnoiseMidi_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigXnoiseMidi_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigXnoiseMidi_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigXnoiseMidiType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigXnoiseMidi_base", /*tp_name*/ sizeof(TrigXnoiseMidi), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigXnoiseMidi_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigXnoiseMidi_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigXnoiseMidi objects. Periodically generates a new random value.", /* tp_doc */ (traverseproc)TrigXnoiseMidi_traverse, /* tp_traverse */ (inquiry)TrigXnoiseMidi_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigXnoiseMidi_methods, /* tp_methods */ TrigXnoiseMidi_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigXnoiseMidi_new, /* tp_new */ }; /***************************************************/ /******* Counter ***********/ /***************************************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; long tmp; long min; long max; int dir; int direction; MYFLT value; int modebuffer[2]; // need at least 2 slots for mul & add } Counter; static void Counter_generates(Counter *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { if (in[i] == 1) { self->value = (MYFLT)self->tmp; if (self->dir == 0) { self->tmp++; if (self->tmp >= self->max) self->tmp = self->min; } else if (self->dir == 1) { self->tmp--; if (self->tmp < self->min) self->tmp = self->max - 1; } else if (self->dir == 2) { self->tmp = self->tmp + self->direction; if (self->tmp >= self->max) { self->direction = -1; self->tmp = self->max - 2; } if (self->tmp <= self->min) { self->direction = 1; self->tmp = self->min; } } } self->data[i] = self->value; } } static void Counter_postprocessing_ii(Counter *self) { POST_PROCESSING_II }; static void Counter_postprocessing_ai(Counter *self) { POST_PROCESSING_AI }; static void Counter_postprocessing_ia(Counter *self) { POST_PROCESSING_IA }; static void Counter_postprocessing_aa(Counter *self) { POST_PROCESSING_AA }; static void Counter_postprocessing_ireva(Counter *self) { POST_PROCESSING_IREVA }; static void Counter_postprocessing_areva(Counter *self) { POST_PROCESSING_AREVA }; static void Counter_postprocessing_revai(Counter *self) { POST_PROCESSING_REVAI }; static void Counter_postprocessing_revaa(Counter *self) { POST_PROCESSING_REVAA }; static void Counter_postprocessing_revareva(Counter *self) { POST_PROCESSING_REVAREVA }; static void Counter_setProcMode(Counter *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Counter_generates; switch (muladdmode) { case 0: self->muladd_func_ptr = Counter_postprocessing_ii; break; case 1: self->muladd_func_ptr = Counter_postprocessing_ai; break; case 2: self->muladd_func_ptr = Counter_postprocessing_revai; break; case 10: self->muladd_func_ptr = Counter_postprocessing_ia; break; case 11: self->muladd_func_ptr = Counter_postprocessing_aa; break; case 12: self->muladd_func_ptr = Counter_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Counter_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Counter_postprocessing_areva; break; case 22: self->muladd_func_ptr = Counter_postprocessing_revareva; break; } } static void Counter_compute_next_data_frame(Counter *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Counter_traverse(Counter *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Counter_clear(Counter *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Counter_dealloc(Counter* self) { pyo_DEALLOC Counter_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Counter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; Counter *self; self = (Counter *)type->tp_alloc(type, 0); self->min = 0; self->max = 100; self->dir = 0; self->direction = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Counter_compute_next_data_frame); self->mode_func_ptr = Counter_setProcMode; static char *kwlist[] = {"input", "min", "max", "dir", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|lliOO", kwlist, &inputtmp, &self->min, &self->max, &self->dir, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (self->dir == 0 || self->dir == 2) self->tmp = self->min; else self->tmp = self->max - 1; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Counter_getServer(Counter* self) { GET_SERVER }; static PyObject * Counter_getStream(Counter* self) { GET_STREAM }; static PyObject * Counter_setMul(Counter *self, PyObject *arg) { SET_MUL }; static PyObject * Counter_setAdd(Counter *self, PyObject *arg) { SET_ADD }; static PyObject * Counter_setSub(Counter *self, PyObject *arg) { SET_SUB }; static PyObject * Counter_setDiv(Counter *self, PyObject *arg) { SET_DIV }; static PyObject * Counter_play(Counter *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Counter_stop(Counter *self) { STOP }; static PyObject * Counter_multiply(Counter *self, PyObject *arg) { MULTIPLY }; static PyObject * Counter_inplace_multiply(Counter *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Counter_add(Counter *self, PyObject *arg) { ADD }; static PyObject * Counter_inplace_add(Counter *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Counter_sub(Counter *self, PyObject *arg) { SUB }; static PyObject * Counter_inplace_sub(Counter *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Counter_div(Counter *self, PyObject *arg) { DIV }; static PyObject * Counter_inplace_div(Counter *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Counter_setMin(Counter *self, PyObject *arg) { ASSERT_ARG_NOT_NULL if (PyLong_Check(arg) || PyInt_Check(arg)) { self->min = PyLong_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Counter_setMax(Counter *self, PyObject *arg) { ASSERT_ARG_NOT_NULL if (PyLong_Check(arg) || PyInt_Check(arg)) { self->max = PyLong_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Counter_setDir(Counter *self, PyObject *arg) { ASSERT_ARG_NOT_NULL if (PyInt_Check(arg)) { self->dir = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Counter_reset(Counter *self, PyObject *arg) { int val; if (arg == Py_None) { if (self->dir == 0 || self->dir == 2) val = self->min; else val = self->max - 1; self->tmp = val; } else if (PyInt_Check(arg)) { val = PyInt_AsLong(arg); self->tmp = val; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Counter_members[] = { {"server", T_OBJECT_EX, offsetof(Counter, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Counter, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Counter, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(Counter, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Counter, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Counter_methods[] = { {"getServer", (PyCFunction)Counter_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Counter_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Counter_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Counter_stop, METH_NOARGS, "Stops computing."}, {"setMin", (PyCFunction)Counter_setMin, METH_O, "Sets minimum value."}, {"setMax", (PyCFunction)Counter_setMax, METH_O, "Sets maximum value."}, {"setDir", (PyCFunction)Counter_setDir, METH_O, "Sets direction. 0 = forward, 1 = backward, 2 = back and forth"}, {"reset", (PyCFunction)Counter_reset, METH_O, "Resets the current count of the counter."}, {"setMul", (PyCFunction)Counter_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Counter_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Counter_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Counter_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Counter_as_number = { (binaryfunc)Counter_add, /*nb_add*/ (binaryfunc)Counter_sub, /*nb_subtract*/ (binaryfunc)Counter_multiply, /*nb_multiply*/ (binaryfunc)Counter_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Counter_inplace_add, /*inplace_add*/ (binaryfunc)Counter_inplace_sub, /*inplace_subtract*/ (binaryfunc)Counter_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Counter_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject CounterType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Counter_base", /*tp_name*/ sizeof(Counter), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Counter_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Counter_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Counter objects. Integer incrementor.", /* tp_doc */ (traverseproc)Counter_traverse, /* tp_traverse */ (inquiry)Counter_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Counter_methods, /* tp_methods */ Counter_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Counter_new, /* tp_new */ }; /***************************************************/ /******* Thresh ***********/ /***************************************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *threshold; Stream *threshold_stream; int dir; int ready; int modebuffer[3]; } Thresh; static void Thresh_generates_i(Thresh *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT thresh = PyFloat_AS_DOUBLE(self->threshold); switch (self->dir) { case 0: for (i=0; ibufsize; i++) { self->data[i] = 0.0; if (in[i] > thresh && self->ready == 1) { self->data[i] = 1.0; self->ready = 0; } else if (in[i] <= thresh && self->ready == 0) self->ready = 1; } break; case 1: for (i=0; ibufsize; i++) { self->data[i] = 0.0; if (in[i] < thresh && self->ready == 1) { self->data[i] = 1.0; self->ready = 0; } else if (in[i] >= thresh && self->ready == 0) self->ready = 1; } break; case 2: for (i=0; ibufsize; i++) { self->data[i] = 0.0; if (in[i] > thresh && self->ready == 1) { self->data[i] = 1.0; self->ready = 0; } else if (in[i] <= thresh && self->ready == 0) { self->data[i] = 1.0; self->ready = 1; } } break; } } static void Thresh_generates_a(Thresh *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *thresh = Stream_getData((Stream *)self->threshold_stream); switch (self->dir) { case 0: for (i=0; ibufsize; i++) { self->data[i] = 0.0; if (in[i] > thresh[i] && self->ready == 1) { self->data[i] = 1.0; self->ready = 0; } else if (in[i] <= thresh[i] && self->ready == 0) self->ready = 1; } break; case 1: for (i=0; ibufsize; i++) { self->data[i] = 0.0; if (in[i] < thresh[i] && self->ready == 1) { self->data[i] = 1.0; self->ready = 0; } else if (in[i] >= thresh[i] && self->ready == 0) self->ready = 1; } break; case 2: for (i=0; ibufsize; i++) { self->data[i] = 0.0; if (in[i] > thresh[i] && self->ready == 1) { self->data[i] = 1.0; self->ready = 0; } else if (in[i] <= thresh[i] && self->ready == 0) self->data[i] = 1.0; self->ready = 1; } break; } } static void Thresh_postprocessing_ii(Thresh *self) { POST_PROCESSING_II }; static void Thresh_postprocessing_ai(Thresh *self) { POST_PROCESSING_AI }; static void Thresh_postprocessing_ia(Thresh *self) { POST_PROCESSING_IA }; static void Thresh_postprocessing_aa(Thresh *self) { POST_PROCESSING_AA }; static void Thresh_postprocessing_ireva(Thresh *self) { POST_PROCESSING_IREVA }; static void Thresh_postprocessing_areva(Thresh *self) { POST_PROCESSING_AREVA }; static void Thresh_postprocessing_revai(Thresh *self) { POST_PROCESSING_REVAI }; static void Thresh_postprocessing_revaa(Thresh *self) { POST_PROCESSING_REVAA }; static void Thresh_postprocessing_revareva(Thresh *self) { POST_PROCESSING_REVAREVA }; static void Thresh_setProcMode(Thresh *self) { int procmode = self->modebuffer[2]; int muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Thresh_generates_i; break; case 1: self->proc_func_ptr = Thresh_generates_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Thresh_postprocessing_ii; break; case 1: self->muladd_func_ptr = Thresh_postprocessing_ai; break; case 2: self->muladd_func_ptr = Thresh_postprocessing_revai; break; case 10: self->muladd_func_ptr = Thresh_postprocessing_ia; break; case 11: self->muladd_func_ptr = Thresh_postprocessing_aa; break; case 12: self->muladd_func_ptr = Thresh_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Thresh_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Thresh_postprocessing_areva; break; case 22: self->muladd_func_ptr = Thresh_postprocessing_revareva; break; } } static void Thresh_compute_next_data_frame(Thresh *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Thresh_traverse(Thresh *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->threshold); Py_VISIT(self->threshold_stream); return 0; } static int Thresh_clear(Thresh *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->threshold); Py_CLEAR(self->threshold_stream); return 0; } static void Thresh_dealloc(Thresh* self) { pyo_DEALLOC Thresh_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Thresh_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *thresholdtmp, *multmp=NULL, *addtmp=NULL; Thresh *self; self = (Thresh *)type->tp_alloc(type, 0); self->threshold = PyFloat_FromDouble(0.); self->dir = 0; self->ready = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Thresh_compute_next_data_frame); self->mode_func_ptr = Thresh_setProcMode; static char *kwlist[] = {"input", "threshold", "dir", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OiOO", kwlist, &inputtmp, &thresholdtmp, &self->dir, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (thresholdtmp) { PyObject_CallMethod((PyObject *)self, "setThreshold", "O", thresholdtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Thresh_getServer(Thresh* self) { GET_SERVER }; static PyObject * Thresh_getStream(Thresh* self) { GET_STREAM }; static PyObject * Thresh_setMul(Thresh *self, PyObject *arg) { SET_MUL }; static PyObject * Thresh_setAdd(Thresh *self, PyObject *arg) { SET_ADD }; static PyObject * Thresh_setSub(Thresh *self, PyObject *arg) { SET_SUB }; static PyObject * Thresh_setDiv(Thresh *self, PyObject *arg) { SET_DIV }; static PyObject * Thresh_play(Thresh *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Thresh_stop(Thresh *self) { STOP }; static PyObject * Thresh_multiply(Thresh *self, PyObject *arg) { MULTIPLY }; static PyObject * Thresh_inplace_multiply(Thresh *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Thresh_add(Thresh *self, PyObject *arg) { ADD }; static PyObject * Thresh_inplace_add(Thresh *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Thresh_sub(Thresh *self, PyObject *arg) { SUB }; static PyObject * Thresh_inplace_sub(Thresh *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Thresh_div(Thresh *self, PyObject *arg) { DIV }; static PyObject * Thresh_inplace_div(Thresh *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Thresh_setThreshold(Thresh *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->threshold); if (isNumber == 1) { self->threshold = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->threshold = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->threshold, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->threshold_stream); self->threshold_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Thresh_setDir(Thresh *self, PyObject *arg) { ASSERT_ARG_NOT_NULL if (PyInt_Check(arg)) { self->dir = PyInt_AsLong(arg); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Thresh_members[] = { {"server", T_OBJECT_EX, offsetof(Thresh, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Thresh, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Thresh, input), 0, "Input sound object."}, {"threshold", T_OBJECT_EX, offsetof(Thresh, threshold), 0, "Threshold object."}, {"mul", T_OBJECT_EX, offsetof(Thresh, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Thresh, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Thresh_methods[] = { {"getServer", (PyCFunction)Thresh_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Thresh_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Thresh_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Thresh_stop, METH_NOARGS, "Stops computing."}, {"setThreshold", (PyCFunction)Thresh_setThreshold, METH_O, "Sets threshold value."}, {"setDir", (PyCFunction)Thresh_setDir, METH_O, "Sets direction. 0 = upward, 1 = downward, 2 = up and down"}, {"setMul", (PyCFunction)Thresh_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)Thresh_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)Thresh_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Thresh_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Thresh_as_number = { (binaryfunc)Thresh_add, /*nb_add*/ (binaryfunc)Thresh_sub, /*nb_subtract*/ (binaryfunc)Thresh_multiply, /*nb_multiply*/ (binaryfunc)Thresh_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Thresh_inplace_add, /*inplace_add*/ (binaryfunc)Thresh_inplace_sub, /*inplace_subtract*/ (binaryfunc)Thresh_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Thresh_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ThreshType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Thresh_base", /*tp_name*/ sizeof(Thresh), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Thresh_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Thresh_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Thresh objects. Threshold detector.", /* tp_doc */ (traverseproc)Thresh_traverse, /* tp_traverse */ (inquiry)Thresh_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Thresh_methods, /* tp_methods */ Thresh_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Thresh_new, /* tp_new */ }; /***************************************************/ /******* Percent ***********/ /***************************************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *percent; Stream *percent_stream; int modebuffer[3]; } Percent; static void Percent_generates_i(Percent *self) { int i; MYFLT guess; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT perc = PyFloat_AS_DOUBLE(self->percent); for (i=0; ibufsize; i++) { self->data[i] = 0.0; if (in[i] == 1.0) { guess = (rand()/((MYFLT)(RAND_MAX)+1)) * 100.0; if (guess <= perc) self->data[i] = 1.0; } } } static void Percent_generates_a(Percent *self) { int i; MYFLT guess; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *perc = Stream_getData((Stream *)self->percent_stream); for (i=0; ibufsize; i++) { self->data[i] = 0.0; if (in[i] == 1.0) { guess = (rand()/((MYFLT)(RAND_MAX)+1)) * 100.0; if (guess <= perc[i]) self->data[i] = 1.0; } } } static void Percent_postprocessing_ii(Percent *self) { POST_PROCESSING_II }; static void Percent_postprocessing_ai(Percent *self) { POST_PROCESSING_AI }; static void Percent_postprocessing_ia(Percent *self) { POST_PROCESSING_IA }; static void Percent_postprocessing_aa(Percent *self) { POST_PROCESSING_AA }; static void Percent_postprocessing_ireva(Percent *self) { POST_PROCESSING_IREVA }; static void Percent_postprocessing_areva(Percent *self) { POST_PROCESSING_AREVA }; static void Percent_postprocessing_revai(Percent *self) { POST_PROCESSING_REVAI }; static void Percent_postprocessing_revaa(Percent *self) { POST_PROCESSING_REVAA }; static void Percent_postprocessing_revareva(Percent *self) { POST_PROCESSING_REVAREVA }; static void Percent_setProcMode(Percent *self) { int muladdmode, procmode ; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Percent_generates_i; break; case 1: self->proc_func_ptr = Percent_generates_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Percent_postprocessing_ii; break; case 1: self->muladd_func_ptr = Percent_postprocessing_ai; break; case 2: self->muladd_func_ptr = Percent_postprocessing_revai; break; case 10: self->muladd_func_ptr = Percent_postprocessing_ia; break; case 11: self->muladd_func_ptr = Percent_postprocessing_aa; break; case 12: self->muladd_func_ptr = Percent_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Percent_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Percent_postprocessing_areva; break; case 22: self->muladd_func_ptr = Percent_postprocessing_revareva; break; } } static void Percent_compute_next_data_frame(Percent *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Percent_traverse(Percent *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->percent); Py_VISIT(self->percent_stream); return 0; } static int Percent_clear(Percent *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->percent); Py_CLEAR(self->percent_stream); return 0; } static void Percent_dealloc(Percent* self) { pyo_DEALLOC Percent_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Percent_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *percenttmp, *multmp=NULL, *addtmp=NULL; Percent *self; self = (Percent *)type->tp_alloc(type, 0); self->percent = PyFloat_FromDouble(50.); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Percent_compute_next_data_frame); self->mode_func_ptr = Percent_setProcMode; static char *kwlist[] = {"input", "percent", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &percenttmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (percenttmp) { PyObject_CallMethod((PyObject *)self, "setPercent", "O", percenttmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Server_generateSeed((Server *)self->server, PERCENT_ID); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Percent_getServer(Percent* self) { GET_SERVER }; static PyObject * Percent_getStream(Percent* self) { GET_STREAM }; static PyObject * Percent_setMul(Percent *self, PyObject *arg) { SET_MUL }; static PyObject * Percent_setAdd(Percent *self, PyObject *arg) { SET_ADD }; static PyObject * Percent_setSub(Percent *self, PyObject *arg) { SET_SUB }; static PyObject * Percent_setDiv(Percent *self, PyObject *arg) { SET_DIV }; static PyObject * Percent_play(Percent *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Percent_stop(Percent *self) { STOP }; static PyObject * Percent_multiply(Percent *self, PyObject *arg) { MULTIPLY }; static PyObject * Percent_inplace_multiply(Percent *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Percent_add(Percent *self, PyObject *arg) { ADD }; static PyObject * Percent_inplace_add(Percent *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Percent_sub(Percent *self, PyObject *arg) { SUB }; static PyObject * Percent_inplace_sub(Percent *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Percent_div(Percent *self, PyObject *arg) { DIV }; static PyObject * Percent_inplace_div(Percent *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Percent_setPercent(Percent *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->percent); if (isNumber == 1) { self->percent = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->percent = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->percent, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->percent_stream); self->percent_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Percent_members[] = { {"server", T_OBJECT_EX, offsetof(Percent, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Percent, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Percent, input), 0, "Input sound object."}, {"percent", T_OBJECT_EX, offsetof(Percent, percent), 0, "percent attribute."}, {"mul", T_OBJECT_EX, offsetof(Percent, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Percent, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Percent_methods[] = { {"getServer", (PyCFunction)Percent_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Percent_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Percent_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Percent_stop, METH_NOARGS, "Stops computing."}, {"setPercent", (PyCFunction)Percent_setPercent, METH_O, "Sets percentange value."}, {"setMul", (PyCFunction)Percent_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)Percent_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)Percent_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Percent_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Percent_as_number = { (binaryfunc)Percent_add, /*nb_add*/ (binaryfunc)Percent_sub, /*nb_subtract*/ (binaryfunc)Percent_multiply, /*nb_multiply*/ (binaryfunc)Percent_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Percent_inplace_add, /*inplace_add*/ (binaryfunc)Percent_inplace_sub, /*inplace_subtract*/ (binaryfunc)Percent_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Percent_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject PercentType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Percent_base", /*tp_name*/ sizeof(Percent), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Percent_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Percent_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Percent objects. Looks for input triggers and sets how much percentage of it to let pass.", /* tp_doc */ (traverseproc)Percent_traverse, /* tp_traverse */ (inquiry)Percent_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Percent_methods, /* tp_methods */ Percent_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Percent_new, /* tp_new */ }; /*************************/ /******* Timer ***********/ /*************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *input2; Stream *input2_stream; unsigned long count; MYFLT lasttime; int started; int modebuffer[2]; } Timer; static void Timer_generates(Timer *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); for (i=0; ibufsize; i++) { if (self->started == 1) { self->count++; if (in[i] == 1.0) { self->lasttime = self->count / self->sr; self->started = 0; } } if (in2[i] == 1 && self->started == 0) { self->count = 0; self->started = 1; } self->data[i] = self->lasttime; } } static void Timer_postprocessing_ii(Timer *self) { POST_PROCESSING_II }; static void Timer_postprocessing_ai(Timer *self) { POST_PROCESSING_AI }; static void Timer_postprocessing_ia(Timer *self) { POST_PROCESSING_IA }; static void Timer_postprocessing_aa(Timer *self) { POST_PROCESSING_AA }; static void Timer_postprocessing_ireva(Timer *self) { POST_PROCESSING_IREVA }; static void Timer_postprocessing_areva(Timer *self) { POST_PROCESSING_AREVA }; static void Timer_postprocessing_revai(Timer *self) { POST_PROCESSING_REVAI }; static void Timer_postprocessing_revaa(Timer *self) { POST_PROCESSING_REVAA }; static void Timer_postprocessing_revareva(Timer *self) { POST_PROCESSING_REVAREVA }; static void Timer_setProcMode(Timer *self) { int muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Timer_generates; switch (muladdmode) { case 0: self->muladd_func_ptr = Timer_postprocessing_ii; break; case 1: self->muladd_func_ptr = Timer_postprocessing_ai; break; case 2: self->muladd_func_ptr = Timer_postprocessing_revai; break; case 10: self->muladd_func_ptr = Timer_postprocessing_ia; break; case 11: self->muladd_func_ptr = Timer_postprocessing_aa; break; case 12: self->muladd_func_ptr = Timer_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Timer_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Timer_postprocessing_areva; break; case 22: self->muladd_func_ptr = Timer_postprocessing_revareva; break; } } static void Timer_compute_next_data_frame(Timer *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Timer_traverse(Timer *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->input2); Py_VISIT(self->input2_stream); return 0; } static int Timer_clear(Timer *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->input2); Py_CLEAR(self->input2_stream); return 0; } static void Timer_dealloc(Timer* self) { pyo_DEALLOC Timer_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Timer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *multmp=NULL, *addtmp=NULL; Timer *self; self = (Timer *)type->tp_alloc(type, 0); self->count = 0; self->started = 0; self->lasttime = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Timer_compute_next_data_frame); self->mode_func_ptr = Timer_setProcMode; static char *kwlist[] = {"input", "input2", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &inputtmp, &input2tmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_XDECREF(self->input2); self->input2 = input2tmp; input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL); Py_INCREF(input2_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (Stream *)input2_streamtmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Timer_getServer(Timer* self) { GET_SERVER }; static PyObject * Timer_getStream(Timer* self) { GET_STREAM }; static PyObject * Timer_setMul(Timer *self, PyObject *arg) { SET_MUL }; static PyObject * Timer_setAdd(Timer *self, PyObject *arg) { SET_ADD }; static PyObject * Timer_setSub(Timer *self, PyObject *arg) { SET_SUB }; static PyObject * Timer_setDiv(Timer *self, PyObject *arg) { SET_DIV }; static PyObject * Timer_play(Timer *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Timer_stop(Timer *self) { STOP }; static PyObject * Timer_multiply(Timer *self, PyObject *arg) { MULTIPLY }; static PyObject * Timer_inplace_multiply(Timer *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Timer_add(Timer *self, PyObject *arg) { ADD }; static PyObject * Timer_inplace_add(Timer *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Timer_sub(Timer *self, PyObject *arg) { SUB }; static PyObject * Timer_inplace_sub(Timer *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Timer_div(Timer *self, PyObject *arg) { DIV }; static PyObject * Timer_inplace_div(Timer *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Timer_members[] = { {"server", T_OBJECT_EX, offsetof(Timer, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Timer, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Timer, input), 0, "Stops timer and output time elapsed."}, {"input2", T_OBJECT_EX, offsetof(Timer, input2), 0, "Starts timer."}, {"mul", T_OBJECT_EX, offsetof(Timer, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Timer, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Timer_methods[] = { {"getServer", (PyCFunction)Timer_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Timer_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Timer_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Timer_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Timer_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)Timer_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)Timer_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Timer_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Timer_as_number = { (binaryfunc)Timer_add, /*nb_add*/ (binaryfunc)Timer_sub, /*nb_subtract*/ (binaryfunc)Timer_multiply, /*nb_multiply*/ (binaryfunc)Timer_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Timer_inplace_add, /*inplace_add*/ (binaryfunc)Timer_inplace_sub, /*inplace_subtract*/ (binaryfunc)Timer_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Timer_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TimerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Timer_base", /*tp_name*/ sizeof(Timer), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Timer_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Timer_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Timer objects. Returns elapsed time between two triggers.", /* tp_doc */ (traverseproc)Timer_traverse, /* tp_traverse */ (inquiry)Timer_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Timer_methods, /* tp_methods */ Timer_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Timer_new, /* tp_new */ }; /*********************************************************************************************/ /* Iter ********************************************************************************/ /*********************************************************************************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int chSize; int chCount; MYFLT *choice; MYFLT value; int modebuffer[2]; // need at least 2 slots for mul & add } Iter; static void Iter_generate(Iter *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { if (in[i] == 1) { if (self->chCount >= self->chSize) self->chCount = 0; self->value = self->choice[self->chCount]; self->chCount++; } self->data[i] = self->value; } } static void Iter_postprocessing_ii(Iter *self) { POST_PROCESSING_II }; static void Iter_postprocessing_ai(Iter *self) { POST_PROCESSING_AI }; static void Iter_postprocessing_ia(Iter *self) { POST_PROCESSING_IA }; static void Iter_postprocessing_aa(Iter *self) { POST_PROCESSING_AA }; static void Iter_postprocessing_ireva(Iter *self) { POST_PROCESSING_IREVA }; static void Iter_postprocessing_areva(Iter *self) { POST_PROCESSING_AREVA }; static void Iter_postprocessing_revai(Iter *self) { POST_PROCESSING_REVAI }; static void Iter_postprocessing_revaa(Iter *self) { POST_PROCESSING_REVAA }; static void Iter_postprocessing_revareva(Iter *self) { POST_PROCESSING_REVAREVA }; static void Iter_setProcMode(Iter *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Iter_generate; switch (muladdmode) { case 0: self->muladd_func_ptr = Iter_postprocessing_ii; break; case 1: self->muladd_func_ptr = Iter_postprocessing_ai; break; case 2: self->muladd_func_ptr = Iter_postprocessing_revai; break; case 10: self->muladd_func_ptr = Iter_postprocessing_ia; break; case 11: self->muladd_func_ptr = Iter_postprocessing_aa; break; case 12: self->muladd_func_ptr = Iter_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Iter_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Iter_postprocessing_areva; break; case 22: self->muladd_func_ptr = Iter_postprocessing_revareva; break; } } static void Iter_compute_next_data_frame(Iter *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Iter_traverse(Iter *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Iter_clear(Iter *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Iter_dealloc(Iter* self) { pyo_DEALLOC free(self->choice); Iter_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Iter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; MYFLT inittmp = 0.0; PyObject *inputtmp, *input_streamtmp, *choicetmp=NULL, *multmp=NULL, *addtmp=NULL; Iter *self; self = (Iter *)type->tp_alloc(type, 0); self->value = 0.; self->chCount = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Iter_compute_next_data_frame); self->mode_func_ptr = Iter_setProcMode; static char *kwlist[] = {"input", "choice", "init", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_FOO, kwlist, &inputtmp, &choicetmp, &inittmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (choicetmp) { PyObject_CallMethod((PyObject *)self, "setChoice", "O", choicetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->value = inittmp; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Iter_getServer(Iter* self) { GET_SERVER }; static PyObject * Iter_getStream(Iter* self) { GET_STREAM }; static PyObject * Iter_setMul(Iter *self, PyObject *arg) { SET_MUL }; static PyObject * Iter_setAdd(Iter *self, PyObject *arg) { SET_ADD }; static PyObject * Iter_setSub(Iter *self, PyObject *arg) { SET_SUB }; static PyObject * Iter_setDiv(Iter *self, PyObject *arg) { SET_DIV }; static PyObject * Iter_play(Iter *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Iter_out(Iter *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Iter_stop(Iter *self) { STOP }; static PyObject * Iter_multiply(Iter *self, PyObject *arg) { MULTIPLY }; static PyObject * Iter_inplace_multiply(Iter *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Iter_add(Iter *self, PyObject *arg) { ADD }; static PyObject * Iter_inplace_add(Iter *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Iter_sub(Iter *self, PyObject *arg) { SUB }; static PyObject * Iter_inplace_sub(Iter *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Iter_div(Iter *self, PyObject *arg) { DIV }; static PyObject * Iter_inplace_div(Iter *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Iter_setChoice(Iter *self, PyObject *arg) { int i; PyObject *tmp; if (! PyList_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The choice attribute must be a list."); Py_INCREF(Py_None); return Py_None; } tmp = arg; self->chSize = PyList_Size(tmp); self->choice = (MYFLT *)realloc(self->choice, self->chSize * sizeof(MYFLT)); for (i=0; ichSize; i++) { self->choice[i] = PyFloat_AsDouble(PyList_GET_ITEM(tmp, i)); } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Iter_reset(Iter *self, PyObject *arg) { int tmp; if (PyInt_Check(arg)) { tmp = PyInt_AsLong(arg); if (tmp < self->chSize) self->chCount = tmp; else self->chCount = 0; } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Iter_members[] = { {"server", T_OBJECT_EX, offsetof(Iter, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Iter, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Iter, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(Iter, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Iter, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Iter_methods[] = { {"getServer", (PyCFunction)Iter_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Iter_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Iter_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Iter_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Iter_stop, METH_NOARGS, "Stops computing."}, {"setChoice", (PyCFunction)Iter_setChoice, METH_O, "Sets possible values."}, {"reset", (PyCFunction)Iter_reset, METH_O, "Resets count to 0."}, {"setMul", (PyCFunction)Iter_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Iter_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Iter_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Iter_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Iter_as_number = { (binaryfunc)Iter_add, /*nb_add*/ (binaryfunc)Iter_sub, /*nb_subtract*/ (binaryfunc)Iter_multiply, /*nb_multiply*/ (binaryfunc)Iter_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Iter_inplace_add, /*inplace_add*/ (binaryfunc)Iter_inplace_sub, /*inplace_subtract*/ (binaryfunc)Iter_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Iter_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject IterType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Iter_base", /*tp_name*/ sizeof(Iter), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Iter_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Iter_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Iter objects. Triggers iterate over a list of values.", /* tp_doc */ (traverseproc)Iter_traverse, /* tp_traverse */ (inquiry)Iter_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Iter_methods, /* tp_methods */ Iter_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Iter_new, /* tp_new */ }; /*************************/ /******* Count ***********/ /*************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; unsigned long count; unsigned long min; unsigned long max; int started; int modebuffer[2]; } Count; static void Count_generates(Count *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { if (in[i] == 1) { self->count = self->min; self->started = 1; } if (self->started == 1) { self->data[i] = (MYFLT)self->count; if (self->count++ >= self->max && self->max != 0) self->count = self->min; } else { self->data[i] = self->min; } } } static void Count_postprocessing_ii(Count *self) { POST_PROCESSING_II }; static void Count_postprocessing_ai(Count *self) { POST_PROCESSING_AI }; static void Count_postprocessing_ia(Count *self) { POST_PROCESSING_IA }; static void Count_postprocessing_aa(Count *self) { POST_PROCESSING_AA }; static void Count_postprocessing_ireva(Count *self) { POST_PROCESSING_IREVA }; static void Count_postprocessing_areva(Count *self) { POST_PROCESSING_AREVA }; static void Count_postprocessing_revai(Count *self) { POST_PROCESSING_REVAI }; static void Count_postprocessing_revaa(Count *self) { POST_PROCESSING_REVAA }; static void Count_postprocessing_revareva(Count *self) { POST_PROCESSING_REVAREVA }; static void Count_setProcMode(Count *self) { int muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Count_generates; switch (muladdmode) { case 0: self->muladd_func_ptr = Count_postprocessing_ii; break; case 1: self->muladd_func_ptr = Count_postprocessing_ai; break; case 2: self->muladd_func_ptr = Count_postprocessing_revai; break; case 10: self->muladd_func_ptr = Count_postprocessing_ia; break; case 11: self->muladd_func_ptr = Count_postprocessing_aa; break; case 12: self->muladd_func_ptr = Count_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Count_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Count_postprocessing_areva; break; case 22: self->muladd_func_ptr = Count_postprocessing_revareva; break; } } static void Count_compute_next_data_frame(Count *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Count_traverse(Count *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Count_clear(Count *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Count_dealloc(Count* self) { pyo_DEALLOC Count_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Count_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; Count *self; self = (Count *)type->tp_alloc(type, 0); self->started = 0; self->count = 0; self->min = 0; self->max = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Count_compute_next_data_frame); self->mode_func_ptr = Count_setProcMode; static char *kwlist[] = {"input", "min", "max", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|kkOO", kwlist, &inputtmp, &self->min, &self->max, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Count_getServer(Count* self) { GET_SERVER }; static PyObject * Count_getStream(Count* self) { GET_STREAM }; static PyObject * Count_setMul(Count *self, PyObject *arg) { SET_MUL }; static PyObject * Count_setAdd(Count *self, PyObject *arg) { SET_ADD }; static PyObject * Count_setSub(Count *self, PyObject *arg) { SET_SUB }; static PyObject * Count_setDiv(Count *self, PyObject *arg) { SET_DIV }; static PyObject * Count_play(Count *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Count_stop(Count *self) { STOP }; static PyObject * Count_multiply(Count *self, PyObject *arg) { MULTIPLY }; static PyObject * Count_inplace_multiply(Count *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Count_add(Count *self, PyObject *arg) { ADD }; static PyObject * Count_inplace_add(Count *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Count_sub(Count *self, PyObject *arg) { SUB }; static PyObject * Count_inplace_sub(Count *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Count_div(Count *self, PyObject *arg) { DIV }; static PyObject * Count_inplace_div(Count *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Count_setMin(Count *self, PyObject *arg) { if (PyLong_Check(arg) || PyInt_Check(arg)) self->min = PyLong_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyObject * Count_setMax(Count *self, PyObject *arg) { if (arg == Py_None) self->max = 0; else if (PyLong_Check(arg) || PyInt_Check(arg)) self->max = PyLong_AsLong(arg); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Count_members[] = { {"server", T_OBJECT_EX, offsetof(Count, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Count, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Count, input), 0, "Starts the count."}, {"mul", T_OBJECT_EX, offsetof(Count, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Count, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Count_methods[] = { {"getServer", (PyCFunction)Count_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Count_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Count_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Count_stop, METH_NOARGS, "Stops computing."}, {"setMin", (PyCFunction)Count_setMin, METH_O, "Sets the minimum value."}, {"setMax", (PyCFunction)Count_setMax, METH_O, "Sets the maximum value."}, {"setMul", (PyCFunction)Count_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)Count_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)Count_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Count_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Count_as_number = { (binaryfunc)Count_add, /*nb_add*/ (binaryfunc)Count_sub, /*nb_subtract*/ (binaryfunc)Count_multiply, /*nb_multiply*/ (binaryfunc)Count_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Count_inplace_add, /*inplace_add*/ (binaryfunc)Count_inplace_sub, /*inplace_subtract*/ (binaryfunc)Count_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Count_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject CountType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Count_base", /*tp_name*/ sizeof(Count), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Count_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Count_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Count objects. Counts integer at audio rate.", /* tp_doc */ (traverseproc)Count_traverse, /* tp_traverse */ (inquiry)Count_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Count_methods, /* tp_methods */ Count_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Count_new, /* tp_new */ }; /*************************/ /******* NextTrig ********/ /*************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *input2; Stream *input2_stream; int gate; int modebuffer[2]; } NextTrig; static void NextTrig_generates(NextTrig *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); for (i=0; ibufsize; i++) { self->data[i] = 0.0; if (self->gate == 1 && in[i] == 1.0) { self->data[i] = 1.0; self->gate = 0; } if (in2[i] == 1 && self->gate == 0) self->gate = 1; } } static void NextTrig_postprocessing_ii(NextTrig *self) { POST_PROCESSING_II }; static void NextTrig_postprocessing_ai(NextTrig *self) { POST_PROCESSING_AI }; static void NextTrig_postprocessing_ia(NextTrig *self) { POST_PROCESSING_IA }; static void NextTrig_postprocessing_aa(NextTrig *self) { POST_PROCESSING_AA }; static void NextTrig_postprocessing_ireva(NextTrig *self) { POST_PROCESSING_IREVA }; static void NextTrig_postprocessing_areva(NextTrig *self) { POST_PROCESSING_AREVA }; static void NextTrig_postprocessing_revai(NextTrig *self) { POST_PROCESSING_REVAI }; static void NextTrig_postprocessing_revaa(NextTrig *self) { POST_PROCESSING_REVAA }; static void NextTrig_postprocessing_revareva(NextTrig *self) { POST_PROCESSING_REVAREVA }; static void NextTrig_setProcMode(NextTrig *self) { int muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = NextTrig_generates; switch (muladdmode) { case 0: self->muladd_func_ptr = NextTrig_postprocessing_ii; break; case 1: self->muladd_func_ptr = NextTrig_postprocessing_ai; break; case 2: self->muladd_func_ptr = NextTrig_postprocessing_revai; break; case 10: self->muladd_func_ptr = NextTrig_postprocessing_ia; break; case 11: self->muladd_func_ptr = NextTrig_postprocessing_aa; break; case 12: self->muladd_func_ptr = NextTrig_postprocessing_revaa; break; case 20: self->muladd_func_ptr = NextTrig_postprocessing_ireva; break; case 21: self->muladd_func_ptr = NextTrig_postprocessing_areva; break; case 22: self->muladd_func_ptr = NextTrig_postprocessing_revareva; break; } } static void NextTrig_compute_next_data_frame(NextTrig *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int NextTrig_traverse(NextTrig *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->input2); Py_VISIT(self->input2_stream); return 0; } static int NextTrig_clear(NextTrig *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->input2); Py_CLEAR(self->input2_stream); return 0; } static void NextTrig_dealloc(NextTrig* self) { pyo_DEALLOC NextTrig_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * NextTrig_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *multmp=NULL, *addtmp=NULL; NextTrig *self; self = (NextTrig *)type->tp_alloc(type, 0); self->gate = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, NextTrig_compute_next_data_frame); self->mode_func_ptr = NextTrig_setProcMode; static char *kwlist[] = {"input", "input2", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &inputtmp, &input2tmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_XDECREF(self->input2); self->input2 = input2tmp; input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL); Py_INCREF(input2_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (Stream *)input2_streamtmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * NextTrig_getServer(NextTrig* self) { GET_SERVER }; static PyObject * NextTrig_getStream(NextTrig* self) { GET_STREAM }; static PyObject * NextTrig_setMul(NextTrig *self, PyObject *arg) { SET_MUL }; static PyObject * NextTrig_setAdd(NextTrig *self, PyObject *arg) { SET_ADD }; static PyObject * NextTrig_setSub(NextTrig *self, PyObject *arg) { SET_SUB }; static PyObject * NextTrig_setDiv(NextTrig *self, PyObject *arg) { SET_DIV }; static PyObject * NextTrig_play(NextTrig *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * NextTrig_stop(NextTrig *self) { STOP }; static PyObject * NextTrig_multiply(NextTrig *self, PyObject *arg) { MULTIPLY }; static PyObject * NextTrig_inplace_multiply(NextTrig *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * NextTrig_add(NextTrig *self, PyObject *arg) { ADD }; static PyObject * NextTrig_inplace_add(NextTrig *self, PyObject *arg) { INPLACE_ADD }; static PyObject * NextTrig_sub(NextTrig *self, PyObject *arg) { SUB }; static PyObject * NextTrig_inplace_sub(NextTrig *self, PyObject *arg) { INPLACE_SUB }; static PyObject * NextTrig_div(NextTrig *self, PyObject *arg) { DIV }; static PyObject * NextTrig_inplace_div(NextTrig *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef NextTrig_members[] = { {"server", T_OBJECT_EX, offsetof(NextTrig, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(NextTrig, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(NextTrig, input), 0, "Stops NextTrig and output time elapsed."}, {"input2", T_OBJECT_EX, offsetof(NextTrig, input2), 0, "Starts NextTrig."}, {"mul", T_OBJECT_EX, offsetof(NextTrig, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(NextTrig, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef NextTrig_methods[] = { {"getServer", (PyCFunction)NextTrig_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)NextTrig_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)NextTrig_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)NextTrig_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)NextTrig_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)NextTrig_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)NextTrig_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)NextTrig_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods NextTrig_as_number = { (binaryfunc)NextTrig_add, /*nb_add*/ (binaryfunc)NextTrig_sub, /*nb_subtract*/ (binaryfunc)NextTrig_multiply, /*nb_multiply*/ (binaryfunc)NextTrig_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)NextTrig_inplace_add, /*inplace_add*/ (binaryfunc)NextTrig_inplace_sub, /*inplace_subtract*/ (binaryfunc)NextTrig_inplace_multiply, /*inplace_multiply*/ (binaryfunc)NextTrig_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject NextTrigType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.NextTrig_base", /*tp_name*/ sizeof(NextTrig), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)NextTrig_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &NextTrig_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "NextTrig objects. A trig opens a gate only for the next one.", /* tp_doc */ (traverseproc)NextTrig_traverse, /* tp_traverse */ (inquiry)NextTrig_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ NextTrig_methods, /* tp_methods */ NextTrig_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ NextTrig_new, /* tp_new */ }; typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *value; Stream *value_stream; MYFLT current_value; int modebuffer[3]; // need at least 2 slots for mul & add } TrigVal; static void TrigVal_generate_i(TrigVal *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT val = PyFloat_AS_DOUBLE(self->value); for (i=0; ibufsize; i++) { if (in[i] == 1) self->current_value = val; self->data[i] = self->current_value; } } static void TrigVal_generate_a(TrigVal *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *val = Stream_getData((Stream *)self->value_stream); for (i=0; ibufsize; i++) { if (in[i] == 1) self->current_value = val[i]; self->data[i] = self->current_value; } } static void TrigVal_postprocessing_ii(TrigVal *self) { POST_PROCESSING_II }; static void TrigVal_postprocessing_ai(TrigVal *self) { POST_PROCESSING_AI }; static void TrigVal_postprocessing_ia(TrigVal *self) { POST_PROCESSING_IA }; static void TrigVal_postprocessing_aa(TrigVal *self) { POST_PROCESSING_AA }; static void TrigVal_postprocessing_ireva(TrigVal *self) { POST_PROCESSING_IREVA }; static void TrigVal_postprocessing_areva(TrigVal *self) { POST_PROCESSING_AREVA }; static void TrigVal_postprocessing_revai(TrigVal *self) { POST_PROCESSING_REVAI }; static void TrigVal_postprocessing_revaa(TrigVal *self) { POST_PROCESSING_REVAA }; static void TrigVal_postprocessing_revareva(TrigVal *self) { POST_PROCESSING_REVAREVA }; static void TrigVal_setProcMode(TrigVal *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = TrigVal_generate_i; break; case 1: self->proc_func_ptr = TrigVal_generate_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = TrigVal_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrigVal_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrigVal_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrigVal_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrigVal_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrigVal_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrigVal_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrigVal_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrigVal_postprocessing_revareva; break; } } static void TrigVal_compute_next_data_frame(TrigVal *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int TrigVal_traverse(TrigVal *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->value); Py_VISIT(self->value_stream); return 0; } static int TrigVal_clear(TrigVal *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->value); Py_CLEAR(self->value_stream); return 0; } static void TrigVal_dealloc(TrigVal* self) { pyo_DEALLOC TrigVal_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrigVal_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *valuetmp=NULL, *multmp=NULL, *addtmp=NULL; TrigVal *self; self = (TrigVal *)type->tp_alloc(type, 0); self->value = PyFloat_FromDouble(0.); self->current_value = 0.; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrigVal_compute_next_data_frame); self->mode_func_ptr = TrigVal_setProcMode; static char *kwlist[] = {"input", "value", "init", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OFOO, kwlist, &inputtmp, &valuetmp, &self->current_value, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (valuetmp) { PyObject_CallMethod((PyObject *)self, "setValue", "O", valuetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrigVal_getServer(TrigVal* self) { GET_SERVER }; static PyObject * TrigVal_getStream(TrigVal* self) { GET_STREAM }; static PyObject * TrigVal_setMul(TrigVal *self, PyObject *arg) { SET_MUL }; static PyObject * TrigVal_setAdd(TrigVal *self, PyObject *arg) { SET_ADD }; static PyObject * TrigVal_setSub(TrigVal *self, PyObject *arg) { SET_SUB }; static PyObject * TrigVal_setDiv(TrigVal *self, PyObject *arg) { SET_DIV }; static PyObject * TrigVal_play(TrigVal *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrigVal_out(TrigVal *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrigVal_stop(TrigVal *self) { STOP }; static PyObject * TrigVal_multiply(TrigVal *self, PyObject *arg) { MULTIPLY }; static PyObject * TrigVal_inplace_multiply(TrigVal *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrigVal_add(TrigVal *self, PyObject *arg) { ADD }; static PyObject * TrigVal_inplace_add(TrigVal *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrigVal_sub(TrigVal *self, PyObject *arg) { SUB }; static PyObject * TrigVal_inplace_sub(TrigVal *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrigVal_div(TrigVal *self, PyObject *arg) { DIV }; static PyObject * TrigVal_inplace_div(TrigVal *self, PyObject *arg) { INPLACE_DIV }; static PyObject * TrigVal_setValue(TrigVal *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->value); if (isNumber == 1) { self->value = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->value = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->value, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->value_stream); self->value_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef TrigVal_members[] = { {"server", T_OBJECT_EX, offsetof(TrigVal, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrigVal, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(TrigVal, input), 0, "Input sound object."}, {"value", T_OBJECT_EX, offsetof(TrigVal, value), 0, "Next value."}, {"mul", T_OBJECT_EX, offsetof(TrigVal, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrigVal, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrigVal_methods[] = { {"getServer", (PyCFunction)TrigVal_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrigVal_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrigVal_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrigVal_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrigVal_stop, METH_NOARGS, "Stops computing."}, {"setValue", (PyCFunction)TrigVal_setValue, METH_O, "Sets the next value."}, {"setMul", (PyCFunction)TrigVal_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TrigVal_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TrigVal_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrigVal_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrigVal_as_number = { (binaryfunc)TrigVal_add, /*nb_add*/ (binaryfunc)TrigVal_sub, /*nb_subtract*/ (binaryfunc)TrigVal_multiply, /*nb_multiply*/ (binaryfunc)TrigVal_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrigVal_inplace_add, /*inplace_add*/ (binaryfunc)TrigVal_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrigVal_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrigVal_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrigValType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrigVal_base", /*tp_name*/ sizeof(TrigVal), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrigVal_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrigVal_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrigVal objects. Outputs a previously defined value on a trigger signal.", /* tp_doc */ (traverseproc)TrigVal_traverse, /* tp_traverse */ (inquiry)TrigVal_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrigVal_methods, /* tp_methods */ TrigVal_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrigVal_new, /* tp_new */ };pyo/src/objects/utilsmodule.c0000644000175000017500000071016712652732202015624 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" #include "interpolation.h" /************/ /* Print */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; char *message; int method; // 0 -> interval, 1 -> change MYFLT lastValue; MYFLT time; MYFLT currentTime; MYFLT sampleToSec; } Print; static void Print_process_time(Print *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { if (self->currentTime >= self->time) { self->currentTime = 0.0; if (self->message == NULL || self->message[0] == '\0') printf("%f\n", in[i]); else printf("%s : %f\n", self->message, in[i]); } self->currentTime += self->sampleToSec; } } static void Print_process_change(Print *self) { int i; MYFLT inval; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { inval = in[i]; if (inval < (self->lastValue-0.00001) || inval > (self->lastValue+0.00001)) { if (self->message == NULL || self->message[0] == '\0') printf("%f\n", inval); else printf("%s : %f\n", self->message, inval); self->lastValue = inval; } } } static void Print_setProcMode(Print *self) { if (self->method < 0 || self->method > 1) self->method = 0; switch (self->method) { case 0: self->proc_func_ptr = Print_process_time; break; case 1: self->proc_func_ptr = Print_process_change; break; } } static void Print_compute_next_data_frame(Print *self) { (*self->proc_func_ptr)(self); } static int Print_traverse(Print *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Print_clear(Print *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Print_dealloc(Print* self) { pyo_DEALLOC Print_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Print_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp; Print *self; self = (Print *)type->tp_alloc(type, 0); self->method = 0; self->time = 0.25; self->lastValue = -99999.0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Print_compute_next_data_frame); self->mode_func_ptr = Print_setProcMode; self->sampleToSec = 1. / self->sr; self->currentTime = 0.; static char *kwlist[] = {"input", "method", "interval", "message", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_IFS, kwlist, &inputtmp, &self->method, &self->time, &self->message)) Py_RETURN_NONE; INIT_INPUT_STREAM PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Print_getServer(Print* self) { GET_SERVER }; static PyObject * Print_getStream(Print* self) { GET_STREAM }; static PyObject * Print_play(Print *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Print_stop(Print *self) { STOP }; static PyObject * Print_setMethod(Print *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->method = PyInt_AsLong(arg); (*self->mode_func_ptr)(self); } Py_INCREF(Py_None); return Py_None; } static PyObject * Print_setInterval(Print *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->time = PyFloat_AsDouble(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * Print_setMessage(Print *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isString = PyString_Check(arg); if (isString == 1) { self->message = PyString_AsString(arg); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Print_members[] = { {"server", T_OBJECT_EX, offsetof(Print, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Print, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Print, input), 0, "Input sound object."}, {NULL} /* Sentinel */ }; static PyMethodDef Print_methods[] = { {"getServer", (PyCFunction)Print_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Print_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Print_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Print_stop, METH_NOARGS, "Stops computing."}, {"setMethod", (PyCFunction)Print_setMethod, METH_O, "Sets the printing method."}, {"setInterval", (PyCFunction)Print_setInterval, METH_O, "Sets the time interval."}, {"setMessage", (PyCFunction)Print_setMessage, METH_O, "Sets the prefix message to print."}, {NULL} /* Sentinel */ }; PyTypeObject PrintType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Print_base", /*tp_name*/ sizeof(Print), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Print_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Print objects. Print the current value of the input object.", /* tp_doc */ (traverseproc)Print_traverse, /* tp_traverse */ (inquiry)Print_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Print_methods, /* tp_methods */ Print_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Print_new, /* tp_new */ }; /*********************************************************************************************/ /* Snap ********************************************************************************/ /*********************************************************************************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int scale; // 0 = Midi, 1 = frequency, 2 = transpo int chSize; int highbound; MYFLT *choice; MYFLT value; MYFLT last_input; int modebuffer[2]; // need at least 2 slots for mul & add } Snap; static MYFLT Snap_convert(Snap *self) { int midival; MYFLT val; midival = self->value; if (self->scale == 1) val = 8.1757989156437 * MYPOW(1.0594630943593, midival); else if (self->scale == 2) val = MYPOW(1.0594630943593, midival - 60); else val = midival; return val; } static void Snap_generate(Snap *self) { int i, j, pos; MYFLT intmp, diff, difftmp; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { if (in[i] < (self->last_input-0.001) || in[i] > (self->last_input + 0.001)) { int oct = 0; self->last_input = intmp = in[i]; while (intmp >= self->highbound) { oct++; intmp -= self->highbound; } diff = MYFABS(self->choice[0]-intmp); pos = 0; for (j=1; jchSize; j++) { difftmp = MYFABS(self->choice[j]-intmp); if (difftmp < diff) { diff = difftmp; pos = j; } } self->value = self->choice[pos] + (self->highbound * oct); self->value = Snap_convert(self); } self->data[i] = self->value; } } static void Snap_postprocessing_ii(Snap *self) { POST_PROCESSING_II }; static void Snap_postprocessing_ai(Snap *self) { POST_PROCESSING_AI }; static void Snap_postprocessing_ia(Snap *self) { POST_PROCESSING_IA }; static void Snap_postprocessing_aa(Snap *self) { POST_PROCESSING_AA }; static void Snap_postprocessing_ireva(Snap *self) { POST_PROCESSING_IREVA }; static void Snap_postprocessing_areva(Snap *self) { POST_PROCESSING_AREVA }; static void Snap_postprocessing_revai(Snap *self) { POST_PROCESSING_REVAI }; static void Snap_postprocessing_revaa(Snap *self) { POST_PROCESSING_REVAA }; static void Snap_postprocessing_revareva(Snap *self) { POST_PROCESSING_REVAREVA }; static void Snap_setProcMode(Snap *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Snap_generate; switch (muladdmode) { case 0: self->muladd_func_ptr = Snap_postprocessing_ii; break; case 1: self->muladd_func_ptr = Snap_postprocessing_ai; break; case 2: self->muladd_func_ptr = Snap_postprocessing_revai; break; case 10: self->muladd_func_ptr = Snap_postprocessing_ia; break; case 11: self->muladd_func_ptr = Snap_postprocessing_aa; break; case 12: self->muladd_func_ptr = Snap_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Snap_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Snap_postprocessing_areva; break; case 22: self->muladd_func_ptr = Snap_postprocessing_revareva; break; } } static void Snap_compute_next_data_frame(Snap *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Snap_traverse(Snap *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Snap_clear(Snap *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Snap_dealloc(Snap* self) { pyo_DEALLOC free(self->choice); Snap_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Snap_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *choicetmp=NULL, *multmp=NULL, *addtmp=NULL; Snap *self; self = (Snap *)type->tp_alloc(type, 0); self->value = self->last_input = 0.; self->scale = 0; self->highbound = 12; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Snap_compute_next_data_frame); self->mode_func_ptr = Snap_setProcMode; static char *kwlist[] = {"input", "choice", "scale", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|iOO", kwlist, &inputtmp, &choicetmp, &self->scale, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (choicetmp) { PyObject_CallMethod((PyObject *)self, "setChoice", "O", choicetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Snap_getServer(Snap* self) { GET_SERVER }; static PyObject * Snap_getStream(Snap* self) { GET_STREAM }; static PyObject * Snap_setMul(Snap *self, PyObject *arg) { SET_MUL }; static PyObject * Snap_setAdd(Snap *self, PyObject *arg) { SET_ADD }; static PyObject * Snap_setSub(Snap *self, PyObject *arg) { SET_SUB }; static PyObject * Snap_setDiv(Snap *self, PyObject *arg) { SET_DIV }; static PyObject * Snap_play(Snap *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Snap_out(Snap *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Snap_stop(Snap *self) { STOP }; static PyObject * Snap_multiply(Snap *self, PyObject *arg) { MULTIPLY }; static PyObject * Snap_inplace_multiply(Snap *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Snap_add(Snap *self, PyObject *arg) { ADD }; static PyObject * Snap_inplace_add(Snap *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Snap_sub(Snap *self, PyObject *arg) { SUB }; static PyObject * Snap_inplace_sub(Snap *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Snap_div(Snap *self, PyObject *arg) { DIV }; static PyObject * Snap_inplace_div(Snap *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Snap_setChoice(Snap *self, PyObject *arg) { int i, oct; MYFLT max; PyObject *tmp; if (! PyList_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The choice attribute must be a list."); Py_INCREF(Py_None); return Py_None; } tmp = arg; self->chSize = PyList_Size(tmp); self->choice = (MYFLT *)realloc(self->choice, self->chSize * sizeof(MYFLT)); for (i=0; ichSize; i++) { self->choice[i] = PyFloat_AsDouble(PyList_GET_ITEM(tmp, i)); } max = self->choice[self->chSize-1]; oct = 12; while (max >= oct) { oct += 12; } self->highbound = oct; (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Snap_setScale(Snap *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isNumber = PyInt_Check(arg); if (isNumber == 1) { tmp = PyInt_AsLong(arg); if (tmp >= 0 && tmp <= 2) self->scale = tmp; else printf("scale attribute must be an integer {0, 1, 2}\n"); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Snap_members[] = { {"server", T_OBJECT_EX, offsetof(Snap, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Snap, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Snap, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(Snap, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Snap, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Snap_methods[] = { {"getServer", (PyCFunction)Snap_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Snap_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Snap_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Snap_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Snap_stop, METH_NOARGS, "Stops computing."}, {"setChoice", (PyCFunction)Snap_setChoice, METH_O, "Sets output scale."}, {"setScale", (PyCFunction)Snap_setScale, METH_O, "Sets new portamento time."}, {"setMul", (PyCFunction)Snap_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Snap_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Snap_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Snap_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Snap_as_number = { (binaryfunc)Snap_add, /*nb_add*/ (binaryfunc)Snap_sub, /*nb_subtract*/ (binaryfunc)Snap_multiply, /*nb_multiply*/ (binaryfunc)Snap_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Snap_inplace_add, /*inplace_add*/ (binaryfunc)Snap_inplace_sub, /*inplace_subtract*/ (binaryfunc)Snap_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Snap_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SnapType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Snap_base", /*tp_name*/ sizeof(Snap), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Snap_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Snap_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Snap objects. Snap input values on an arbitrary Midi scale.", /* tp_doc */ (traverseproc)Snap_traverse, /* tp_traverse */ (inquiry)Snap_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Snap_methods, /* tp_methods */ Snap_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Snap_new, /* tp_new */ }; /************/ /* Interp */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *input2; Stream *input2_stream; PyObject *interp; Stream *interp_stream; int modebuffer[3]; // need at least 2 slots for mul & add } Interp; static void Interp_filters_i(Interp *self) { MYFLT amp2; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); MYFLT inter = PyFloat_AS_DOUBLE(self->interp); if (inter < 0.0) inter = 0.0; else if (inter > 1.0) inter = 1.0; amp2 = 1.0 - inter; for (i=0; ibufsize; i++) { self->data[i] = in[i] * amp2 + in2[i] * inter; } } static void Interp_filters_a(Interp *self) { MYFLT amp1, amp2; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); MYFLT *inter = Stream_getData((Stream *)self->interp_stream); for (i=0; ibufsize; i++) { amp1 = inter[i]; if (amp1 < 0.0) amp1 = 0.0; else if (amp1 > 1.0) amp1 = 1.0; amp2 = 1.0 - amp1; self->data[i] = in[i] * amp2 + in2[i] * amp1; } } static void Interp_postprocessing_ii(Interp *self) { POST_PROCESSING_II }; static void Interp_postprocessing_ai(Interp *self) { POST_PROCESSING_AI }; static void Interp_postprocessing_ia(Interp *self) { POST_PROCESSING_IA }; static void Interp_postprocessing_aa(Interp *self) { POST_PROCESSING_AA }; static void Interp_postprocessing_ireva(Interp *self) { POST_PROCESSING_IREVA }; static void Interp_postprocessing_areva(Interp *self) { POST_PROCESSING_AREVA }; static void Interp_postprocessing_revai(Interp *self) { POST_PROCESSING_REVAI }; static void Interp_postprocessing_revaa(Interp *self) { POST_PROCESSING_REVAA }; static void Interp_postprocessing_revareva(Interp *self) { POST_PROCESSING_REVAREVA }; static void Interp_setProcMode(Interp *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Interp_filters_i; break; case 1: self->proc_func_ptr = Interp_filters_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Interp_postprocessing_ii; break; case 1: self->muladd_func_ptr = Interp_postprocessing_ai; break; case 2: self->muladd_func_ptr = Interp_postprocessing_revai; break; case 10: self->muladd_func_ptr = Interp_postprocessing_ia; break; case 11: self->muladd_func_ptr = Interp_postprocessing_aa; break; case 12: self->muladd_func_ptr = Interp_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Interp_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Interp_postprocessing_areva; break; case 22: self->muladd_func_ptr = Interp_postprocessing_revareva; break; } } static void Interp_compute_next_data_frame(Interp *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Interp_traverse(Interp *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->input2); Py_VISIT(self->input2_stream); Py_VISIT(self->interp); Py_VISIT(self->interp_stream); return 0; } static int Interp_clear(Interp *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->input2); Py_CLEAR(self->input2_stream); Py_CLEAR(self->interp); Py_CLEAR(self->interp_stream); return 0; } static void Interp_dealloc(Interp* self) { pyo_DEALLOC Interp_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Interp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *interptmp=NULL, *multmp=NULL, *addtmp=NULL; Interp *self; self = (Interp *)type->tp_alloc(type, 0); self->interp = PyFloat_FromDouble(.5); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Interp_compute_next_data_frame); self->mode_func_ptr = Interp_setProcMode; static char *kwlist[] = {"input", "input2", "interp", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO", kwlist, &inputtmp, &input2tmp, &interptmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_XDECREF(self->input2); self->input2 = input2tmp; input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL); Py_INCREF(input2_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (Stream *)input2_streamtmp; if (interptmp) { PyObject_CallMethod((PyObject *)self, "setInterp", "O", interptmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Interp_getServer(Interp* self) { GET_SERVER }; static PyObject * Interp_getStream(Interp* self) { GET_STREAM }; static PyObject * Interp_setMul(Interp *self, PyObject *arg) { SET_MUL }; static PyObject * Interp_setAdd(Interp *self, PyObject *arg) { SET_ADD }; static PyObject * Interp_setSub(Interp *self, PyObject *arg) { SET_SUB }; static PyObject * Interp_setDiv(Interp *self, PyObject *arg) { SET_DIV }; static PyObject * Interp_play(Interp *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Interp_out(Interp *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Interp_stop(Interp *self) { STOP }; static PyObject * Interp_multiply(Interp *self, PyObject *arg) { MULTIPLY }; static PyObject * Interp_inplace_multiply(Interp *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Interp_add(Interp *self, PyObject *arg) { ADD }; static PyObject * Interp_inplace_add(Interp *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Interp_sub(Interp *self, PyObject *arg) { SUB }; static PyObject * Interp_inplace_sub(Interp *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Interp_div(Interp *self, PyObject *arg) { DIV }; static PyObject * Interp_inplace_div(Interp *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Interp_setInterp(Interp *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->interp); if (isNumber == 1) { self->interp = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->interp = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->interp, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->interp_stream); self->interp_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Interp_members[] = { {"server", T_OBJECT_EX, offsetof(Interp, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Interp, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Interp, input), 0, "Input sound object."}, {"input2", T_OBJECT_EX, offsetof(Interp, input2), 0, "Second input sound object."}, {"interp", T_OBJECT_EX, offsetof(Interp, interp), 0, "Cutoff interpuency in cycle per second."}, {"mul", T_OBJECT_EX, offsetof(Interp, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Interp, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Interp_methods[] = { {"getServer", (PyCFunction)Interp_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Interp_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Interp_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Interp_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Interp_stop, METH_NOARGS, "Stops computing."}, {"setInterp", (PyCFunction)Interp_setInterp, METH_O, "Sets filter cutoff interpuency in cycle per second."}, {"setMul", (PyCFunction)Interp_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Interp_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Interp_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Interp_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Interp_as_number = { (binaryfunc)Interp_add, /*nb_add*/ (binaryfunc)Interp_sub, /*nb_subtract*/ (binaryfunc)Interp_multiply, /*nb_multiply*/ (binaryfunc)Interp_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Interp_inplace_add, /*inplace_add*/ (binaryfunc)Interp_inplace_sub, /*inplace_subtract*/ (binaryfunc)Interp_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Interp_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject InterpType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Interp_base", /*tp_name*/ sizeof(Interp), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Interp_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Interp_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Interp objects. Interpolates between 2 audio streams.", /* tp_doc */ (traverseproc)Interp_traverse, /* tp_traverse */ (inquiry)Interp_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Interp_methods, /* tp_methods */ Interp_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Interp_new, /* tp_new */ }; /************/ /* SampHold */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *controlsig; Stream *controlsig_stream; PyObject *value; Stream *value_stream; MYFLT currentValue; int flag; int modebuffer[3]; // need at least 2 slots for mul & add } SampHold; static void SampHold_filters_i(SampHold *self) { MYFLT ctrl; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *ctrlsig = Stream_getData((Stream *)self->controlsig_stream); MYFLT val = PyFloat_AS_DOUBLE(self->value); for (i=0; ibufsize; i++) { ctrl = ctrlsig[i]; if (ctrl > (val - 0.001) && ctrl < (val + 0.001)) { if (self->flag == 1) { self->currentValue = in[i]; self->flag = 0; } } else self->flag = 1; self->data[i] = self->currentValue; } } static void SampHold_filters_a(SampHold *self) { MYFLT ctrl, val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *ctrlsig = Stream_getData((Stream *)self->controlsig_stream); MYFLT *valsig = Stream_getData((Stream *)self->value_stream); for (i=0; ibufsize; i++) { ctrl = ctrlsig[i]; val = valsig[i]; if (ctrl > (val - 0.001) && ctrl < (val + 0.001)) { if (self->flag == 1) { self->currentValue = in[i]; self->flag = 0; } } else self->flag = 1; self->data[i] = self->currentValue; } } static void SampHold_postprocessing_ii(SampHold *self) { POST_PROCESSING_II }; static void SampHold_postprocessing_ai(SampHold *self) { POST_PROCESSING_AI }; static void SampHold_postprocessing_ia(SampHold *self) { POST_PROCESSING_IA }; static void SampHold_postprocessing_aa(SampHold *self) { POST_PROCESSING_AA }; static void SampHold_postprocessing_ireva(SampHold *self) { POST_PROCESSING_IREVA }; static void SampHold_postprocessing_areva(SampHold *self) { POST_PROCESSING_AREVA }; static void SampHold_postprocessing_revai(SampHold *self) { POST_PROCESSING_REVAI }; static void SampHold_postprocessing_revaa(SampHold *self) { POST_PROCESSING_REVAA }; static void SampHold_postprocessing_revareva(SampHold *self) { POST_PROCESSING_REVAREVA }; static void SampHold_setProcMode(SampHold *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = SampHold_filters_i; break; case 1: self->proc_func_ptr = SampHold_filters_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = SampHold_postprocessing_ii; break; case 1: self->muladd_func_ptr = SampHold_postprocessing_ai; break; case 2: self->muladd_func_ptr = SampHold_postprocessing_revai; break; case 10: self->muladd_func_ptr = SampHold_postprocessing_ia; break; case 11: self->muladd_func_ptr = SampHold_postprocessing_aa; break; case 12: self->muladd_func_ptr = SampHold_postprocessing_revaa; break; case 20: self->muladd_func_ptr = SampHold_postprocessing_ireva; break; case 21: self->muladd_func_ptr = SampHold_postprocessing_areva; break; case 22: self->muladd_func_ptr = SampHold_postprocessing_revareva; break; } } static void SampHold_compute_next_data_frame(SampHold *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int SampHold_traverse(SampHold *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->controlsig); Py_VISIT(self->controlsig_stream); Py_VISIT(self->value); Py_VISIT(self->value_stream); return 0; } static int SampHold_clear(SampHold *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->controlsig); Py_CLEAR(self->controlsig_stream); Py_CLEAR(self->value); Py_CLEAR(self->value_stream); return 0; } static void SampHold_dealloc(SampHold* self) { pyo_DEALLOC SampHold_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SampHold_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *controlsigtmp, *controlsig_streamtmp, *valuetmp=NULL, *multmp=NULL, *addtmp=NULL; SampHold *self; self = (SampHold *)type->tp_alloc(type, 0); self->value = PyFloat_FromDouble(0.0); self->currentValue = 0.0; self->flag = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, SampHold_compute_next_data_frame); self->mode_func_ptr = SampHold_setProcMode; static char *kwlist[] = {"input", "controlsig", "value", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO", kwlist, &inputtmp, &controlsigtmp, &valuetmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_XDECREF(self->controlsig); self->controlsig = controlsigtmp; controlsig_streamtmp = PyObject_CallMethod((PyObject *)self->controlsig, "_getStream", NULL); Py_INCREF(controlsig_streamtmp); Py_XDECREF(self->controlsig_stream); self->controlsig_stream = (Stream *)controlsig_streamtmp; if (valuetmp) { PyObject_CallMethod((PyObject *)self, "setValue", "O", valuetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * SampHold_getServer(SampHold* self) { GET_SERVER }; static PyObject * SampHold_getStream(SampHold* self) { GET_STREAM }; static PyObject * SampHold_setMul(SampHold *self, PyObject *arg) { SET_MUL }; static PyObject * SampHold_setAdd(SampHold *self, PyObject *arg) { SET_ADD }; static PyObject * SampHold_setSub(SampHold *self, PyObject *arg) { SET_SUB }; static PyObject * SampHold_setDiv(SampHold *self, PyObject *arg) { SET_DIV }; static PyObject * SampHold_play(SampHold *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SampHold_out(SampHold *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * SampHold_stop(SampHold *self) { STOP }; static PyObject * SampHold_multiply(SampHold *self, PyObject *arg) { MULTIPLY }; static PyObject * SampHold_inplace_multiply(SampHold *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * SampHold_add(SampHold *self, PyObject *arg) { ADD }; static PyObject * SampHold_inplace_add(SampHold *self, PyObject *arg) { INPLACE_ADD }; static PyObject * SampHold_sub(SampHold *self, PyObject *arg) { SUB }; static PyObject * SampHold_inplace_sub(SampHold *self, PyObject *arg) { INPLACE_SUB }; static PyObject * SampHold_div(SampHold *self, PyObject *arg) { DIV }; static PyObject * SampHold_inplace_div(SampHold *self, PyObject *arg) { INPLACE_DIV }; static PyObject * SampHold_setValue(SampHold *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->value); if (isNumber == 1) { self->value = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->value = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->value, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->value_stream); self->value_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef SampHold_members[] = { {"server", T_OBJECT_EX, offsetof(SampHold, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SampHold, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(SampHold, input), 0, "Input sound object."}, {"controlsig", T_OBJECT_EX, offsetof(SampHold, controlsig), 0, "Control input object."}, {"value", T_OBJECT_EX, offsetof(SampHold, value), 0, "Trigger value."}, {"mul", T_OBJECT_EX, offsetof(SampHold, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(SampHold, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef SampHold_methods[] = { {"getServer", (PyCFunction)SampHold_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SampHold_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SampHold_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)SampHold_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)SampHold_stop, METH_NOARGS, "Stops computing."}, {"setValue", (PyCFunction)SampHold_setValue, METH_O, "Sets trigger value."}, {"setMul", (PyCFunction)SampHold_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)SampHold_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)SampHold_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)SampHold_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods SampHold_as_number = { (binaryfunc)SampHold_add, /*nb_add*/ (binaryfunc)SampHold_sub, /*nb_subtract*/ (binaryfunc)SampHold_multiply, /*nb_multiply*/ (binaryfunc)SampHold_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)SampHold_inplace_add, /*inplace_add*/ (binaryfunc)SampHold_inplace_sub, /*inplace_subtract*/ (binaryfunc)SampHold_inplace_multiply, /*inplace_multiply*/ (binaryfunc)SampHold_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SampHoldType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SampHold_base", /*tp_name*/ sizeof(SampHold), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SampHold_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &SampHold_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SampHold objects. SampHoldolates between 2 audio streams.", /* tp_doc */ (traverseproc)SampHold_traverse, /* tp_traverse */ (inquiry)SampHold_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SampHold_methods, /* tp_methods */ SampHold_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SampHold_new, /* tp_new */ }; /************/ /* TrackHold */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *controlsig; Stream *controlsig_stream; PyObject *value; Stream *value_stream; MYFLT currentValue; int flag; int modebuffer[3]; // need at least 2 slots for mul & add } TrackHold; static void TrackHold_filters_i(TrackHold *self) { MYFLT ctrl; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *ctrlsig = Stream_getData((Stream *)self->controlsig_stream); MYFLT val = PyFloat_AS_DOUBLE(self->value); for (i=0; ibufsize; i++) { ctrl = ctrlsig[i]; if (ctrl > (val - 0.0001) && ctrl < (val + 0.0001)) { if (self->flag == 1) { self->currentValue = in[i]; self->flag = 0; } } else { self->currentValue = in[i]; self->flag = 1; } self->data[i] = self->currentValue; } } static void TrackHold_filters_a(TrackHold *self) { MYFLT ctrl, val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *ctrlsig = Stream_getData((Stream *)self->controlsig_stream); MYFLT *valsig = Stream_getData((Stream *)self->value_stream); for (i=0; ibufsize; i++) { ctrl = ctrlsig[i]; val = valsig[i]; if (ctrl > (val - 0.0001) && ctrl < (val + 0.0001)) { if (self->flag == 1) { self->currentValue = in[i]; self->flag = 0; } } else { self->currentValue = in[i]; self->flag = 1; } self->data[i] = self->currentValue; } } static void TrackHold_postprocessing_ii(TrackHold *self) { POST_PROCESSING_II }; static void TrackHold_postprocessing_ai(TrackHold *self) { POST_PROCESSING_AI }; static void TrackHold_postprocessing_ia(TrackHold *self) { POST_PROCESSING_IA }; static void TrackHold_postprocessing_aa(TrackHold *self) { POST_PROCESSING_AA }; static void TrackHold_postprocessing_ireva(TrackHold *self) { POST_PROCESSING_IREVA }; static void TrackHold_postprocessing_areva(TrackHold *self) { POST_PROCESSING_AREVA }; static void TrackHold_postprocessing_revai(TrackHold *self) { POST_PROCESSING_REVAI }; static void TrackHold_postprocessing_revaa(TrackHold *self) { POST_PROCESSING_REVAA }; static void TrackHold_postprocessing_revareva(TrackHold *self) { POST_PROCESSING_REVAREVA }; static void TrackHold_setProcMode(TrackHold *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = TrackHold_filters_i; break; case 1: self->proc_func_ptr = TrackHold_filters_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = TrackHold_postprocessing_ii; break; case 1: self->muladd_func_ptr = TrackHold_postprocessing_ai; break; case 2: self->muladd_func_ptr = TrackHold_postprocessing_revai; break; case 10: self->muladd_func_ptr = TrackHold_postprocessing_ia; break; case 11: self->muladd_func_ptr = TrackHold_postprocessing_aa; break; case 12: self->muladd_func_ptr = TrackHold_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TrackHold_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TrackHold_postprocessing_areva; break; case 22: self->muladd_func_ptr = TrackHold_postprocessing_revareva; break; } } static void TrackHold_compute_next_data_frame(TrackHold *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int TrackHold_traverse(TrackHold *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->controlsig); Py_VISIT(self->controlsig_stream); Py_VISIT(self->value); Py_VISIT(self->value_stream); return 0; } static int TrackHold_clear(TrackHold *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->controlsig); Py_CLEAR(self->controlsig_stream); Py_CLEAR(self->value); Py_CLEAR(self->value_stream); return 0; } static void TrackHold_dealloc(TrackHold* self) { pyo_DEALLOC TrackHold_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TrackHold_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *controlsigtmp, *controlsig_streamtmp, *valuetmp=NULL, *multmp=NULL, *addtmp=NULL; TrackHold *self; self = (TrackHold *)type->tp_alloc(type, 0); self->value = PyFloat_FromDouble(0.0); self->currentValue = 0.0; self->flag = 1; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TrackHold_compute_next_data_frame); self->mode_func_ptr = TrackHold_setProcMode; static char *kwlist[] = {"input", "controlsig", "value", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO", kwlist, &inputtmp, &controlsigtmp, &valuetmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_XDECREF(self->controlsig); self->controlsig = controlsigtmp; controlsig_streamtmp = PyObject_CallMethod((PyObject *)self->controlsig, "_getStream", NULL); Py_INCREF(controlsig_streamtmp); Py_XDECREF(self->controlsig_stream); self->controlsig_stream = (Stream *)controlsig_streamtmp; if (valuetmp) { PyObject_CallMethod((PyObject *)self, "setValue", "O", valuetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TrackHold_getServer(TrackHold* self) { GET_SERVER }; static PyObject * TrackHold_getStream(TrackHold* self) { GET_STREAM }; static PyObject * TrackHold_setMul(TrackHold *self, PyObject *arg) { SET_MUL }; static PyObject * TrackHold_setAdd(TrackHold *self, PyObject *arg) { SET_ADD }; static PyObject * TrackHold_setSub(TrackHold *self, PyObject *arg) { SET_SUB }; static PyObject * TrackHold_setDiv(TrackHold *self, PyObject *arg) { SET_DIV }; static PyObject * TrackHold_play(TrackHold *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TrackHold_out(TrackHold *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TrackHold_stop(TrackHold *self) { STOP }; static PyObject * TrackHold_multiply(TrackHold *self, PyObject *arg) { MULTIPLY }; static PyObject * TrackHold_inplace_multiply(TrackHold *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TrackHold_add(TrackHold *self, PyObject *arg) { ADD }; static PyObject * TrackHold_inplace_add(TrackHold *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TrackHold_sub(TrackHold *self, PyObject *arg) { SUB }; static PyObject * TrackHold_inplace_sub(TrackHold *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TrackHold_div(TrackHold *self, PyObject *arg) { DIV }; static PyObject * TrackHold_inplace_div(TrackHold *self, PyObject *arg) { INPLACE_DIV }; static PyObject * TrackHold_setValue(TrackHold *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->value); if (isNumber == 1) { self->value = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->value = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->value, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->value_stream); self->value_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef TrackHold_members[] = { {"server", T_OBJECT_EX, offsetof(TrackHold, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TrackHold, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(TrackHold, input), 0, "Input sound object."}, {"controlsig", T_OBJECT_EX, offsetof(TrackHold, controlsig), 0, "Control input object."}, {"value", T_OBJECT_EX, offsetof(TrackHold, value), 0, "Trigger value."}, {"mul", T_OBJECT_EX, offsetof(TrackHold, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TrackHold, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TrackHold_methods[] = { {"getServer", (PyCFunction)TrackHold_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TrackHold_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TrackHold_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)TrackHold_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)TrackHold_stop, METH_NOARGS, "Stops computing."}, {"setValue", (PyCFunction)TrackHold_setValue, METH_O, "Sets trigger value."}, {"setMul", (PyCFunction)TrackHold_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TrackHold_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TrackHold_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TrackHold_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TrackHold_as_number = { (binaryfunc)TrackHold_add, /*nb_add*/ (binaryfunc)TrackHold_sub, /*nb_subtract*/ (binaryfunc)TrackHold_multiply, /*nb_multiply*/ (binaryfunc)TrackHold_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TrackHold_inplace_add, /*inplace_add*/ (binaryfunc)TrackHold_inplace_sub, /*inplace_subtract*/ (binaryfunc)TrackHold_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TrackHold_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TrackHoldType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TrackHold_base", /*tp_name*/ sizeof(TrackHold), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TrackHold_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TrackHold_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TrackHold objects. Let pass and freeze an audio stream.", /* tp_doc */ (traverseproc)TrackHold_traverse, /* tp_traverse */ (inquiry)TrackHold_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TrackHold_methods, /* tp_methods */ TrackHold_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TrackHold_new, /* tp_new */ }; /************/ /* Compare */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *comp; Stream *comp_stream; MYFLT (*compare_func_ptr)(MYFLT, MYFLT); // true = 1.0, false = 0.0 int modebuffer[3]; // need at least 2 slots for mul & add } Compare; static MYFLT Compare_lt(MYFLT in, MYFLT comp) { if (in < comp) { return 1.0; } else { return 0.0; } } static MYFLT Compare_elt(MYFLT in, MYFLT comp) { if (in <= comp) { return 1.0; } else { return 0.0; } } static MYFLT Compare_gt(MYFLT in, MYFLT comp) { if (in > comp) { return 1.0; } else { return 0.0; } } static MYFLT Compare_egt(MYFLT in, MYFLT comp) { if (in >= comp) { return 1.0; } else { return 0.0; } } static MYFLT Compare_eq(MYFLT in, MYFLT comp) { if (in >= (comp - 0.0001) && in <= (comp + 0.0001)) { return 1.0; } else { return 0.0; } } static MYFLT Compare_neq(MYFLT in, MYFLT comp) { if (in <= (comp - 0.0001) || in >= (comp + 0.0001)) { return 1.0; } else { return 0.0; } } static void Compare_process_i(Compare *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT comp = PyFloat_AS_DOUBLE(self->comp); for (i=0; ibufsize; i++) { self->data[i] = (*self->compare_func_ptr)(in[i], comp); } } static void Compare_process_a(Compare *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *comp = Stream_getData((Stream *)self->comp_stream); for (i=0; ibufsize; i++) { self->data[i] = (*self->compare_func_ptr)(in[i], comp[i]); } } static void Compare_postprocessing_ii(Compare *self) { POST_PROCESSING_II }; static void Compare_postprocessing_ai(Compare *self) { POST_PROCESSING_AI }; static void Compare_postprocessing_ia(Compare *self) { POST_PROCESSING_IA }; static void Compare_postprocessing_aa(Compare *self) { POST_PROCESSING_AA }; static void Compare_postprocessing_ireva(Compare *self) { POST_PROCESSING_IREVA }; static void Compare_postprocessing_areva(Compare *self) { POST_PROCESSING_AREVA }; static void Compare_postprocessing_revai(Compare *self) { POST_PROCESSING_REVAI }; static void Compare_postprocessing_revaa(Compare *self) { POST_PROCESSING_REVAA }; static void Compare_postprocessing_revareva(Compare *self) { POST_PROCESSING_REVAREVA }; static void Compare_setProcMode(Compare *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Compare_process_i; break; case 1: self->proc_func_ptr = Compare_process_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Compare_postprocessing_ii; break; case 1: self->muladd_func_ptr = Compare_postprocessing_ai; break; case 2: self->muladd_func_ptr = Compare_postprocessing_revai; break; case 10: self->muladd_func_ptr = Compare_postprocessing_ia; break; case 11: self->muladd_func_ptr = Compare_postprocessing_aa; break; case 12: self->muladd_func_ptr = Compare_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Compare_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Compare_postprocessing_areva; break; case 22: self->muladd_func_ptr = Compare_postprocessing_revareva; break; } } static void Compare_compute_next_data_frame(Compare *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Compare_traverse(Compare *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->comp); Py_VISIT(self->comp_stream); return 0; } static int Compare_clear(Compare *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->comp); Py_CLEAR(self->comp_stream); return 0; } static void Compare_dealloc(Compare* self) { pyo_DEALLOC Compare_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Compare_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *comptmp, *modetmp=NULL, *multmp=NULL, *addtmp=NULL; Compare *self; self = (Compare *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->compare_func_ptr = Compare_lt; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Compare_compute_next_data_frame); self->mode_func_ptr = Compare_setProcMode; static char *kwlist[] = {"input", "comp", "mode", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO", kwlist, &inputtmp, &comptmp, &modetmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (comptmp) { PyObject_CallMethod((PyObject *)self, "setComp", "O", comptmp); } if (modetmp) { PyObject_CallMethod((PyObject *)self, "setMode", "O", modetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Compare_getServer(Compare* self) { GET_SERVER }; static PyObject * Compare_getStream(Compare* self) { GET_STREAM }; static PyObject * Compare_setMul(Compare *self, PyObject *arg) { SET_MUL }; static PyObject * Compare_setAdd(Compare *self, PyObject *arg) { SET_ADD }; static PyObject * Compare_setSub(Compare *self, PyObject *arg) { SET_SUB }; static PyObject * Compare_setDiv(Compare *self, PyObject *arg) { SET_DIV }; static PyObject * Compare_play(Compare *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Compare_stop(Compare *self) { STOP }; static PyObject * Compare_multiply(Compare *self, PyObject *arg) { MULTIPLY }; static PyObject * Compare_inplace_multiply(Compare *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Compare_add(Compare *self, PyObject *arg) { ADD }; static PyObject * Compare_inplace_add(Compare *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Compare_sub(Compare *self, PyObject *arg) { SUB }; static PyObject * Compare_inplace_sub(Compare *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Compare_div(Compare *self, PyObject *arg) { DIV }; static PyObject * Compare_inplace_div(Compare *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Compare_setComp(Compare *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_XDECREF(self->comp); if (isNumber == 1) { self->comp = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->comp = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->comp, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->comp_stream); self->comp_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Compare_setMode(Compare *self, PyObject *arg) { ASSERT_ARG_NOT_NULL if (! PyInt_Check(arg)) { printf("mode should be a comparison operator as a string\n"); Py_RETURN_NONE; } int tmp = PyInt_AsLong(arg); if (tmp == 0) self->compare_func_ptr = Compare_lt; else if (tmp == 1) self->compare_func_ptr = Compare_elt; else if (tmp == 2) self->compare_func_ptr = Compare_gt; else if (tmp == 3) self->compare_func_ptr = Compare_egt; else if (tmp == 4) self->compare_func_ptr = Compare_eq; else if (tmp == 5) self->compare_func_ptr = Compare_neq; Py_RETURN_NONE; } static PyMemberDef Compare_members[] = { {"server", T_OBJECT_EX, offsetof(Compare, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Compare, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Compare, input), 0, "Input sound object."}, {"comp", T_OBJECT_EX, offsetof(Compare, comp), 0, "Comparison object."}, {"mul", T_OBJECT_EX, offsetof(Compare, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Compare, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Compare_methods[] = { {"getServer", (PyCFunction)Compare_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Compare_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Compare_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Compare_stop, METH_NOARGS, "Stops computing."}, {"setComp", (PyCFunction)Compare_setComp, METH_O, "Sets the comparison object."}, {"setMode", (PyCFunction)Compare_setMode, METH_O, "Sets the comparison mode."}, {"setMul", (PyCFunction)Compare_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)Compare_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)Compare_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Compare_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Compare_as_number = { (binaryfunc)Compare_add, /*nb_add*/ (binaryfunc)Compare_sub, /*nb_subtract*/ (binaryfunc)Compare_multiply, /*nb_multiply*/ (binaryfunc)Compare_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Compare_inplace_add, /*inplace_add*/ (binaryfunc)Compare_inplace_sub, /*inplace_subtract*/ (binaryfunc)Compare_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Compare_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject CompareType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Compare_base", /*tp_name*/ sizeof(Compare), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Compare_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Compare_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Compare objects. Comparison between 2 audio streams.", /* tp_doc */ (traverseproc)Compare_traverse, /* tp_traverse */ (inquiry)Compare_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Compare_methods, /* tp_methods */ Compare_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Compare_new, /* tp_new */ }; /*****************/ /** Between object **/ /*****************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *min; Stream *min_stream; PyObject *max; Stream *max_stream; int modebuffer[4]; } Between; static void Between_transform_ii(Between *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT ma = PyFloat_AS_DOUBLE(self->max); for (i=0; ibufsize; i++) { val = in[i]; if(val >= mi && val < ma) self->data[i] = 1.0; else self->data[i] = 0.0; } } static void Between_transform_ai(Between *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT ma = PyFloat_AS_DOUBLE(self->max); for (i=0; ibufsize; i++) { val = in[i]; if(val >= mi[i] && val < ma) self->data[i] = 1.0; else self->data[i] = 0.0; } } static void Between_transform_ia(Between *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT mi = PyFloat_AS_DOUBLE(self->min); MYFLT *ma = Stream_getData((Stream *)self->max_stream); for (i=0; ibufsize; i++) { val = in[i]; if(val >= mi && val < ma[i]) self->data[i] = 1.0; else self->data[i] = 0.0; } } static void Between_transform_aa(Between *self) { MYFLT val; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *mi = Stream_getData((Stream *)self->min_stream); MYFLT *ma = Stream_getData((Stream *)self->max_stream); for (i=0; ibufsize; i++) { val = in[i]; if(val >= mi[i] && val < ma[i]) self->data[i] = 1.0; else self->data[i] = 0.0; } } static void Between_postprocessing_ii(Between *self) { POST_PROCESSING_II }; static void Between_postprocessing_ai(Between *self) { POST_PROCESSING_AI }; static void Between_postprocessing_ia(Between *self) { POST_PROCESSING_IA }; static void Between_postprocessing_aa(Between *self) { POST_PROCESSING_AA }; static void Between_postprocessing_ireva(Between *self) { POST_PROCESSING_IREVA }; static void Between_postprocessing_areva(Between *self) { POST_PROCESSING_AREVA }; static void Between_postprocessing_revai(Between *self) { POST_PROCESSING_REVAI }; static void Between_postprocessing_revaa(Between *self) { POST_PROCESSING_REVAA }; static void Between_postprocessing_revareva(Between *self) { POST_PROCESSING_REVAREVA }; static void Between_setProcMode(Between *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Between_transform_ii; break; case 1: self->proc_func_ptr = Between_transform_ai; break; case 10: self->proc_func_ptr = Between_transform_ia; break; case 11: self->proc_func_ptr = Between_transform_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Between_postprocessing_ii; break; case 1: self->muladd_func_ptr = Between_postprocessing_ai; break; case 2: self->muladd_func_ptr = Between_postprocessing_revai; break; case 10: self->muladd_func_ptr = Between_postprocessing_ia; break; case 11: self->muladd_func_ptr = Between_postprocessing_aa; break; case 12: self->muladd_func_ptr = Between_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Between_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Between_postprocessing_areva; break; case 22: self->muladd_func_ptr = Between_postprocessing_revareva; break; } } static void Between_compute_next_data_frame(Between *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Between_traverse(Between *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->min); Py_VISIT(self->min_stream); Py_VISIT(self->max); Py_VISIT(self->max_stream); return 0; } static int Between_clear(Between *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->min); Py_CLEAR(self->min_stream); Py_CLEAR(self->max); Py_CLEAR(self->max_stream); return 0; } static void Between_dealloc(Between* self) { pyo_DEALLOC Between_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Between_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL; Between *self; self = (Between *)type->tp_alloc(type, 0); self->min = PyFloat_FromDouble(0.0); self->max = PyFloat_FromDouble(1.0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Between_compute_next_data_frame); self->mode_func_ptr = Between_setProcMode; static char *kwlist[] = {"input", "min", "max", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &mintmp, &maxtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (mintmp) { PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp); } if (maxtmp) { PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Between_getServer(Between* self) { GET_SERVER }; static PyObject * Between_getStream(Between* self) { GET_STREAM }; static PyObject * Between_setMul(Between *self, PyObject *arg) { SET_MUL }; static PyObject * Between_setAdd(Between *self, PyObject *arg) { SET_ADD }; static PyObject * Between_setSub(Between *self, PyObject *arg) { SET_SUB }; static PyObject * Between_setDiv(Between *self, PyObject *arg) { SET_DIV }; static PyObject * Between_play(Between *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Between_out(Between *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Between_stop(Between *self) { STOP }; static PyObject * Between_multiply(Between *self, PyObject *arg) { MULTIPLY }; static PyObject * Between_inplace_multiply(Between *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Between_add(Between *self, PyObject *arg) { ADD }; static PyObject * Between_inplace_add(Between *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Between_sub(Between *self, PyObject *arg) { SUB }; static PyObject * Between_inplace_sub(Between *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Between_div(Between *self, PyObject *arg) { DIV }; static PyObject * Between_inplace_div(Between *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Between_setMin(Between *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->min); if (isNumber == 1) { self->min = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->min = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->min, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->min_stream); self->min_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Between_setMax(Between *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->max); if (isNumber == 1) { self->max = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->max = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->max_stream); self->max_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Between_members[] = { {"server", T_OBJECT_EX, offsetof(Between, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Between, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Between, input), 0, "Input sound object."}, {"min", T_OBJECT_EX, offsetof(Between, min), 0, "Minimum possible value."}, {"max", T_OBJECT_EX, offsetof(Between, max), 0, "Maximum possible value."}, {"mul", T_OBJECT_EX, offsetof(Between, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Between, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Between_methods[] = { {"getServer", (PyCFunction)Between_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Between_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Between_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Between_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Between_stop, METH_NOARGS, "Stops computing."}, {"setMin", (PyCFunction)Between_setMin, METH_O, "Sets the minimum value."}, {"setMax", (PyCFunction)Between_setMax, METH_O, "Sets the maximum value."}, {"setMul", (PyCFunction)Between_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Between_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Between_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Between_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Between_as_number = { (binaryfunc)Between_add, /*nb_add*/ (binaryfunc)Between_sub, /*nb_subtract*/ (binaryfunc)Between_multiply, /*nb_multiply*/ (binaryfunc)Between_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Between_inplace_add, /*inplace_add*/ (binaryfunc)Between_inplace_sub, /*inplace_subtract*/ (binaryfunc)Between_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Between_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject BetweenType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Between_base", /*tp_name*/ sizeof(Between), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Between_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Between_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Between objects. Outputs a trig if signal is between min and max values.", /* tp_doc */ (traverseproc)Between_traverse, /* tp_traverse */ (inquiry)Between_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Between_methods, /* tp_methods */ Between_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Between_new, /* tp_new */ }; /************/ /* Denorm */ /************/ #ifndef USE_DOUBLE #define DENORM_RAND ((MYFLT) ((rand()/((MYFLT)(RAND_MAX)*0.5+1) - 1.0) * (MYFLT)(1.0e-24))) #else #define DENORM_RAND ((MYFLT) ((rand()/((MYFLT)(RAND_MAX)*0.5+1) - 1.0) * (MYFLT)(1.0e-60))) #endif typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; int modebuffer[2]; // need at least 2 slots for mul & add } Denorm; static void Denorm_filters(Denorm *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->data[i] = in[i] + DENORM_RAND; } } static void Denorm_postprocessing_ii(Denorm *self) { POST_PROCESSING_II }; static void Denorm_postprocessing_ai(Denorm *self) { POST_PROCESSING_AI }; static void Denorm_postprocessing_ia(Denorm *self) { POST_PROCESSING_IA }; static void Denorm_postprocessing_aa(Denorm *self) { POST_PROCESSING_AA }; static void Denorm_postprocessing_ireva(Denorm *self) { POST_PROCESSING_IREVA }; static void Denorm_postprocessing_areva(Denorm *self) { POST_PROCESSING_AREVA }; static void Denorm_postprocessing_revai(Denorm *self) { POST_PROCESSING_REVAI }; static void Denorm_postprocessing_revaa(Denorm *self) { POST_PROCESSING_REVAA }; static void Denorm_postprocessing_revareva(Denorm *self) { POST_PROCESSING_REVAREVA }; static void Denorm_setProcMode(Denorm *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Denorm_filters; switch (muladdmode) { case 0: self->muladd_func_ptr = Denorm_postprocessing_ii; break; case 1: self->muladd_func_ptr = Denorm_postprocessing_ai; break; case 2: self->muladd_func_ptr = Denorm_postprocessing_revai; break; case 10: self->muladd_func_ptr = Denorm_postprocessing_ia; break; case 11: self->muladd_func_ptr = Denorm_postprocessing_aa; break; case 12: self->muladd_func_ptr = Denorm_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Denorm_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Denorm_postprocessing_areva; break; case 22: self->muladd_func_ptr = Denorm_postprocessing_revareva; break; } } static void Denorm_compute_next_data_frame(Denorm *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Denorm_traverse(Denorm *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Denorm_clear(Denorm *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Denorm_dealloc(Denorm* self) { pyo_DEALLOC Denorm_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Denorm_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; Denorm *self; self = (Denorm *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Denorm_compute_next_data_frame); self->mode_func_ptr = Denorm_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Server_generateSeed((Server *)self->server, DENORM_ID); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Denorm_getServer(Denorm* self) { GET_SERVER }; static PyObject * Denorm_getStream(Denorm* self) { GET_STREAM }; static PyObject * Denorm_setMul(Denorm *self, PyObject *arg) { SET_MUL }; static PyObject * Denorm_setAdd(Denorm *self, PyObject *arg) { SET_ADD }; static PyObject * Denorm_setSub(Denorm *self, PyObject *arg) { SET_SUB }; static PyObject * Denorm_setDiv(Denorm *self, PyObject *arg) { SET_DIV }; static PyObject * Denorm_play(Denorm *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Denorm_out(Denorm *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Denorm_stop(Denorm *self) { STOP }; static PyObject * Denorm_multiply(Denorm *self, PyObject *arg) { MULTIPLY }; static PyObject * Denorm_inplace_multiply(Denorm *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Denorm_add(Denorm *self, PyObject *arg) { ADD }; static PyObject * Denorm_inplace_add(Denorm *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Denorm_sub(Denorm *self, PyObject *arg) { SUB }; static PyObject * Denorm_inplace_sub(Denorm *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Denorm_div(Denorm *self, PyObject *arg) { DIV }; static PyObject * Denorm_inplace_div(Denorm *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Denorm_members[] = { {"server", T_OBJECT_EX, offsetof(Denorm, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Denorm, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Denorm, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(Denorm, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Denorm, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Denorm_methods[] = { {"getServer", (PyCFunction)Denorm_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Denorm_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Denorm_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Denorm_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Denorm_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Denorm_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Denorm_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Denorm_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Denorm_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Denorm_as_number = { (binaryfunc)Denorm_add, /*nb_add*/ (binaryfunc)Denorm_sub, /*nb_subtract*/ (binaryfunc)Denorm_multiply, /*nb_multiply*/ (binaryfunc)Denorm_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Denorm_inplace_add, /*inplace_add*/ (binaryfunc)Denorm_inplace_sub, /*inplace_subtract*/ (binaryfunc)Denorm_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Denorm_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject DenormType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Denorm_base", /*tp_name*/ sizeof(Denorm), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Denorm_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Denorm_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Denorm objects. Mixes low level noise to an input signal.", /* tp_doc */ (traverseproc)Denorm_traverse, /* tp_traverse */ (inquiry)Denorm_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Denorm_methods, /* tp_methods */ Denorm_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Denorm_new, /* tp_new */ }; /************/ /* DBToA */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; MYFLT lastdb; MYFLT currentamp; int modebuffer[2]; // need at least 2 slots for mul & add } DBToA; static void DBToA_process(DBToA *self) { int i; MYFLT db; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { db = in[i]; if (db <= -120.0) { self->data[i] = self->currentamp = 0.0; self->lastdb = -120.0; } else if (db != self->lastdb) { self->data[i] = self->currentamp = MYPOW(10.0, db * 0.05); self->lastdb = db; } else self->data[i] = self->currentamp; } } static void DBToA_postprocessing_ii(DBToA *self) { POST_PROCESSING_II }; static void DBToA_postprocessing_ai(DBToA *self) { POST_PROCESSING_AI }; static void DBToA_postprocessing_ia(DBToA *self) { POST_PROCESSING_IA }; static void DBToA_postprocessing_aa(DBToA *self) { POST_PROCESSING_AA }; static void DBToA_postprocessing_ireva(DBToA *self) { POST_PROCESSING_IREVA }; static void DBToA_postprocessing_areva(DBToA *self) { POST_PROCESSING_AREVA }; static void DBToA_postprocessing_revai(DBToA *self) { POST_PROCESSING_REVAI }; static void DBToA_postprocessing_revaa(DBToA *self) { POST_PROCESSING_REVAA }; static void DBToA_postprocessing_revareva(DBToA *self) { POST_PROCESSING_REVAREVA }; static void DBToA_setProcMode(DBToA *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = DBToA_process; switch (muladdmode) { case 0: self->muladd_func_ptr = DBToA_postprocessing_ii; break; case 1: self->muladd_func_ptr = DBToA_postprocessing_ai; break; case 2: self->muladd_func_ptr = DBToA_postprocessing_revai; break; case 10: self->muladd_func_ptr = DBToA_postprocessing_ia; break; case 11: self->muladd_func_ptr = DBToA_postprocessing_aa; break; case 12: self->muladd_func_ptr = DBToA_postprocessing_revaa; break; case 20: self->muladd_func_ptr = DBToA_postprocessing_ireva; break; case 21: self->muladd_func_ptr = DBToA_postprocessing_areva; break; case 22: self->muladd_func_ptr = DBToA_postprocessing_revareva; break; } } static void DBToA_compute_next_data_frame(DBToA *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int DBToA_traverse(DBToA *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int DBToA_clear(DBToA *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void DBToA_dealloc(DBToA* self) { pyo_DEALLOC DBToA_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * DBToA_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; DBToA *self; self = (DBToA *)type->tp_alloc(type, 0); self->lastdb = -120.0; self->currentamp = MYPOW(10.0, self->lastdb * 0.05); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, DBToA_compute_next_data_frame); self->mode_func_ptr = DBToA_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * DBToA_getServer(DBToA* self) { GET_SERVER }; static PyObject * DBToA_getStream(DBToA* self) { GET_STREAM }; static PyObject * DBToA_setMul(DBToA *self, PyObject *arg) { SET_MUL }; static PyObject * DBToA_setAdd(DBToA *self, PyObject *arg) { SET_ADD }; static PyObject * DBToA_setSub(DBToA *self, PyObject *arg) { SET_SUB }; static PyObject * DBToA_setDiv(DBToA *self, PyObject *arg) { SET_DIV }; static PyObject * DBToA_play(DBToA *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * DBToA_out(DBToA *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * DBToA_stop(DBToA *self) { STOP }; static PyObject * DBToA_multiply(DBToA *self, PyObject *arg) { MULTIPLY }; static PyObject * DBToA_inplace_multiply(DBToA *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * DBToA_add(DBToA *self, PyObject *arg) { ADD }; static PyObject * DBToA_inplace_add(DBToA *self, PyObject *arg) { INPLACE_ADD }; static PyObject * DBToA_sub(DBToA *self, PyObject *arg) { SUB }; static PyObject * DBToA_inplace_sub(DBToA *self, PyObject *arg) { INPLACE_SUB }; static PyObject * DBToA_div(DBToA *self, PyObject *arg) { DIV }; static PyObject * DBToA_inplace_div(DBToA *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef DBToA_members[] = { {"server", T_OBJECT_EX, offsetof(DBToA, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(DBToA, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(DBToA, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(DBToA, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(DBToA, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef DBToA_methods[] = { {"getServer", (PyCFunction)DBToA_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)DBToA_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)DBToA_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)DBToA_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)DBToA_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)DBToA_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)DBToA_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)DBToA_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)DBToA_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods DBToA_as_number = { (binaryfunc)DBToA_add, /*nb_add*/ (binaryfunc)DBToA_sub, /*nb_subtract*/ (binaryfunc)DBToA_multiply, /*nb_multiply*/ (binaryfunc)DBToA_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)DBToA_inplace_add, /*inplace_add*/ (binaryfunc)DBToA_inplace_sub, /*inplace_subtract*/ (binaryfunc)DBToA_inplace_multiply, /*inplace_multiply*/ (binaryfunc)DBToA_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject DBToAType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.DBToA_base", /*tp_name*/ sizeof(DBToA), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)DBToA_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &DBToA_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "DBToA objects. Converts dB value to amplitude value.", /* tp_doc */ (traverseproc)DBToA_traverse, /* tp_traverse */ (inquiry)DBToA_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ DBToA_methods, /* tp_methods */ DBToA_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ DBToA_new, /* tp_new */ }; /************/ /* AToDB */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; MYFLT lastamp; MYFLT currentdb; int modebuffer[2]; // need at least 2 slots for mul & add } AToDB; static void AToDB_process(AToDB *self) { int i; MYFLT amp; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { amp = in[i]; if (amp <= 0.000001) { self->data[i] = self->currentdb = -120.0; self->lastamp = 0.000001; } else if (amp != self->lastamp) { self->data[i] = self->currentdb = 20.0 * MYLOG10(amp); self->lastamp = amp; } else self->data[i] = self->currentdb; } } static void AToDB_postprocessing_ii(AToDB *self) { POST_PROCESSING_II }; static void AToDB_postprocessing_ai(AToDB *self) { POST_PROCESSING_AI }; static void AToDB_postprocessing_ia(AToDB *self) { POST_PROCESSING_IA }; static void AToDB_postprocessing_aa(AToDB *self) { POST_PROCESSING_AA }; static void AToDB_postprocessing_ireva(AToDB *self) { POST_PROCESSING_IREVA }; static void AToDB_postprocessing_areva(AToDB *self) { POST_PROCESSING_AREVA }; static void AToDB_postprocessing_revai(AToDB *self) { POST_PROCESSING_REVAI }; static void AToDB_postprocessing_revaa(AToDB *self) { POST_PROCESSING_REVAA }; static void AToDB_postprocessing_revareva(AToDB *self) { POST_PROCESSING_REVAREVA }; static void AToDB_setProcMode(AToDB *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = AToDB_process; switch (muladdmode) { case 0: self->muladd_func_ptr = AToDB_postprocessing_ii; break; case 1: self->muladd_func_ptr = AToDB_postprocessing_ai; break; case 2: self->muladd_func_ptr = AToDB_postprocessing_revai; break; case 10: self->muladd_func_ptr = AToDB_postprocessing_ia; break; case 11: self->muladd_func_ptr = AToDB_postprocessing_aa; break; case 12: self->muladd_func_ptr = AToDB_postprocessing_revaa; break; case 20: self->muladd_func_ptr = AToDB_postprocessing_ireva; break; case 21: self->muladd_func_ptr = AToDB_postprocessing_areva; break; case 22: self->muladd_func_ptr = AToDB_postprocessing_revareva; break; } } static void AToDB_compute_next_data_frame(AToDB *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int AToDB_traverse(AToDB *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int AToDB_clear(AToDB *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void AToDB_dealloc(AToDB* self) { pyo_DEALLOC AToDB_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * AToDB_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; AToDB *self; self = (AToDB *)type->tp_alloc(type, 0); self->lastamp = 0.000001; self->currentdb = 20.0 * MYLOG10(self->lastamp); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, AToDB_compute_next_data_frame); self->mode_func_ptr = AToDB_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * AToDB_getServer(AToDB* self) { GET_SERVER }; static PyObject * AToDB_getStream(AToDB* self) { GET_STREAM }; static PyObject * AToDB_setMul(AToDB *self, PyObject *arg) { SET_MUL }; static PyObject * AToDB_setAdd(AToDB *self, PyObject *arg) { SET_ADD }; static PyObject * AToDB_setSub(AToDB *self, PyObject *arg) { SET_SUB }; static PyObject * AToDB_setDiv(AToDB *self, PyObject *arg) { SET_DIV }; static PyObject * AToDB_play(AToDB *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * AToDB_out(AToDB *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * AToDB_stop(AToDB *self) { STOP }; static PyObject * AToDB_multiply(AToDB *self, PyObject *arg) { MULTIPLY }; static PyObject * AToDB_inplace_multiply(AToDB *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * AToDB_add(AToDB *self, PyObject *arg) { ADD }; static PyObject * AToDB_inplace_add(AToDB *self, PyObject *arg) { INPLACE_ADD }; static PyObject * AToDB_sub(AToDB *self, PyObject *arg) { SUB }; static PyObject * AToDB_inplace_sub(AToDB *self, PyObject *arg) { INPLACE_SUB }; static PyObject * AToDB_div(AToDB *self, PyObject *arg) { DIV }; static PyObject * AToDB_inplace_div(AToDB *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef AToDB_members[] = { {"server", T_OBJECT_EX, offsetof(AToDB, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(AToDB, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(AToDB, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(AToDB, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(AToDB, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef AToDB_methods[] = { {"getServer", (PyCFunction)AToDB_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)AToDB_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)AToDB_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)AToDB_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)AToDB_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)AToDB_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)AToDB_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)AToDB_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)AToDB_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods AToDB_as_number = { (binaryfunc)AToDB_add, /*nb_add*/ (binaryfunc)AToDB_sub, /*nb_subtract*/ (binaryfunc)AToDB_multiply, /*nb_multiply*/ (binaryfunc)AToDB_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)AToDB_inplace_add, /*inplace_add*/ (binaryfunc)AToDB_inplace_sub, /*inplace_subtract*/ (binaryfunc)AToDB_inplace_multiply, /*inplace_multiply*/ (binaryfunc)AToDB_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject AToDBType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.AToDB_base", /*tp_name*/ sizeof(AToDB), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)AToDB_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &AToDB_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "AToDB objects. Converts dB value to amplitude value.", /* tp_doc */ (traverseproc)AToDB_traverse, /* tp_traverse */ (inquiry)AToDB_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ AToDB_methods, /* tp_methods */ AToDB_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ AToDB_new, /* tp_new */ }; /*********************************************************************************************/ /* Scale ********************************************************************************/ /*********************************************************************************************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *inmin; Stream *inmin_stream; PyObject *inmax; Stream *inmax_stream; PyObject *outmin; Stream *outmin_stream; PyObject *outmax; Stream *outmax_stream; PyObject *exp; Stream *exp_stream; int modebuffer[7]; // need at least 2 slots for mul & add } Scale; static MYFLT _scale_clip(MYFLT x, MYFLT min, MYFLT max) { if (x < min) return min; else if (x > max) return max; else return x; } static void Scale_generate(Scale *self) { int i, inrev, outrev; MYFLT tmp, inrange, outrange, normin; MYFLT inmin, inmax, outmin, outmax, exp; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->modebuffer[2] == 0) inmin = PyFloat_AS_DOUBLE(self->inmin); else inmin = Stream_getData((Stream *)self->inmin_stream)[0]; if (self->modebuffer[3] == 0) inmax = PyFloat_AS_DOUBLE(self->inmax); else inmax = Stream_getData((Stream *)self->inmax_stream)[0]; if (inmin < inmax) { inrev = 0; } else { tmp = inmin; inmin = inmax; inmax = tmp; inrev = 1; } inrange = inmax - inmin; if (self->modebuffer[4] == 0) outmin = PyFloat_AS_DOUBLE(self->outmin); else outmin = Stream_getData((Stream *)self->outmin_stream)[0]; if (self->modebuffer[5] == 0) outmax = PyFloat_AS_DOUBLE(self->outmax); else outmax = Stream_getData((Stream *)self->outmax_stream)[0]; if (outmin < outmax) { outrev = 0; } else { tmp = outmin; outmin = outmax; outmax = tmp; outrev = 1; } outrange = outmax - outmin; if (self->modebuffer[6] == 0) exp = PyFloat_AS_DOUBLE(self->exp); else exp = Stream_getData((Stream *)self->exp_stream)[0]; if (exp < 0.0) exp = 0.0; /* Handle case where input or output range equal 0 */ if (inrange == 0.0 || outrange == 0.0) { for (i=0; ibufsize; i++) { self->data[i] = outmin; } } /* Linear scaling */ else if (exp == 1.0) { if (inrev == 0 && outrev == 0) { for (i=0; ibufsize; i++) { normin = (_scale_clip(in[i], inmin, inmax) - inmin) / inrange; self->data[i] = normin * outrange + outmin; } } else if (inrev == 1 && outrev == 0) { for (i=0; ibufsize; i++) { normin = 1.0 - ((_scale_clip(in[i], inmin, inmax) - inmin) / inrange); self->data[i] = normin * outrange + outmin; } } else if (inrev == 0 && outrev == 1) { for (i=0; ibufsize; i++) { normin = (_scale_clip(in[i], inmin, inmax) - inmin) / inrange; self->data[i] = outmax - (normin * outrange); } } else if (inrev == 1 && outrev == 1) { for (i=0; ibufsize; i++) { normin = 1.0 - ((_scale_clip(in[i], inmin, inmax) - inmin) / inrange); self->data[i] = outmax - (normin * outrange); } } } /* Exponential scaling */ else { if (inrev == 0 && outrev == 0) { for (i=0; ibufsize; i++) { normin = MYPOW((_scale_clip(in[i], inmin, inmax) - inmin) / inrange, exp); self->data[i] = normin * outrange + outmin; } } else if (inrev == 1 && outrev == 0) { for (i=0; ibufsize; i++) { normin = MYPOW(1.0 - ((_scale_clip(in[i], inmin, inmax) - inmin) / inrange), exp); self->data[i] = normin * outrange + outmin; } } else if (inrev == 0 && outrev == 1) { for (i=0; ibufsize; i++) { normin = MYPOW((_scale_clip(in[i], inmin, inmax) - inmin) / inrange, exp); self->data[i] = outmax - (normin * outrange); } } else if (inrev == 1 && outrev == 1) { for (i=0; ibufsize; i++) { normin = MYPOW(1.0 - ((_scale_clip(in[i], inmin, inmax) - inmin) / inrange), exp); self->data[i] = outmax - (normin * outrange); } } } } static void Scale_postprocessing_ii(Scale *self) { POST_PROCESSING_II }; static void Scale_postprocessing_ai(Scale *self) { POST_PROCESSING_AI }; static void Scale_postprocessing_ia(Scale *self) { POST_PROCESSING_IA }; static void Scale_postprocessing_aa(Scale *self) { POST_PROCESSING_AA }; static void Scale_postprocessing_ireva(Scale *self) { POST_PROCESSING_IREVA }; static void Scale_postprocessing_areva(Scale *self) { POST_PROCESSING_AREVA }; static void Scale_postprocessing_revai(Scale *self) { POST_PROCESSING_REVAI }; static void Scale_postprocessing_revaa(Scale *self) { POST_PROCESSING_REVAA }; static void Scale_postprocessing_revareva(Scale *self) { POST_PROCESSING_REVAREVA }; static void Scale_setProcMode(Scale *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Scale_generate; switch (muladdmode) { case 0: self->muladd_func_ptr = Scale_postprocessing_ii; break; case 1: self->muladd_func_ptr = Scale_postprocessing_ai; break; case 2: self->muladd_func_ptr = Scale_postprocessing_revai; break; case 10: self->muladd_func_ptr = Scale_postprocessing_ia; break; case 11: self->muladd_func_ptr = Scale_postprocessing_aa; break; case 12: self->muladd_func_ptr = Scale_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Scale_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Scale_postprocessing_areva; break; case 22: self->muladd_func_ptr = Scale_postprocessing_revareva; break; } } static void Scale_compute_next_data_frame(Scale *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Scale_traverse(Scale *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->inmin); Py_VISIT(self->inmin_stream); Py_VISIT(self->inmax); Py_VISIT(self->inmax_stream); Py_VISIT(self->outmin); Py_VISIT(self->outmin_stream); Py_VISIT(self->outmax); Py_VISIT(self->outmax_stream); Py_VISIT(self->exp); Py_VISIT(self->exp_stream); return 0; } static int Scale_clear(Scale *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->inmin); Py_CLEAR(self->inmin_stream); Py_CLEAR(self->inmax); Py_CLEAR(self->inmax_stream); Py_CLEAR(self->outmin); Py_CLEAR(self->outmin_stream); Py_CLEAR(self->outmax); Py_CLEAR(self->outmax_stream); Py_CLEAR(self->exp); Py_CLEAR(self->exp_stream); return 0; } static void Scale_dealloc(Scale* self) { pyo_DEALLOC Scale_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Scale_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *inmintmp=NULL, *inmaxtmp=NULL, *outmintmp=NULL, *outmaxtmp=NULL, *exptmp=NULL, *multmp=NULL, *addtmp=NULL; Scale *self; self = (Scale *)type->tp_alloc(type, 0); self->inmin = PyFloat_FromDouble(0.0); self->inmax = PyFloat_FromDouble(1.0); self->outmin = PyFloat_FromDouble(0.0); self->outmax = PyFloat_FromDouble(1.0); self->exp = PyFloat_FromDouble(1.0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->modebuffer[5] = 0; self->modebuffer[6] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Scale_compute_next_data_frame); self->mode_func_ptr = Scale_setProcMode; static char *kwlist[] = {"input", "inmin", "inmax", "outmin", "outmax", "exp", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOOOO", kwlist, &inputtmp, &inmintmp, &inmaxtmp, &outmintmp, &outmaxtmp, &exptmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (inmintmp) { PyObject_CallMethod((PyObject *)self, "setInMin", "O", inmintmp); } if (inmaxtmp) { PyObject_CallMethod((PyObject *)self, "setInMax", "O", inmaxtmp); } if (outmintmp) { PyObject_CallMethod((PyObject *)self, "setOutMin", "O", outmintmp); } if (outmaxtmp) { PyObject_CallMethod((PyObject *)self, "setOutMax", "O", outmaxtmp); } if (exptmp) { PyObject_CallMethod((PyObject *)self, "setExp", "O", exptmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Scale_getServer(Scale* self) { GET_SERVER }; static PyObject * Scale_getStream(Scale* self) { GET_STREAM }; static PyObject * Scale_setMul(Scale *self, PyObject *arg) { SET_MUL }; static PyObject * Scale_setAdd(Scale *self, PyObject *arg) { SET_ADD }; static PyObject * Scale_setSub(Scale *self, PyObject *arg) { SET_SUB }; static PyObject * Scale_setDiv(Scale *self, PyObject *arg) { SET_DIV }; static PyObject * Scale_play(Scale *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Scale_out(Scale *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Scale_stop(Scale *self) { STOP }; static PyObject * Scale_multiply(Scale *self, PyObject *arg) { MULTIPLY }; static PyObject * Scale_inplace_multiply(Scale *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Scale_add(Scale *self, PyObject *arg) { ADD }; static PyObject * Scale_inplace_add(Scale *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Scale_sub(Scale *self, PyObject *arg) { SUB }; static PyObject * Scale_inplace_sub(Scale *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Scale_div(Scale *self, PyObject *arg) { DIV }; static PyObject * Scale_inplace_div(Scale *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Scale_setInMin(Scale *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->inmin); if (isNumber == 1) { self->inmin = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->inmin = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->inmin, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->inmin_stream); self->inmin_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Scale_setInMax(Scale *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->inmax); if (isNumber == 1) { self->inmax = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->inmax = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->inmax, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->inmax_stream); self->inmax_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Scale_setOutMin(Scale *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->outmin); if (isNumber == 1) { self->outmin = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->outmin = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->outmin, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->outmin_stream); self->outmin_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Scale_setOutMax(Scale *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->outmax); if (isNumber == 1) { self->outmax = PyNumber_Float(tmp); self->modebuffer[5] = 0; } else { self->outmax = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->outmax, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->outmax_stream); self->outmax_stream = (Stream *)streamtmp; self->modebuffer[5] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Scale_setExp(Scale *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->exp); if (isNumber == 1) { self->exp = PyNumber_Float(tmp); self->modebuffer[6] = 0; } else { self->exp = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->exp, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->exp_stream); self->exp_stream = (Stream *)streamtmp; self->modebuffer[6] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Scale_members[] = { {"server", T_OBJECT_EX, offsetof(Scale, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Scale, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Scale, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(Scale, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Scale, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Scale_methods[] = { {"getServer", (PyCFunction)Scale_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Scale_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Scale_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Scale_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Scale_stop, METH_NOARGS, "Stops computing."}, {"setInMin", (PyCFunction)Scale_setInMin, METH_O, "Sets input minimum scaling value."}, {"setInMax", (PyCFunction)Scale_setInMax, METH_O, "Sets input maximum scaling value."}, {"setOutMin", (PyCFunction)Scale_setOutMin, METH_O, "Sets output minimum scaling value."}, {"setOutMax", (PyCFunction)Scale_setOutMax, METH_O, "Sets output maximum scaling value."}, {"setExp", (PyCFunction)Scale_setExp, METH_O, "Sets exponent factor."}, {"setMul", (PyCFunction)Scale_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Scale_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Scale_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Scale_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Scale_as_number = { (binaryfunc)Scale_add, /*nb_add*/ (binaryfunc)Scale_sub, /*nb_subtract*/ (binaryfunc)Scale_multiply, /*nb_multiply*/ (binaryfunc)Scale_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Scale_inplace_add, /*inplace_add*/ (binaryfunc)Scale_inplace_sub, /*inplace_subtract*/ (binaryfunc)Scale_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Scale_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ScaleType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Scale_base", /*tp_name*/ sizeof(Scale), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Scale_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Scale_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Scale objects. Scale input values on an arbitrary output scaling range.", /* tp_doc */ (traverseproc)Scale_traverse, /* tp_traverse */ (inquiry)Scale_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Scale_methods, /* tp_methods */ Scale_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Scale_new, /* tp_new */ }; /************/ /* CentsToTranspo */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; MYFLT lastcents; MYFLT curtranspo; int modebuffer[2]; // need at least 2 slots for mul & add } CentsToTranspo; static void CentsToTranspo_process(CentsToTranspo *self) { int i; MYFLT cents; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { cents = in[i]; if (cents != self->lastcents) { self->data[i] = self->curtranspo = MYPOW(2.0, cents / 1200.); self->lastcents = cents; } else self->data[i] = self->curtranspo; } } static void CentsToTranspo_postprocessing_ii(CentsToTranspo *self) { POST_PROCESSING_II }; static void CentsToTranspo_postprocessing_ai(CentsToTranspo *self) { POST_PROCESSING_AI }; static void CentsToTranspo_postprocessing_ia(CentsToTranspo *self) { POST_PROCESSING_IA }; static void CentsToTranspo_postprocessing_aa(CentsToTranspo *self) { POST_PROCESSING_AA }; static void CentsToTranspo_postprocessing_ireva(CentsToTranspo *self) { POST_PROCESSING_IREVA }; static void CentsToTranspo_postprocessing_areva(CentsToTranspo *self) { POST_PROCESSING_AREVA }; static void CentsToTranspo_postprocessing_revai(CentsToTranspo *self) { POST_PROCESSING_REVAI }; static void CentsToTranspo_postprocessing_revaa(CentsToTranspo *self) { POST_PROCESSING_REVAA }; static void CentsToTranspo_postprocessing_revareva(CentsToTranspo *self) { POST_PROCESSING_REVAREVA }; static void CentsToTranspo_setProcMode(CentsToTranspo *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = CentsToTranspo_process; switch (muladdmode) { case 0: self->muladd_func_ptr = CentsToTranspo_postprocessing_ii; break; case 1: self->muladd_func_ptr = CentsToTranspo_postprocessing_ai; break; case 2: self->muladd_func_ptr = CentsToTranspo_postprocessing_revai; break; case 10: self->muladd_func_ptr = CentsToTranspo_postprocessing_ia; break; case 11: self->muladd_func_ptr = CentsToTranspo_postprocessing_aa; break; case 12: self->muladd_func_ptr = CentsToTranspo_postprocessing_revaa; break; case 20: self->muladd_func_ptr = CentsToTranspo_postprocessing_ireva; break; case 21: self->muladd_func_ptr = CentsToTranspo_postprocessing_areva; break; case 22: self->muladd_func_ptr = CentsToTranspo_postprocessing_revareva; break; } } static void CentsToTranspo_compute_next_data_frame(CentsToTranspo *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int CentsToTranspo_traverse(CentsToTranspo *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int CentsToTranspo_clear(CentsToTranspo *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void CentsToTranspo_dealloc(CentsToTranspo* self) { pyo_DEALLOC CentsToTranspo_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * CentsToTranspo_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; CentsToTranspo *self; self = (CentsToTranspo *)type->tp_alloc(type, 0); self->lastcents = 0.0; self->curtranspo = 1.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, CentsToTranspo_compute_next_data_frame); self->mode_func_ptr = CentsToTranspo_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * CentsToTranspo_getServer(CentsToTranspo* self) { GET_SERVER }; static PyObject * CentsToTranspo_getStream(CentsToTranspo* self) { GET_STREAM }; static PyObject * CentsToTranspo_setMul(CentsToTranspo *self, PyObject *arg) { SET_MUL }; static PyObject * CentsToTranspo_setAdd(CentsToTranspo *self, PyObject *arg) { SET_ADD }; static PyObject * CentsToTranspo_setSub(CentsToTranspo *self, PyObject *arg) { SET_SUB }; static PyObject * CentsToTranspo_setDiv(CentsToTranspo *self, PyObject *arg) { SET_DIV }; static PyObject * CentsToTranspo_play(CentsToTranspo *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * CentsToTranspo_out(CentsToTranspo *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * CentsToTranspo_stop(CentsToTranspo *self) { STOP }; static PyObject * CentsToTranspo_multiply(CentsToTranspo *self, PyObject *arg) { MULTIPLY }; static PyObject * CentsToTranspo_inplace_multiply(CentsToTranspo *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * CentsToTranspo_add(CentsToTranspo *self, PyObject *arg) { ADD }; static PyObject * CentsToTranspo_inplace_add(CentsToTranspo *self, PyObject *arg) { INPLACE_ADD }; static PyObject * CentsToTranspo_sub(CentsToTranspo *self, PyObject *arg) { SUB }; static PyObject * CentsToTranspo_inplace_sub(CentsToTranspo *self, PyObject *arg) { INPLACE_SUB }; static PyObject * CentsToTranspo_div(CentsToTranspo *self, PyObject *arg) { DIV }; static PyObject * CentsToTranspo_inplace_div(CentsToTranspo *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef CentsToTranspo_members[] = { {"server", T_OBJECT_EX, offsetof(CentsToTranspo, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(CentsToTranspo, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(CentsToTranspo, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(CentsToTranspo, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(CentsToTranspo, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef CentsToTranspo_methods[] = { {"getServer", (PyCFunction)CentsToTranspo_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)CentsToTranspo_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)CentsToTranspo_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)CentsToTranspo_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)CentsToTranspo_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)CentsToTranspo_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)CentsToTranspo_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)CentsToTranspo_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)CentsToTranspo_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods CentsToTranspo_as_number = { (binaryfunc)CentsToTranspo_add, /*nb_add*/ (binaryfunc)CentsToTranspo_sub, /*nb_subtract*/ (binaryfunc)CentsToTranspo_multiply, /*nb_multiply*/ (binaryfunc)CentsToTranspo_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)CentsToTranspo_inplace_add, /*inplace_add*/ (binaryfunc)CentsToTranspo_inplace_sub, /*inplace_subtract*/ (binaryfunc)CentsToTranspo_inplace_multiply, /*inplace_multiply*/ (binaryfunc)CentsToTranspo_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject CentsToTranspoType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.CentsToTranspo_base", /*tp_name*/ sizeof(CentsToTranspo), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)CentsToTranspo_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &CentsToTranspo_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "CentsToTranspo objects. Converts cents value to transposition factor.", /* tp_doc */ (traverseproc)CentsToTranspo_traverse, /* tp_traverse */ (inquiry)CentsToTranspo_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ CentsToTranspo_methods, /* tp_methods */ CentsToTranspo_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ CentsToTranspo_new, /* tp_new */ }; /************/ /* TranspoToCents */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; MYFLT lasttranspo; MYFLT curcents; int modebuffer[2]; // need at least 2 slots for mul & add } TranspoToCents; static void TranspoToCents_process(TranspoToCents *self) { int i; MYFLT transpo; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { transpo = in[i]; if (transpo != self->lasttranspo) { self->data[i] = self->curcents = 1200.0 * MYLOG2(transpo); self->lasttranspo = transpo; } else self->data[i] = self->curcents; } } static void TranspoToCents_postprocessing_ii(TranspoToCents *self) { POST_PROCESSING_II }; static void TranspoToCents_postprocessing_ai(TranspoToCents *self) { POST_PROCESSING_AI }; static void TranspoToCents_postprocessing_ia(TranspoToCents *self) { POST_PROCESSING_IA }; static void TranspoToCents_postprocessing_aa(TranspoToCents *self) { POST_PROCESSING_AA }; static void TranspoToCents_postprocessing_ireva(TranspoToCents *self) { POST_PROCESSING_IREVA }; static void TranspoToCents_postprocessing_areva(TranspoToCents *self) { POST_PROCESSING_AREVA }; static void TranspoToCents_postprocessing_revai(TranspoToCents *self) { POST_PROCESSING_REVAI }; static void TranspoToCents_postprocessing_revaa(TranspoToCents *self) { POST_PROCESSING_REVAA }; static void TranspoToCents_postprocessing_revareva(TranspoToCents *self) { POST_PROCESSING_REVAREVA }; static void TranspoToCents_setProcMode(TranspoToCents *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = TranspoToCents_process; switch (muladdmode) { case 0: self->muladd_func_ptr = TranspoToCents_postprocessing_ii; break; case 1: self->muladd_func_ptr = TranspoToCents_postprocessing_ai; break; case 2: self->muladd_func_ptr = TranspoToCents_postprocessing_revai; break; case 10: self->muladd_func_ptr = TranspoToCents_postprocessing_ia; break; case 11: self->muladd_func_ptr = TranspoToCents_postprocessing_aa; break; case 12: self->muladd_func_ptr = TranspoToCents_postprocessing_revaa; break; case 20: self->muladd_func_ptr = TranspoToCents_postprocessing_ireva; break; case 21: self->muladd_func_ptr = TranspoToCents_postprocessing_areva; break; case 22: self->muladd_func_ptr = TranspoToCents_postprocessing_revareva; break; } } static void TranspoToCents_compute_next_data_frame(TranspoToCents *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int TranspoToCents_traverse(TranspoToCents *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int TranspoToCents_clear(TranspoToCents *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void TranspoToCents_dealloc(TranspoToCents* self) { pyo_DEALLOC TranspoToCents_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * TranspoToCents_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; TranspoToCents *self; self = (TranspoToCents *)type->tp_alloc(type, 0); self->lasttranspo = 1.0; self->curcents = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, TranspoToCents_compute_next_data_frame); self->mode_func_ptr = TranspoToCents_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * TranspoToCents_getServer(TranspoToCents* self) { GET_SERVER }; static PyObject * TranspoToCents_getStream(TranspoToCents* self) { GET_STREAM }; static PyObject * TranspoToCents_setMul(TranspoToCents *self, PyObject *arg) { SET_MUL }; static PyObject * TranspoToCents_setAdd(TranspoToCents *self, PyObject *arg) { SET_ADD }; static PyObject * TranspoToCents_setSub(TranspoToCents *self, PyObject *arg) { SET_SUB }; static PyObject * TranspoToCents_setDiv(TranspoToCents *self, PyObject *arg) { SET_DIV }; static PyObject * TranspoToCents_play(TranspoToCents *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * TranspoToCents_out(TranspoToCents *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * TranspoToCents_stop(TranspoToCents *self) { STOP }; static PyObject * TranspoToCents_multiply(TranspoToCents *self, PyObject *arg) { MULTIPLY }; static PyObject * TranspoToCents_inplace_multiply(TranspoToCents *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * TranspoToCents_add(TranspoToCents *self, PyObject *arg) { ADD }; static PyObject * TranspoToCents_inplace_add(TranspoToCents *self, PyObject *arg) { INPLACE_ADD }; static PyObject * TranspoToCents_sub(TranspoToCents *self, PyObject *arg) { SUB }; static PyObject * TranspoToCents_inplace_sub(TranspoToCents *self, PyObject *arg) { INPLACE_SUB }; static PyObject * TranspoToCents_div(TranspoToCents *self, PyObject *arg) { DIV }; static PyObject * TranspoToCents_inplace_div(TranspoToCents *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef TranspoToCents_members[] = { {"server", T_OBJECT_EX, offsetof(TranspoToCents, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(TranspoToCents, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(TranspoToCents, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(TranspoToCents, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(TranspoToCents, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef TranspoToCents_methods[] = { {"getServer", (PyCFunction)TranspoToCents_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)TranspoToCents_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)TranspoToCents_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)TranspoToCents_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)TranspoToCents_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)TranspoToCents_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)TranspoToCents_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)TranspoToCents_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)TranspoToCents_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods TranspoToCents_as_number = { (binaryfunc)TranspoToCents_add, /*nb_add*/ (binaryfunc)TranspoToCents_sub, /*nb_subtract*/ (binaryfunc)TranspoToCents_multiply, /*nb_multiply*/ (binaryfunc)TranspoToCents_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)TranspoToCents_inplace_add, /*inplace_add*/ (binaryfunc)TranspoToCents_inplace_sub, /*inplace_subtract*/ (binaryfunc)TranspoToCents_inplace_multiply, /*inplace_multiply*/ (binaryfunc)TranspoToCents_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject TranspoToCentsType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.TranspoToCents_base", /*tp_name*/ sizeof(TranspoToCents), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)TranspoToCents_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &TranspoToCents_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "TranspoToCents objects. Converts transposition factor to cents value.", /* tp_doc */ (traverseproc)TranspoToCents_traverse, /* tp_traverse */ (inquiry)TranspoToCents_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ TranspoToCents_methods, /* tp_methods */ TranspoToCents_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ TranspoToCents_new, /* tp_new */ }; /************/ /* MToF */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; MYFLT lastmidi; MYFLT curfreq; int modebuffer[2]; // need at least 2 slots for mul & add } MToF; static void MToF_process(MToF *self) { int i; MYFLT midi; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { midi = in[i]; if (midi != self->lastmidi) { self->data[i] = self->curfreq = 440.0 * MYPOW(2.0, (midi - 69) / 12.0); self->lastmidi = midi; } else self->data[i] = self->curfreq; } } static void MToF_postprocessing_ii(MToF *self) { POST_PROCESSING_II }; static void MToF_postprocessing_ai(MToF *self) { POST_PROCESSING_AI }; static void MToF_postprocessing_ia(MToF *self) { POST_PROCESSING_IA }; static void MToF_postprocessing_aa(MToF *self) { POST_PROCESSING_AA }; static void MToF_postprocessing_ireva(MToF *self) { POST_PROCESSING_IREVA }; static void MToF_postprocessing_areva(MToF *self) { POST_PROCESSING_AREVA }; static void MToF_postprocessing_revai(MToF *self) { POST_PROCESSING_REVAI }; static void MToF_postprocessing_revaa(MToF *self) { POST_PROCESSING_REVAA }; static void MToF_postprocessing_revareva(MToF *self) { POST_PROCESSING_REVAREVA }; static void MToF_setProcMode(MToF *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = MToF_process; switch (muladdmode) { case 0: self->muladd_func_ptr = MToF_postprocessing_ii; break; case 1: self->muladd_func_ptr = MToF_postprocessing_ai; break; case 2: self->muladd_func_ptr = MToF_postprocessing_revai; break; case 10: self->muladd_func_ptr = MToF_postprocessing_ia; break; case 11: self->muladd_func_ptr = MToF_postprocessing_aa; break; case 12: self->muladd_func_ptr = MToF_postprocessing_revaa; break; case 20: self->muladd_func_ptr = MToF_postprocessing_ireva; break; case 21: self->muladd_func_ptr = MToF_postprocessing_areva; break; case 22: self->muladd_func_ptr = MToF_postprocessing_revareva; break; } } static void MToF_compute_next_data_frame(MToF *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int MToF_traverse(MToF *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int MToF_clear(MToF *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void MToF_dealloc(MToF* self) { pyo_DEALLOC MToF_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * MToF_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; MToF *self; self = (MToF *)type->tp_alloc(type, 0); self->lastmidi = 0; self->curfreq = 8.1757989156437; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, MToF_compute_next_data_frame); self->mode_func_ptr = MToF_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * MToF_getServer(MToF* self) { GET_SERVER }; static PyObject * MToF_getStream(MToF* self) { GET_STREAM }; static PyObject * MToF_setMul(MToF *self, PyObject *arg) { SET_MUL }; static PyObject * MToF_setAdd(MToF *self, PyObject *arg) { SET_ADD }; static PyObject * MToF_setSub(MToF *self, PyObject *arg) { SET_SUB }; static PyObject * MToF_setDiv(MToF *self, PyObject *arg) { SET_DIV }; static PyObject * MToF_play(MToF *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * MToF_out(MToF *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * MToF_stop(MToF *self) { STOP }; static PyObject * MToF_multiply(MToF *self, PyObject *arg) { MULTIPLY }; static PyObject * MToF_inplace_multiply(MToF *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * MToF_add(MToF *self, PyObject *arg) { ADD }; static PyObject * MToF_inplace_add(MToF *self, PyObject *arg) { INPLACE_ADD }; static PyObject * MToF_sub(MToF *self, PyObject *arg) { SUB }; static PyObject * MToF_inplace_sub(MToF *self, PyObject *arg) { INPLACE_SUB }; static PyObject * MToF_div(MToF *self, PyObject *arg) { DIV }; static PyObject * MToF_inplace_div(MToF *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef MToF_members[] = { {"server", T_OBJECT_EX, offsetof(MToF, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(MToF, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(MToF, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(MToF, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(MToF, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef MToF_methods[] = { {"getServer", (PyCFunction)MToF_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)MToF_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)MToF_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)MToF_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)MToF_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)MToF_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)MToF_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)MToF_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)MToF_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods MToF_as_number = { (binaryfunc)MToF_add, /*nb_add*/ (binaryfunc)MToF_sub, /*nb_subtract*/ (binaryfunc)MToF_multiply, /*nb_multiply*/ (binaryfunc)MToF_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)MToF_inplace_add, /*inplace_add*/ (binaryfunc)MToF_inplace_sub, /*inplace_subtract*/ (binaryfunc)MToF_inplace_multiply, /*inplace_multiply*/ (binaryfunc)MToF_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject MToFType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.MToF_base", /*tp_name*/ sizeof(MToF), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)MToF_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &MToF_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "MToF objects. Converts midi notes to frequency.", /* tp_doc */ (traverseproc)MToF_traverse, /* tp_traverse */ (inquiry)MToF_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ MToF_methods, /* tp_methods */ MToF_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MToF_new, /* tp_new */ }; /************/ /* FToM */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; MYFLT lastfreq; MYFLT curmidi; int modebuffer[2]; // need at least 2 slots for mul & add } FToM; static void FToM_process(FToM *self) { int i; MYFLT freq; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { freq = in[i]; if (freq != self->lastfreq) { if (freq < 8.1758) freq = 8.1578; self->curmidi = 12.0 * MYLOG2(freq / 440.0) + 69; self->lastfreq = freq; } else self->data[i] = self->curmidi; } } static void FToM_postprocessing_ii(FToM *self) { POST_PROCESSING_II }; static void FToM_postprocessing_ai(FToM *self) { POST_PROCESSING_AI }; static void FToM_postprocessing_ia(FToM *self) { POST_PROCESSING_IA }; static void FToM_postprocessing_aa(FToM *self) { POST_PROCESSING_AA }; static void FToM_postprocessing_ireva(FToM *self) { POST_PROCESSING_IREVA }; static void FToM_postprocessing_areva(FToM *self) { POST_PROCESSING_AREVA }; static void FToM_postprocessing_revai(FToM *self) { POST_PROCESSING_REVAI }; static void FToM_postprocessing_revaa(FToM *self) { POST_PROCESSING_REVAA }; static void FToM_postprocessing_revareva(FToM *self) { POST_PROCESSING_REVAREVA }; static void FToM_setProcMode(FToM *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = FToM_process; switch (muladdmode) { case 0: self->muladd_func_ptr = FToM_postprocessing_ii; break; case 1: self->muladd_func_ptr = FToM_postprocessing_ai; break; case 2: self->muladd_func_ptr = FToM_postprocessing_revai; break; case 10: self->muladd_func_ptr = FToM_postprocessing_ia; break; case 11: self->muladd_func_ptr = FToM_postprocessing_aa; break; case 12: self->muladd_func_ptr = FToM_postprocessing_revaa; break; case 20: self->muladd_func_ptr = FToM_postprocessing_ireva; break; case 21: self->muladd_func_ptr = FToM_postprocessing_areva; break; case 22: self->muladd_func_ptr = FToM_postprocessing_revareva; break; } } static void FToM_compute_next_data_frame(FToM *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int FToM_traverse(FToM *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int FToM_clear(FToM *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void FToM_dealloc(FToM* self) { pyo_DEALLOC FToM_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * FToM_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; FToM *self; self = (FToM *)type->tp_alloc(type, 0); self->lastfreq = 8.1758; self->curmidi = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, FToM_compute_next_data_frame); self->mode_func_ptr = FToM_setProcMode; static char *kwlist[] = {"input", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * FToM_getServer(FToM* self) { GET_SERVER }; static PyObject * FToM_getStream(FToM* self) { GET_STREAM }; static PyObject * FToM_setMul(FToM *self, PyObject *arg) { SET_MUL }; static PyObject * FToM_setAdd(FToM *self, PyObject *arg) { SET_ADD }; static PyObject * FToM_setSub(FToM *self, PyObject *arg) { SET_SUB }; static PyObject * FToM_setDiv(FToM *self, PyObject *arg) { SET_DIV }; static PyObject * FToM_play(FToM *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * FToM_out(FToM *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * FToM_stop(FToM *self) { STOP }; static PyObject * FToM_multiply(FToM *self, PyObject *arg) { MULTIPLY }; static PyObject * FToM_inplace_multiply(FToM *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * FToM_add(FToM *self, PyObject *arg) { ADD }; static PyObject * FToM_inplace_add(FToM *self, PyObject *arg) { INPLACE_ADD }; static PyObject * FToM_sub(FToM *self, PyObject *arg) { SUB }; static PyObject * FToM_inplace_sub(FToM *self, PyObject *arg) { INPLACE_SUB }; static PyObject * FToM_div(FToM *self, PyObject *arg) { DIV }; static PyObject * FToM_inplace_div(FToM *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef FToM_members[] = { {"server", T_OBJECT_EX, offsetof(FToM, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(FToM, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(FToM, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(FToM, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(FToM, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef FToM_methods[] = { {"getServer", (PyCFunction)FToM_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)FToM_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)FToM_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)FToM_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)FToM_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)FToM_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)FToM_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)FToM_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)FToM_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods FToM_as_number = { (binaryfunc)FToM_add, /*nb_add*/ (binaryfunc)FToM_sub, /*nb_subtract*/ (binaryfunc)FToM_multiply, /*nb_multiply*/ (binaryfunc)FToM_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)FToM_inplace_add, /*inplace_add*/ (binaryfunc)FToM_inplace_sub, /*inplace_subtract*/ (binaryfunc)FToM_inplace_multiply, /*inplace_multiply*/ (binaryfunc)FToM_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject FToMType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.FToM_base", /*tp_name*/ sizeof(FToM), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)FToM_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &FToM_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "FToM objects. Converts frequency to midi note.", /* tp_doc */ (traverseproc)FToM_traverse, /* tp_traverse */ (inquiry)FToM_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ FToM_methods, /* tp_methods */ FToM_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ FToM_new, /* tp_new */ }; /************/ /* MToT */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; MYFLT centralkey; MYFLT lastmidi; MYFLT curfreq; int modebuffer[2]; // need at least 2 slots for mul & add } MToT; static void MToT_process(MToT *self) { int i; MYFLT midi; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { midi = in[i]; if (midi != self->lastmidi) { self->data[i] = self->curfreq = MYPOW(1.0594630943593, midi - self->centralkey); self->lastmidi = midi; } else self->data[i] = self->curfreq; } } static void MToT_postprocessing_ii(MToT *self) { POST_PROCESSING_II }; static void MToT_postprocessing_ai(MToT *self) { POST_PROCESSING_AI }; static void MToT_postprocessing_ia(MToT *self) { POST_PROCESSING_IA }; static void MToT_postprocessing_aa(MToT *self) { POST_PROCESSING_AA }; static void MToT_postprocessing_ireva(MToT *self) { POST_PROCESSING_IREVA }; static void MToT_postprocessing_areva(MToT *self) { POST_PROCESSING_AREVA }; static void MToT_postprocessing_revai(MToT *self) { POST_PROCESSING_REVAI }; static void MToT_postprocessing_revaa(MToT *self) { POST_PROCESSING_REVAA }; static void MToT_postprocessing_revareva(MToT *self) { POST_PROCESSING_REVAREVA }; static void MToT_setProcMode(MToT *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = MToT_process; switch (muladdmode) { case 0: self->muladd_func_ptr = MToT_postprocessing_ii; break; case 1: self->muladd_func_ptr = MToT_postprocessing_ai; break; case 2: self->muladd_func_ptr = MToT_postprocessing_revai; break; case 10: self->muladd_func_ptr = MToT_postprocessing_ia; break; case 11: self->muladd_func_ptr = MToT_postprocessing_aa; break; case 12: self->muladd_func_ptr = MToT_postprocessing_revaa; break; case 20: self->muladd_func_ptr = MToT_postprocessing_ireva; break; case 21: self->muladd_func_ptr = MToT_postprocessing_areva; break; case 22: self->muladd_func_ptr = MToT_postprocessing_revareva; break; } } static void MToT_compute_next_data_frame(MToT *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int MToT_traverse(MToT *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int MToT_clear(MToT *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void MToT_dealloc(MToT* self) { pyo_DEALLOC MToT_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * MToT_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; MToT *self; self = (MToT *)type->tp_alloc(type, 0); self->centralkey = 60.0; self->lastmidi = 0; self->curfreq = 8.1757989156437; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, MToT_compute_next_data_frame); self->mode_func_ptr = MToT_setProcMode; static char *kwlist[] = {"input", "centralkey", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FOO, kwlist, &inputtmp, &self->centralkey, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * MToT_setCentralKey(MToT *self, PyObject *arg) { ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); if (isNumber == 1) { self->centralkey = PyFloat_AsDouble(arg); } Py_INCREF(Py_None); return Py_None; } static PyObject * MToT_getServer(MToT* self) { GET_SERVER }; static PyObject * MToT_getStream(MToT* self) { GET_STREAM }; static PyObject * MToT_setMul(MToT *self, PyObject *arg) { SET_MUL }; static PyObject * MToT_setAdd(MToT *self, PyObject *arg) { SET_ADD }; static PyObject * MToT_setSub(MToT *self, PyObject *arg) { SET_SUB }; static PyObject * MToT_setDiv(MToT *self, PyObject *arg) { SET_DIV }; static PyObject * MToT_play(MToT *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * MToT_out(MToT *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * MToT_stop(MToT *self) { STOP }; static PyObject * MToT_multiply(MToT *self, PyObject *arg) { MULTIPLY }; static PyObject * MToT_inplace_multiply(MToT *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * MToT_add(MToT *self, PyObject *arg) { ADD }; static PyObject * MToT_inplace_add(MToT *self, PyObject *arg) { INPLACE_ADD }; static PyObject * MToT_sub(MToT *self, PyObject *arg) { SUB }; static PyObject * MToT_inplace_sub(MToT *self, PyObject *arg) { INPLACE_SUB }; static PyObject * MToT_div(MToT *self, PyObject *arg) { DIV }; static PyObject * MToT_inplace_div(MToT *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef MToT_members[] = { {"server", T_OBJECT_EX, offsetof(MToT, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(MToT, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(MToT, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(MToT, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(MToT, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef MToT_methods[] = { {"getServer", (PyCFunction)MToT_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)MToT_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)MToT_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)MToT_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)MToT_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setCentralKey", (PyCFunction)MToT_setCentralKey, METH_O, "Sets the central key."}, {"setMul", (PyCFunction)MToT_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)MToT_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)MToT_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)MToT_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods MToT_as_number = { (binaryfunc)MToT_add, /*nb_add*/ (binaryfunc)MToT_sub, /*nb_subtract*/ (binaryfunc)MToT_multiply, /*nb_multiply*/ (binaryfunc)MToT_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)MToT_inplace_add, /*inplace_add*/ (binaryfunc)MToT_inplace_sub, /*inplace_subtract*/ (binaryfunc)MToT_inplace_multiply, /*inplace_multiply*/ (binaryfunc)MToT_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject MToTType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.MToT_base", /*tp_name*/ sizeof(MToT), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)MToT_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &MToT_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "MToT objects. Converts midi notes to transposition factor.", /* tp_doc */ (traverseproc)MToT_traverse, /* tp_traverse */ (inquiry)MToT_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ MToT_methods, /* tp_methods */ MToT_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MToT_new, /* tp_new */ }; /************/ /* Resample */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; MYFLT **pimpulse; MYFLT **pinput; int factor; int count; int dir; // Up = 1, DOWN = 0 int size; // UP: 0 = zero-padding, 1 = sample-and-hold, 2+ polyphase lowpass filtering // DOWN: <2 = discard extra samples, 2+ polyphase lowpass filtering int modebuffer[2]; // need at least 2 slots for mul & add } Resample; static void Resample_create_impulse(Resample *self) { int i, half; MYFLT val, scl, sum, invSum, env, w; MYFLT impulse[self->size]; half = self->size / 2; sum = 0.0; w = TWOPI * 0.49 / self->factor; for (i=0; isize)); scl = i - half; val = (MYSIN(w * scl) / scl) * env; sum += val; impulse[i] = val; } sum *= 2.0; sum += w; invSum = 1.0 / sum; impulse[half] = w * invSum; for (i=0; isize; i++) { impulse[i] = impulse[self->size-i]; } /* Create sub-filters. */ for (i=0; isize; i++) { self->pimpulse[i%self->factor][(int)(i/self->factor)] = impulse[i]; } } static void Resample_downsample(Resample *self) { int i, j, k, tmp_count, len; MYFLT filtout; MYFLT *in = Stream_getData((Stream *)self->input_stream); len = self->size / self->factor; if (self->size <= self->factor) { for (i=0; ibufsize; i++) { self->data[i] = in[i * self->factor]; } } else { for (i=0; ibufsize; i++) { self->data[i] = 0.0; for (j=0; jfactor; j++) { // for each polyphase sub-filter... filtout = 0.0; tmp_count = self->count; for (k=0; kpinput[j][tmp_count--] * self->pimpulse[j][k]; } self->data[i] += filtout; // ... and sum. } // Input decomposition (input delay line in reverse order). self->count++; if (self->count == len) self->count = 0; for (j=0; jfactor; j++) { self->pinput[self->factor-1-j][self->count] = in[i*self->factor+j]; } } } } static void Resample_upsample(Resample *self) { int i, j, k, tmp_count, len; MYFLT filtout; MYFLT *in = Stream_getData((Stream *)self->input_stream); len = self->size / self->factor; if (self->size == 0) { for (i=0; i<(self->bufsize/self->factor); i++) { j = i*self->factor; self->data[j] = in[i]; for (k=1; kfactor; k++) { self->data[j+k] = 0.0; } } } else if (self->size == self->factor) { for (i=0; i<(self->bufsize/self->factor); i++) { for (k=0; kfactor; k++) { self->data[i*self->factor+k] = in[i]; } } } else { for (i=0; ibufsize/self->factor; i++) { for(j=0; jfactor; j++) { // for each polyphase sub-filter... filtout = 0.0; tmp_count = self->count; for (k=0; kpinput[j][tmp_count--] * self->pimpulse[j][k]; } self->data[i*self->factor+j] = filtout; } self->count++; if (self->count == len) self->count = 0; for (j=0; jfactor; j++) { self->pinput[self->factor-1-j][self->count] = in[i]; } } } } static void Resample_process(Resample *self) { if (self->dir == 0) Resample_downsample(self); else Resample_upsample(self); } static void Resample_postprocessing_ii(Resample *self) { POST_PROCESSING_II }; static void Resample_postprocessing_ai(Resample *self) { POST_PROCESSING_AI }; static void Resample_postprocessing_ia(Resample *self) { POST_PROCESSING_IA }; static void Resample_postprocessing_aa(Resample *self) { POST_PROCESSING_AA }; static void Resample_postprocessing_ireva(Resample *self) { POST_PROCESSING_IREVA }; static void Resample_postprocessing_areva(Resample *self) { POST_PROCESSING_AREVA }; static void Resample_postprocessing_revai(Resample *self) { POST_PROCESSING_REVAI }; static void Resample_postprocessing_revaa(Resample *self) { POST_PROCESSING_REVAA }; static void Resample_postprocessing_revareva(Resample *self) { POST_PROCESSING_REVAREVA }; static void Resample_setProcMode(Resample *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = Resample_process; switch (muladdmode) { case 0: self->muladd_func_ptr = Resample_postprocessing_ii; break; case 1: self->muladd_func_ptr = Resample_postprocessing_ai; break; case 2: self->muladd_func_ptr = Resample_postprocessing_revai; break; case 10: self->muladd_func_ptr = Resample_postprocessing_ia; break; case 11: self->muladd_func_ptr = Resample_postprocessing_aa; break; case 12: self->muladd_func_ptr = Resample_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Resample_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Resample_postprocessing_areva; break; case 22: self->muladd_func_ptr = Resample_postprocessing_revareva; break; } } static void Resample_compute_next_data_frame(Resample *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Resample_traverse(Resample *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); return 0; } static int Resample_clear(Resample *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); return 0; } static void Resample_dealloc(Resample* self) { int i; pyo_DEALLOC if (self->size > 0) { for (i=0; ifactor; i++) { free(self->pimpulse[i]); free(self->pinput[i]); } free(self->pimpulse); free(self->pinput); } Resample_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Resample_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i, j, lfac, cfac, mode; PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL; Resample *self; self = (Resample *)type->tp_alloc(type, 0); self->factor = 1; self->size = 0; self->count = 0; self->dir = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; static char *kwlist[] = {"input", "mode", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &inputtmp, &mode, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM lfac = Server_getLastResamplingFactor((Server *)PyServer_get_server()); cfac = Server_getCurrentResamplingFactor((Server *)PyServer_get_server()); if (lfac == 1) { if (cfac < 0) { self->dir = 0; cfac = -cfac; } else self->dir = 1; self->factor = cfac; } else if (cfac == 1) { if (lfac < 0) { self->dir = 1; lfac = -lfac; } else self->dir = 0; self->factor = lfac; } self->size = self->factor * mode; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Resample_compute_next_data_frame); self->mode_func_ptr = Resample_setProcMode; if (self->size > self->factor) { self->pimpulse = (MYFLT **)realloc(self->pimpulse, self->factor * sizeof(MYFLT *)); self->pinput = (MYFLT **)realloc(self->pinput, self->factor * sizeof(MYFLT *)); for (j=0; jfactor; j++) { self->pimpulse[j] = (MYFLT *)malloc(self->size / self->factor * sizeof(MYFLT)); self->pinput[j] = (MYFLT *)malloc(self->size / self->factor * sizeof(MYFLT)); for (i=0; isize/self->factor; i++) { self->pinput[j][i] = 0.0; } } Resample_create_impulse(self); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Resample_getServer(Resample* self) { GET_SERVER }; static PyObject * Resample_getStream(Resample* self) { GET_STREAM }; static PyObject * Resample_setMul(Resample *self, PyObject *arg) { SET_MUL }; static PyObject * Resample_setAdd(Resample *self, PyObject *arg) { SET_ADD }; static PyObject * Resample_setSub(Resample *self, PyObject *arg) { SET_SUB }; static PyObject * Resample_setDiv(Resample *self, PyObject *arg) { SET_DIV }; static PyObject * Resample_play(Resample *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Resample_out(Resample *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Resample_stop(Resample *self) { STOP }; static PyObject * Resample_multiply(Resample *self, PyObject *arg) { MULTIPLY }; static PyObject * Resample_inplace_multiply(Resample *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Resample_add(Resample *self, PyObject *arg) { ADD }; static PyObject * Resample_inplace_add(Resample *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Resample_sub(Resample *self, PyObject *arg) { SUB }; static PyObject * Resample_inplace_sub(Resample *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Resample_div(Resample *self, PyObject *arg) { DIV }; static PyObject * Resample_inplace_div(Resample *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Resample_members[] = { {"server", T_OBJECT_EX, offsetof(Resample, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Resample, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Resample, input), 0, "Input sound object."}, {"mul", T_OBJECT_EX, offsetof(Resample, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Resample, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Resample_methods[] = { {"getServer", (PyCFunction)Resample_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Resample_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Resample_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Resample_stop, METH_NOARGS, "Stops computing."}, {"out", (PyCFunction)Resample_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"setMul", (PyCFunction)Resample_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Resample_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Resample_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Resample_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Resample_as_number = { (binaryfunc)Resample_add, /*nb_add*/ (binaryfunc)Resample_sub, /*nb_subtract*/ (binaryfunc)Resample_multiply, /*nb_multiply*/ (binaryfunc)Resample_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Resample_inplace_add, /*inplace_add*/ (binaryfunc)Resample_inplace_sub, /*inplace_subtract*/ (binaryfunc)Resample_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Resample_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject ResampleType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Resample_base", /*tp_name*/ sizeof(Resample), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Resample_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Resample_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Resample objects. Performs resampling of an audio signal.", /* tp_doc */ (traverseproc)Resample_traverse, /* tp_traverse */ (inquiry)Resample_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Resample_methods, /* tp_methods */ Resample_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Resample_new, /* tp_new */ }; pyo/src/objects/lfomodule.c0000644000175000017500000013236312652732202015240 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD PyObject *freq; Stream *freq_stream; PyObject *sharp; Stream *sharp_stream; int modebuffer[4]; // need at least 2 slots for mul & add int wavetype; MYFLT oneOverPiOverTwo; MYFLT srOverFour; MYFLT srOverEight; MYFLT pointerPos; MYFLT sahPointerPos; MYFLT sahCurrentValue; MYFLT sahLastValue; MYFLT modPointerPos; } LFO; static void LFO_generates_ii(LFO *self) { MYFLT val, inc, freq, sharp, pointer, numh; MYFLT v1, v2, inc2, fade; int i, maxHarms; freq = PyFloat_AS_DOUBLE(self->freq); if (freq <= 0) { return; } sharp = PyFloat_AS_DOUBLE(self->sharp); if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; inc = freq / self->sr; switch (self->wavetype) { case 0: /* Saw up */ maxHarms = (int)(self->srOverFour/freq); numh = sharp * 46.0 + 4.0; if (numh > maxHarms) numh = maxHarms; for (i=0; ibufsize; i++) { pointer = self->pointerPos * 2.0 - 1.0; val = pointer - MYTANH(numh * pointer) / MYTANH(numh); self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 1: /* Saw down */ maxHarms = (int)(self->srOverFour/freq); numh = sharp * 46.0 + 4.0; if (numh > maxHarms) numh = maxHarms; for (i=0; ibufsize; i++) { pointer = self->pointerPos * 2.0 - 1.0; val = -(pointer - MYTANH(numh * pointer) / MYTANH(numh)); self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 2: /* Square */ maxHarms = (int)(self->srOverEight/freq); numh = sharp * 46.0 + 4.0; if (numh > maxHarms) numh = maxHarms; for (i=0; ibufsize; i++) { val = MYATAN(numh * MYSIN(TWOPI*self->pointerPos)); self->data[i] = val * self->oneOverPiOverTwo; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 3: /* Triangle */ maxHarms = (int)(self->srOverFour/freq); if ((sharp * 36.0) > maxHarms) numh = (MYFLT)(maxHarms / 36.0); else numh = sharp; for (i=0; ibufsize; i++) { v1 = MYTAN(MYSIN(TWOPI*self->pointerPos)) * self->oneOverPiOverTwo; pointer = self->pointerPos + 0.25; if (pointer > 1.0) pointer -= 1.0; v2 = 4.0 * (0.5 - MYFABS(pointer - 0.5)) - 1.0; val = v1 * (1 - numh) + v2 * numh; self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 4: /* Pulse */ maxHarms = (int)(self->srOverEight/freq); numh = MYFLOOR(sharp * 46.0 + 4.0); if (numh > maxHarms) numh = maxHarms; if (MYFMOD(numh, 2.0) == 0.0) numh += 1.0; for (i=0; ibufsize; i++) { val = MYTAN(MYPOW(MYFABS(MYSIN(TWOPI*self->pointerPos)), numh)); self->data[i] = val * self->oneOverPiOverTwo; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 5: /* Bi-Pulse */ maxHarms = (int)(self->srOverEight/freq); numh = MYFLOOR(sharp * 46.0 + 4.0); if (numh > maxHarms) numh = maxHarms; if (MYFMOD(numh, 2.0) == 0.0) numh += 1.0; for (i=0; ibufsize; i++) { val = MYTAN(MYPOW(MYSIN(TWOPI*self->pointerPos), numh)); self->data[i] = val * self->oneOverPiOverTwo; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 6: /* SAH */ numh = 1.0 - sharp; inc2 = 1.0 / (int)(1.0 / inc * numh); for (i=0; ibufsize; i++) { self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) { self->pointerPos -= 1.0; self->sahPointerPos = 0.0; self->sahLastValue = self->sahCurrentValue; self->sahCurrentValue = rand()/((MYFLT)(RAND_MAX)*0.5) - 1.0; } if (self->sahPointerPos < 1.0) { fade = 0.5 * MYSIN(PI * (self->sahPointerPos+0.5)) + 0.5; val = self->sahCurrentValue * (1.0 - fade) + self->sahLastValue * fade; self->sahPointerPos += inc2; } else { val = self->sahCurrentValue; } self->data[i] = val; } break; case 7: /* Sine-mod */ inc2 = inc * sharp; for (i=0; ibufsize; i++) { self->modPointerPos += inc2; if (self->modPointerPos < 0) self->modPointerPos += 1.0; else if (self->modPointerPos >= 1) self->modPointerPos -= 1.0; val = (0.5 * MYCOS(TWOPI*self->modPointerPos) + 0.5) * MYSIN(TWOPI*self->pointerPos); self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; default: break; } } static void LFO_generates_ai(LFO *self) { MYFLT val, inc, freq, sharp, pointer, numh; MYFLT v1, v2, inc2, fade; int i, maxHarms; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); if (fr[0] <= 0) { return; } sharp = PyFloat_AS_DOUBLE(self->sharp); if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; switch (self->wavetype) { case 0: /* Saw up */ for (i=0; ibufsize; i++) { freq = fr[i]; inc = freq / self->sr; maxHarms = (int)(self->srOverFour/freq); numh = sharp * 46.0 + 4.0; if (numh > maxHarms) numh = maxHarms; pointer = self->pointerPos * 2.0 - 1.0; val = pointer - MYTANH(numh * pointer) / MYTANH(numh); self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 1: /* Saw down */ for (i=0; ibufsize; i++) { freq = fr[i]; inc = freq / self->sr; maxHarms = (int)(self->srOverFour/freq); numh = sharp * 46.0 + 4.0; if (numh > maxHarms) numh = maxHarms; pointer = self->pointerPos * 2.0 - 1.0; val = -(pointer - MYTANH(numh * pointer) / MYTANH(numh)); self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 2: /* Square */ for (i=0; ibufsize; i++) { freq = fr[i]; inc = freq / self->sr; maxHarms = (int)(self->srOverEight/freq); numh = sharp * 46.0 + 4.0; if (numh > maxHarms) numh = maxHarms; val = MYATAN(numh * MYSIN(TWOPI*self->pointerPos)); self->data[i] = val * self->oneOverPiOverTwo; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 3: /* Triangle */ for (i=0; ibufsize; i++) { freq = fr[i]; inc = freq / self->sr; maxHarms = (int)(self->srOverFour/freq); if ((sharp * 36.0) > maxHarms) numh = (MYFLT)(maxHarms / 36.0); else numh = sharp; v1 = MYTAN(MYSIN(TWOPI*self->pointerPos)); pointer = self->pointerPos + 0.25; if (pointer > 1.0) pointer -= 1.0; v2 = 4.0 * (0.5 - MYFABS(pointer - 0.5)) - 1.0; val = v1 * (1 - numh) + v2 * numh; self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 4: /* Pulse */ for (i=0; ibufsize; i++) { freq = fr[i]; inc = freq / self->sr; maxHarms = (int)(self->srOverEight/freq); numh = MYFLOOR(sharp * 46.0 + 4.0); if (numh > maxHarms) numh = maxHarms; if (MYFMOD(numh, 2.0) == 0.0) numh += 1.0; val = MYTAN(MYPOW(MYFABS(MYSIN(TWOPI*self->pointerPos)), numh)); self->data[i] = val * self->oneOverPiOverTwo; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 5: /* Bi-Pulse */ for (i=0; ibufsize; i++) { freq = fr[i]; inc = freq / self->sr; maxHarms = (int)(self->srOverEight/freq); numh = MYFLOOR(sharp * 46.0 + 4.0); if (numh > maxHarms) numh = maxHarms; if (MYFMOD(numh, 2.0) == 0.0) numh += 1.0; val = MYTAN(MYPOW(MYSIN(TWOPI*self->pointerPos), numh)); self->data[i] = val * self->oneOverPiOverTwo; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 6: /* SAH */ numh = 1.0 - sharp; for (i=0; ibufsize; i++) { freq = fr[i]; inc = freq / self->sr; inc2 = 1.0 / (int)(1.0 / inc * numh); self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) { self->pointerPos -= 1.0; self->sahPointerPos = 0.0; self->sahLastValue = self->sahCurrentValue; self->sahCurrentValue = rand()/((MYFLT)(RAND_MAX)*0.5) - 1.0; } if (self->sahPointerPos < 1.0) { fade = 0.5 * MYSIN(PI * (self->sahPointerPos+0.5)) + 0.5; val = self->sahCurrentValue * (1.0 - fade) + self->sahLastValue * fade; self->sahPointerPos += inc2; } else { val = self->sahCurrentValue; } self->data[i] = val; } break; case 7: /* Sine-mod */ for (i=0; ibufsize; i++) { freq = fr[i]; inc = freq / self->sr; inc2 = inc * sharp; self->modPointerPos += inc2; if (self->modPointerPos < 0) self->modPointerPos += 1.0; else if (self->modPointerPos >= 1) self->modPointerPos -= 1.0; val = (0.5 * MYCOS(TWOPI*self->modPointerPos) + 0.5) * MYSIN(TWOPI*self->pointerPos); self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; default: break; } } static void LFO_generates_ia(LFO *self) { MYFLT val, inc, freq, sharp, pointer, numh; MYFLT v1, v2, inc2, fade; int i, maxHarms; freq = PyFloat_AS_DOUBLE(self->freq); if (freq <= 0) { return; } MYFLT *sh = Stream_getData((Stream *)self->sharp_stream); inc = freq / self->sr; switch (self->wavetype) { case 0: /* Saw up */ maxHarms = (int)(self->srOverFour/freq); for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; numh = sharp * 46.0 + 4.0; if (numh > maxHarms) numh = maxHarms; pointer = self->pointerPos * 2.0 - 1.0; val = pointer - MYTANH(numh * pointer) / MYTANH(numh); self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 1: /* Saw down */ maxHarms = (int)(self->srOverFour/freq); for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; numh = sharp * 46.0 + 4.0; if (numh > maxHarms) numh = maxHarms; pointer = self->pointerPos * 2.0 - 1.0; val = -(pointer - MYTANH(numh * pointer) / MYTANH(numh)); self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 2: /* Square */ maxHarms = (int)(self->srOverEight/freq); for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; numh = sharp * 46.0 + 4.0; if (numh > maxHarms) numh = maxHarms; val = MYATAN(numh * MYSIN(TWOPI*self->pointerPos)); self->data[i] = val * self->oneOverPiOverTwo; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 3: /* Triangle */ maxHarms = (int)(self->srOverFour/freq); for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; if ((sharp * 36.0) > maxHarms) numh = (MYFLT)(maxHarms / 36.0); else numh = sharp; v1 = MYTAN(MYSIN(TWOPI*self->pointerPos)); pointer = self->pointerPos + 0.25; if (pointer > 1.0) pointer -= 1.0; v2 = 4.0 * (0.5 - MYFABS(pointer - 0.5)) - 1.0; val = v1 * (1 - numh) + v2 * numh; self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 4: /* Pulse */ maxHarms = (int)(self->srOverEight/freq); for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; numh = MYFLOOR(sharp * 46.0 + 4.0); if (numh > maxHarms) numh = maxHarms; if (MYFMOD(numh, 2.0) == 0.0) numh += 1.0; val = MYTAN(MYPOW(MYFABS(MYSIN(TWOPI*self->pointerPos)), numh)); self->data[i] = val * self->oneOverPiOverTwo; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 5: /* Bi-Pulse */ maxHarms = (int)(self->srOverEight/freq); for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; numh = MYFLOOR(sharp * 46.0 + 4.0); if (numh > maxHarms) numh = maxHarms; if (MYFMOD(numh, 2.0) == 0.0) numh += 1.0; val = MYTAN(MYPOW(MYSIN(TWOPI*self->pointerPos), numh)); self->data[i] = val * self->oneOverPiOverTwo; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 6: /* SAH */ for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; numh = 1.0 - sharp; inc2 = 1.0 / (int)(1.0 / inc * numh); self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) { self->pointerPos -= 1.0; self->sahPointerPos = 0.0; self->sahLastValue = self->sahCurrentValue; self->sahCurrentValue = rand()/((MYFLT)(RAND_MAX)*0.5) - 1.0; } if (self->sahPointerPos < 1.0) { fade = 0.5 * MYSIN(PI * (self->sahPointerPos+0.5)) + 0.5; val = self->sahCurrentValue * (1.0 - fade) + self->sahLastValue * fade; self->sahPointerPos += inc2; } else { val = self->sahCurrentValue; } self->data[i] = val; } break; case 7: /* Sine-mod */ for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; inc2 = inc * sharp; self->modPointerPos += inc2; if (self->modPointerPos < 0) self->modPointerPos += 1.0; else if (self->modPointerPos >= 1) self->modPointerPos -= 1.0; val = (0.5 * MYCOS(TWOPI*self->modPointerPos) + 0.5) * MYSIN(TWOPI*self->pointerPos); self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; default: break; } } static void LFO_generates_aa(LFO *self) { MYFLT val, inc, freq, sharp, pointer, numh; MYFLT v1, v2, inc2, fade; int i, maxHarms; MYFLT *fr = Stream_getData((Stream *)self->freq_stream); if (fr[0] <= 0) { return; } MYFLT *sh = Stream_getData((Stream *)self->sharp_stream); switch (self->wavetype) { case 0: /* Saw up */ for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; freq = fr[i]; inc = freq / self->sr; maxHarms = (int)(self->srOverFour/freq); numh = sharp * 46.0 + 4.0; if (numh > maxHarms) numh = maxHarms; pointer = self->pointerPos * 2.0 - 1.0; val = pointer - MYTANH(numh * pointer) / MYTANH(numh); self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 1: /* Saw down */ for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; freq = fr[i]; inc = freq / self->sr; maxHarms = (int)(self->srOverFour/freq); numh = sharp * 46.0 + 4.0; if (numh > maxHarms) numh = maxHarms; pointer = self->pointerPos * 2.0 - 1.0; val = -(pointer - MYTANH(numh * pointer) / MYTANH(numh)); self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 2: /* Square */ for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; freq = fr[i]; inc = freq / self->sr; maxHarms = (int)(self->srOverEight/freq); numh = sharp * 46.0 + 4.0; if (numh > maxHarms) numh = maxHarms; val = MYATAN(numh * MYSIN(TWOPI*self->pointerPos)); self->data[i] = val * self->oneOverPiOverTwo; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 3: /* Triangle */ for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; freq = fr[i]; inc = freq / self->sr; maxHarms = (int)(self->srOverFour/freq); if ((sharp * 36.0) > maxHarms) numh = (MYFLT)(maxHarms / 36.0); else numh = sharp; v1 = MYTAN(MYSIN(TWOPI*self->pointerPos)); pointer = self->pointerPos + 0.25; if (pointer > 1.0) pointer -= 1.0; v2 = 4.0 * (0.5 - MYFABS(pointer - 0.5)) - 1.0; val = v1 * (1 - numh) + v2 * numh; self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 4: /* Pulse */ for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; freq = fr[i]; inc = freq / self->sr; maxHarms = (int)(self->srOverEight/freq); numh = MYFLOOR(sharp * 46.0 + 4.0); if (numh > maxHarms) numh = maxHarms; if (MYFMOD(numh, 2.0) == 0.0) numh += 1.0; val = MYTAN(MYPOW(MYFABS(MYSIN(TWOPI*self->pointerPos)), numh)); self->data[i] = val * self->oneOverPiOverTwo; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 5: /* Bi-Pulse */ for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; freq = fr[i]; inc = freq / self->sr; maxHarms = (int)(self->srOverEight/freq); numh = MYFLOOR(sharp * 46.0 + 4.0); if (numh > maxHarms) numh = maxHarms; if (MYFMOD(numh, 2.0) == 0.0) numh += 1.0; val = MYTAN(MYPOW(MYSIN(TWOPI*self->pointerPos), numh)); self->data[i] = val * self->oneOverPiOverTwo; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; case 6: /* SAH */ for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; numh = 1.0 - sharp; freq = fr[i]; inc = freq / self->sr; inc2 = 1.0 / (int)(1.0 / inc * numh); self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) { self->pointerPos -= 1.0; self->sahPointerPos = 0.0; self->sahLastValue = self->sahCurrentValue; self->sahCurrentValue = rand()/((MYFLT)(RAND_MAX)*0.5) - 1.0; } if (self->sahPointerPos < 1.0) { fade = 0.5 * MYSIN(PI * (self->sahPointerPos+0.5)) + 0.5; val = self->sahCurrentValue * (1.0 - fade) + self->sahLastValue * fade; self->sahPointerPos += inc2; } else { val = self->sahCurrentValue; } self->data[i] = val; } break; case 7: /* Sine-mod */ for (i=0; ibufsize; i++) { sharp = sh[i]; if (sharp < 0.0) sharp = 0.0; else if (sharp > 1.0) sharp = 1.0; freq = fr[i]; inc = freq / self->sr; inc2 = inc * sharp; self->modPointerPos += inc2; if (self->modPointerPos < 0) self->modPointerPos += 1.0; else if (self->modPointerPos >= 1) self->modPointerPos -= 1.0; val = (0.5 * MYCOS(TWOPI*self->modPointerPos) + 0.5) * MYSIN(TWOPI*self->pointerPos); self->data[i] = val; self->pointerPos += inc; if (self->pointerPos < 0) self->pointerPos += 1.0; else if (self->pointerPos >= 1) self->pointerPos -= 1.0; } break; default: break; } } static void LFO_postprocessing_ii(LFO *self) { POST_PROCESSING_II }; static void LFO_postprocessing_ai(LFO *self) { POST_PROCESSING_AI }; static void LFO_postprocessing_ia(LFO *self) { POST_PROCESSING_IA }; static void LFO_postprocessing_aa(LFO *self) { POST_PROCESSING_AA }; static void LFO_postprocessing_ireva(LFO *self) { POST_PROCESSING_IREVA }; static void LFO_postprocessing_areva(LFO *self) { POST_PROCESSING_AREVA }; static void LFO_postprocessing_revai(LFO *self) { POST_PROCESSING_REVAI }; static void LFO_postprocessing_revaa(LFO *self) { POST_PROCESSING_REVAA }; static void LFO_postprocessing_revareva(LFO *self) { POST_PROCESSING_REVAREVA }; static void LFO_setProcMode(LFO *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = LFO_generates_ii; break; case 1: self->proc_func_ptr = LFO_generates_ai; break; case 10: self->proc_func_ptr = LFO_generates_ia; break; case 11: self->proc_func_ptr = LFO_generates_aa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = LFO_postprocessing_ii; break; case 1: self->muladd_func_ptr = LFO_postprocessing_ai; break; case 2: self->muladd_func_ptr = LFO_postprocessing_revai; break; case 10: self->muladd_func_ptr = LFO_postprocessing_ia; break; case 11: self->muladd_func_ptr = LFO_postprocessing_aa; break; case 12: self->muladd_func_ptr = LFO_postprocessing_revaa; break; case 20: self->muladd_func_ptr = LFO_postprocessing_ireva; break; case 21: self->muladd_func_ptr = LFO_postprocessing_areva; break; case 22: self->muladd_func_ptr = LFO_postprocessing_revareva; break; } } static void LFO_compute_next_data_frame(LFO *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int LFO_traverse(LFO *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->freq); Py_VISIT(self->freq_stream); Py_VISIT(self->sharp); Py_VISIT(self->sharp_stream); return 0; } static int LFO_clear(LFO *self) { pyo_CLEAR Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); Py_CLEAR(self->sharp); Py_CLEAR(self->sharp_stream); return 0; } static void LFO_dealloc(LFO* self) { pyo_DEALLOC LFO_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * LFO_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *freqtmp=NULL, *sharptmp=NULL, *multmp=NULL, *addtmp=NULL; LFO *self; self = (LFO *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(100); self->sharp = PyFloat_FromDouble(0.5); self->oneOverPiOverTwo = 1.0 / (PI / 2.0); self->wavetype = 0; self->pointerPos = 0.0; self->sahPointerPos = 0.0; self->modPointerPos = 0.0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; INIT_OBJECT_COMMON self->srOverFour = (MYFLT)self->sr * 0.25; self->srOverEight = (MYFLT)self->sr * 0.125; Stream_setFunctionPtr(self->stream, LFO_compute_next_data_frame); self->mode_func_ptr = LFO_setProcMode; static char *kwlist[] = {"freq", "sharp", "type", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOiOO", kwlist, &freqtmp, &sharptmp, &self->wavetype, &multmp, &addtmp)) Py_RETURN_NONE; if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (sharptmp) { PyObject_CallMethod((PyObject *)self, "setSharp", "O", sharptmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); Server_generateSeed((Server *)self->server, LFO_ID); self->sahCurrentValue = self->sahLastValue = rand()/((MYFLT)(RAND_MAX)*0.5) - 1.0; (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * LFO_getServer(LFO* self) { GET_SERVER }; static PyObject * LFO_getStream(LFO* self) { GET_STREAM }; static PyObject * LFO_setMul(LFO *self, PyObject *arg) { SET_MUL }; static PyObject * LFO_setAdd(LFO *self, PyObject *arg) { SET_ADD }; static PyObject * LFO_setSub(LFO *self, PyObject *arg) { SET_SUB }; static PyObject * LFO_setDiv(LFO *self, PyObject *arg) { SET_DIV }; static PyObject * LFO_play(LFO *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * LFO_out(LFO *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * LFO_stop(LFO *self) { STOP }; static PyObject * LFO_multiply(LFO *self, PyObject *arg) { MULTIPLY }; static PyObject * LFO_inplace_multiply(LFO *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * LFO_add(LFO *self, PyObject *arg) { ADD }; static PyObject * LFO_inplace_add(LFO *self, PyObject *arg) { INPLACE_ADD }; static PyObject * LFO_sub(LFO *self, PyObject *arg) { SUB }; static PyObject * LFO_inplace_sub(LFO *self, PyObject *arg) { INPLACE_SUB }; static PyObject * LFO_div(LFO *self, PyObject *arg) { DIV }; static PyObject * LFO_inplace_div(LFO *self, PyObject *arg) { INPLACE_DIV }; static PyObject * LFO_setFreq(LFO *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * LFO_setSharp(LFO *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->sharp); if (isNumber == 1) { self->sharp = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->sharp = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->sharp, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->sharp_stream); self->sharp_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * LFO_setType(LFO *self, PyObject *arg) { int tmp; ASSERT_ARG_NOT_NULL int isInt = PyInt_Check(arg); if (isInt == 1) { tmp = PyInt_AsLong(arg); if (tmp >= 0 && tmp < 8) self->wavetype = tmp; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * LFO_reset(LFO *self) { self->pointerPos = 0.0; self->sahPointerPos = 0.0; self->modPointerPos = 0.0; Py_INCREF(Py_None); return Py_None; } static PyMemberDef LFO_members[] = { {"server", T_OBJECT_EX, offsetof(LFO, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(LFO, stream), 0, "Stream object."}, {"freq", T_OBJECT_EX, offsetof(LFO, freq), 0, "Cutoff frequency in cycle per second."}, {"sharp", T_OBJECT_EX, offsetof(LFO, sharp), 0, "Sharpness factor."}, {"mul", T_OBJECT_EX, offsetof(LFO, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(LFO, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef LFO_methods[] = { {"getServer", (PyCFunction)LFO_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)LFO_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)LFO_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)LFO_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)LFO_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)LFO_setFreq, METH_O, "Sets oscillator frequency in cycle per second."}, {"setSharp", (PyCFunction)LFO_setSharp, METH_O, "Sets the sharpness factor."}, {"setType", (PyCFunction)LFO_setType, METH_O, "Sets waveform type."}, {"reset", (PyCFunction)LFO_reset, METH_NOARGS, "Resets pointer position to 0."}, {"setMul", (PyCFunction)LFO_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)LFO_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)LFO_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)LFO_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods LFO_as_number = { (binaryfunc)LFO_add, /*nb_add*/ (binaryfunc)LFO_sub, /*nb_subtract*/ (binaryfunc)LFO_multiply, /*nb_multiply*/ (binaryfunc)LFO_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)LFO_inplace_add, /*inplace_add*/ (binaryfunc)LFO_inplace_sub, /*inplace_subtract*/ (binaryfunc)LFO_inplace_multiply, /*inplace_multiply*/ (binaryfunc)LFO_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject LFOType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.LFO_base", /*tp_name*/ sizeof(LFO), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)LFO_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &LFO_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "LFO objects. Generates a Low Frequency Oscillator with different waveshapes.", /* tp_doc */ (traverseproc)LFO_traverse, /* tp_traverse */ (inquiry)LFO_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ LFO_methods, /* tp_methods */ LFO_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ LFO_new, /* tp_new */ };pyo/src/objects/compressmodule.c0000644000175000017500000021102112652732202016300 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" /* Compressor */ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *risetime; PyObject *falltime; PyObject *thresh; PyObject *ratio; Stream *risetime_stream; Stream *falltime_stream; Stream *thresh_stream; Stream *ratio_stream; int modebuffer[6]; // need at least 2 slots for mul & add int outputAmp; MYFLT follow; MYFLT knee; long lh_delay; long lh_size; long lh_in_count; MYFLT *lh_buffer; } Compress; static MYFLT C_clip(MYFLT x) { if (x <= 0.0) return 0.00000001; else if (x > 1.0) return 1.0; else return x; } static void Compress_compress_soft(Compress *self) { MYFLT samp, ampthresh, absin, indb, diff, outdb, outa; MYFLT kneethresh, kneescl, knee, kneeratio, invKneeRange; MYFLT risetime, falltime, thresh, ratio; int i; long ind; MYFLT *in = Stream_getData((Stream *)self->input_stream); if (self->modebuffer[2] == 0) risetime = PyFloat_AS_DOUBLE(self->risetime); else risetime = Stream_getData((Stream *)self->risetime_stream)[0]; if (risetime <= 0.0) risetime = 0.001; if (self->modebuffer[3] == 0) falltime = PyFloat_AS_DOUBLE(self->falltime); else falltime = Stream_getData((Stream *)self->falltime_stream)[0]; if (falltime <= 0.0) falltime = 0.001; if (self->modebuffer[4] == 0) thresh = PyFloat_AS_DOUBLE(self->thresh); else thresh = Stream_getData((Stream *)self->thresh_stream)[0]; if (self->modebuffer[5] == 0) ratio = PyFloat_AS_DOUBLE(self->ratio); else ratio = Stream_getData((Stream *)self->ratio_stream)[0]; ratio = 1.0 / ratio; risetime = MYEXP(-1.0 / (self->sr * risetime)); falltime = MYEXP(-1.0 / (self->sr * falltime)); knee = self->knee * 0.999 + 0.001; /* 0 = hard knee, 1 = soft knee */ thresh += 3.0 * self->knee; if (thresh > 0.0) thresh = 0.0; ampthresh = MYPOW(10.0, thresh * 0.05); /* up to 3 dB above threshold */ kneethresh = MYPOW(10.0, (thresh - (self->knee * 8.5 + 0.5)) * 0.05); /* up to 6 dB under threshold */ invKneeRange = 1.0 / (ampthresh - kneethresh); for (i=0; ibufsize; i++) { /* Envelope follower */ absin = in[i]; if (absin < 0.0) absin = -absin; if (self->follow < absin) self->follow = absin + risetime * (self->follow - absin); else self->follow = absin + falltime * (self->follow - absin); /* Look ahead */ ind = self->lh_in_count - self->lh_delay; if (ind < 0) ind += self->lh_size; samp = self->lh_buffer[ind]; self->lh_buffer[self->lh_in_count] = in[i]; self->lh_in_count++; if (self->lh_in_count >= self->lh_size) self->lh_in_count = 0; /* Compress signal */ outa = 1.0; if (self->follow > ampthresh) { /* Above threshold */ indb = 20.0 * MYLOG10(C_clip(self->follow)); diff = indb - thresh; outdb = diff - diff * ratio; outa = MYPOW(10.0, -outdb * 0.05); } else if (self->follow > kneethresh) { /* Under the knee */ kneescl = (self->follow - kneethresh) * invKneeRange; kneeratio = (((knee + 1.0) * kneescl) / (knee + kneescl)) * (ratio - 1.0) + 1.0; indb = 20.0 * MYLOG10(C_clip(self->follow)); diff = indb - thresh; outdb = diff - diff * kneeratio; outa = MYPOW(10.0, -outdb * 0.05); } if (self->outputAmp == 0) self->data[i] = samp * C_clip(outa); else self->data[i] = C_clip(outa); } } static void Compress_postprocessing_ii(Compress *self) { POST_PROCESSING_II }; static void Compress_postprocessing_ai(Compress *self) { POST_PROCESSING_AI }; static void Compress_postprocessing_ia(Compress *self) { POST_PROCESSING_IA }; static void Compress_postprocessing_aa(Compress *self) { POST_PROCESSING_AA }; static void Compress_postprocessing_ireva(Compress *self) { POST_PROCESSING_IREVA }; static void Compress_postprocessing_areva(Compress *self) { POST_PROCESSING_AREVA }; static void Compress_postprocessing_revai(Compress *self) { POST_PROCESSING_REVAI }; static void Compress_postprocessing_revaa(Compress *self) { POST_PROCESSING_REVAA }; static void Compress_postprocessing_revareva(Compress *self) { POST_PROCESSING_REVAREVA }; static void Compress_setProcMode(Compress *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Compress_postprocessing_ii; break; case 1: self->muladd_func_ptr = Compress_postprocessing_ai; break; case 2: self->muladd_func_ptr = Compress_postprocessing_revai; break; case 10: self->muladd_func_ptr = Compress_postprocessing_ia; break; case 11: self->muladd_func_ptr = Compress_postprocessing_aa; break; case 12: self->muladd_func_ptr = Compress_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Compress_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Compress_postprocessing_areva; break; case 22: self->muladd_func_ptr = Compress_postprocessing_revareva; break; } } static void Compress_compute_next_data_frame(Compress *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Compress_traverse(Compress *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->risetime); Py_VISIT(self->risetime_stream); Py_VISIT(self->falltime); Py_VISIT(self->falltime_stream); Py_VISIT(self->thresh); Py_VISIT(self->thresh_stream); Py_VISIT(self->ratio); Py_VISIT(self->ratio_stream); return 0; } static int Compress_clear(Compress *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->risetime); Py_CLEAR(self->risetime_stream); Py_CLEAR(self->falltime); Py_CLEAR(self->falltime_stream); Py_CLEAR(self->thresh); Py_CLEAR(self->thresh_stream); Py_CLEAR(self->ratio); Py_CLEAR(self->ratio_stream); return 0; } static void Compress_dealloc(Compress* self) { pyo_DEALLOC free(self->lh_buffer); Compress_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Compress_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *threshtmp=NULL, *ratiotmp=NULL, *risetimetmp=NULL, *falltimetmp=NULL, *multmp=NULL, *addtmp=NULL; PyObject *looktmp=NULL, *kneetmp=NULL; Compress *self; self = (Compress *)type->tp_alloc(type, 0); self->thresh = PyFloat_FromDouble(-20.0); self->ratio = PyFloat_FromDouble(2.0); self->risetime = PyFloat_FromDouble(0.01); self->falltime = PyFloat_FromDouble(0.1); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->modebuffer[5] = 0; self->outputAmp = 0; self->follow = 0.0; self->lh_delay = 0; self->lh_in_count = 0; self->knee = 0.; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Compress_compute_next_data_frame); self->mode_func_ptr = Compress_setProcMode; static char *kwlist[] = {"input", "thresh", "ratio", "risetime", "falltime", "lookahead", "knee", "outputAmp", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOOOiOO", kwlist, &inputtmp, &threshtmp, &ratiotmp, &risetimetmp, &falltimetmp, &looktmp, &kneetmp, &self->outputAmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (threshtmp) { PyObject_CallMethod((PyObject *)self, "setThresh", "O", threshtmp); } if (ratiotmp) { PyObject_CallMethod((PyObject *)self, "setRatio", "O", ratiotmp); } if (risetimetmp) { PyObject_CallMethod((PyObject *)self, "setRiseTime", "O", risetimetmp); } if (falltimetmp) { PyObject_CallMethod((PyObject *)self, "setFallTime", "O", falltimetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod((PyObject *)self, "setLookAhead", "O", looktmp); PyObject_CallMethod((PyObject *)self, "setKnee", "O", kneetmp); self->lh_size = (long)(0.025 * self->sr + 0.5); self->lh_buffer = (MYFLT *)realloc(self->lh_buffer, (self->lh_size+1) * sizeof(MYFLT)); for (i=0; i<(self->lh_size+1); i++) { self->lh_buffer[i] = 0.; } self->proc_func_ptr = Compress_compress_soft; PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Compress_getServer(Compress* self) { GET_SERVER }; static PyObject * Compress_getStream(Compress* self) { GET_STREAM }; static PyObject * Compress_setMul(Compress *self, PyObject *arg) { SET_MUL }; static PyObject * Compress_setAdd(Compress *self, PyObject *arg) { SET_ADD }; static PyObject * Compress_setSub(Compress *self, PyObject *arg) { SET_SUB }; static PyObject * Compress_setDiv(Compress *self, PyObject *arg) { SET_DIV }; static PyObject * Compress_play(Compress *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Compress_out(Compress *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Compress_stop(Compress *self) { STOP }; static PyObject * Compress_multiply(Compress *self, PyObject *arg) { MULTIPLY }; static PyObject * Compress_inplace_multiply(Compress *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Compress_add(Compress *self, PyObject *arg) { ADD }; static PyObject * Compress_inplace_add(Compress *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Compress_sub(Compress *self, PyObject *arg) { SUB }; static PyObject * Compress_inplace_sub(Compress *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Compress_div(Compress *self, PyObject *arg) { DIV }; static PyObject * Compress_inplace_div(Compress *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Compress_setThresh(Compress *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->thresh); if (isNumber == 1) { self->thresh = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->thresh = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->thresh, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->thresh_stream); self->thresh_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * Compress_setRatio(Compress *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->ratio); if (isNumber == 1) { self->ratio = PyNumber_Float(tmp); self->modebuffer[5] = 0; } else { self->ratio = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->ratio, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->ratio_stream); self->ratio_stream = (Stream *)streamtmp; self->modebuffer[5] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * Compress_setRiseTime(Compress *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->risetime); if (isNumber == 1) { self->risetime = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->risetime = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->risetime, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->risetime_stream); self->risetime_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * Compress_setFallTime(Compress *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->falltime); if (isNumber == 1) { self->falltime = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->falltime = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->falltime, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->falltime_stream); self->falltime_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } Py_INCREF(Py_None); return Py_None; } static PyObject * Compress_setLookAhead(Compress *self, PyObject *arg) { MYFLT tmp; ASSERT_ARG_NOT_NULL if (PyNumber_Check(arg)) { tmp = PyFloat_AsDouble(arg); if (tmp <= 25.0) self->lh_delay = (long)(tmp * 0.001 * self->sr); else printf("lookahead must be less than 25.0 ms.\n"); } Py_INCREF(Py_None); return Py_None; } static PyObject * Compress_setKnee(Compress *self, PyObject *arg) { MYFLT tmp; ASSERT_ARG_NOT_NULL if (PyNumber_Check(arg)) { tmp = PyFloat_AsDouble(arg); if (tmp >= 0.0 && tmp <= 1.0) self->knee = tmp; else printf("knee must be in range 0 (hard) -> 1 (soft).\n"); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Compress_members[] = { {"server", T_OBJECT_EX, offsetof(Compress, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Compress, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Compress, input), 0, "Input sound object."}, {"thresh", T_OBJECT_EX, offsetof(Compress, thresh), 0, "Compressor threshold."}, {"ratio", T_OBJECT_EX, offsetof(Compress, ratio), 0, "Compressor ratio."}, {"risetime", T_OBJECT_EX, offsetof(Compress, risetime), 0, "Rising portamento time in seconds."}, {"falltime", T_OBJECT_EX, offsetof(Compress, falltime), 0, "Falling portamento time in seconds."}, {"mul", T_OBJECT_EX, offsetof(Compress, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Compress, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Compress_methods[] = { {"getServer", (PyCFunction)Compress_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Compress_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Compress_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Compress_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Compress_stop, METH_NOARGS, "Stops computing."}, {"setThresh", (PyCFunction)Compress_setThresh, METH_O, "Sets compressor threshold."}, {"setRatio", (PyCFunction)Compress_setRatio, METH_O, "Sets compressor ratio."}, {"setRiseTime", (PyCFunction)Compress_setRiseTime, METH_O, "Sets rising portamento time in seconds."}, {"setFallTime", (PyCFunction)Compress_setFallTime, METH_O, "Sets falling portamento time in seconds."}, {"setLookAhead", (PyCFunction)Compress_setLookAhead, METH_O, "Sets look ahead time in ms."}, {"setKnee", (PyCFunction)Compress_setKnee, METH_O, "Sets the knee between 0 (hard) and 1 (soft)."}, {"setMul", (PyCFunction)Compress_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)Compress_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)Compress_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Compress_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Compress_as_number = { (binaryfunc)Compress_add, /*nb_add*/ (binaryfunc)Compress_sub, /*nb_subtract*/ (binaryfunc)Compress_multiply, /*nb_multiply*/ (binaryfunc)Compress_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Compress_inplace_add, /*inplace_add*/ (binaryfunc)Compress_inplace_sub, /*inplace_subtract*/ (binaryfunc)Compress_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Compress_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject CompressType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Compress_base", /*tp_name*/ sizeof(Compress), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Compress_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Compress_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Compress objects. Compress audio signal by a certain ratio above a threshold.", /* tp_doc */ (traverseproc)Compress_traverse, /* tp_traverse */ (inquiry)Compress_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Compress_methods, /* tp_methods */ Compress_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Compress_new, /* tp_new */ }; const MYFLT GATE_MIN_RAMP_TIME = 0.0001; /************/ /* Gate */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *thresh; Stream *thresh_stream; PyObject *risetime; Stream *risetime_stream; PyObject *falltime; Stream *falltime_stream; int modebuffer[5]; // need at least 2 slots for mul & add int outputAmp; MYFLT lpfollow; MYFLT lpfactor; MYFLT gate; MYFLT last_risetime; MYFLT last_falltime; MYFLT risefactor; MYFLT fallfactor; long lh_delay; long lh_size; long lh_in_count; MYFLT *lh_buffer; } Gate; static void Gate_filters_iii(Gate *self) { MYFLT samp, absin, thresh, ampthresh, risetime, falltime; int i, ind; MYFLT *in = Stream_getData((Stream *)self->input_stream); thresh = PyFloat_AS_DOUBLE(self->thresh); risetime = PyFloat_AS_DOUBLE(self->risetime); if (risetime <= 0.0) risetime = GATE_MIN_RAMP_TIME; falltime = PyFloat_AS_DOUBLE(self->falltime); if (falltime <= 0.0) falltime = GATE_MIN_RAMP_TIME; if (risetime != self->last_risetime) { self->risefactor = MYEXP(-1.0 / (self->sr * risetime)); self->last_risetime = risetime; } if (falltime != self->last_falltime) { self->fallfactor = MYEXP(-1.0 / (self->sr * falltime)); self->last_falltime = falltime; } ampthresh = MYPOW(10.0, thresh * 0.05); for (i=0; ibufsize; i++) { /* Follower */ absin = in[i] * in[i]; self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin); /* Gate slope */ if (self->lpfollow >= ampthresh) self->gate = 1.0 + self->risefactor * (self->gate - 1.0); else self->gate = self->fallfactor * self->gate; /* Look ahead */ ind = self->lh_in_count - self->lh_delay; if (ind < 0) ind += self->lh_size; samp = self->lh_buffer[ind]; self->lh_buffer[self->lh_in_count] = in[i]; self->lh_in_count++; if (self->lh_in_count >= self->lh_size) self->lh_in_count = 0; /* Gate the signal */ if (self->outputAmp == 0) self->data[i] = samp * self->gate; else self->data[i] = self->gate; } } static void Gate_filters_aii(Gate *self) { MYFLT samp, absin, thresh, ampthresh, risetime, falltime; int i, ind; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *tr = Stream_getData((Stream *)self->thresh_stream); risetime = PyFloat_AS_DOUBLE(self->risetime); if (risetime <= 0.0) risetime = GATE_MIN_RAMP_TIME; falltime = PyFloat_AS_DOUBLE(self->falltime); if (falltime <= 0.0) falltime = GATE_MIN_RAMP_TIME; if (risetime != self->last_risetime) { self->risefactor = MYEXP(-1.0 / (self->sr * risetime)); self->last_risetime = risetime; } if (falltime != self->last_falltime) { self->fallfactor = MYEXP(-1.0 / (self->sr * falltime)); self->last_falltime = falltime; } for (i=0; ibufsize; i++) { thresh = tr[i]; ampthresh = MYPOW(10.0, thresh * 0.05); /* Follower */ absin = in[i] * in[i]; self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin); /* Gate slope */ if (self->lpfollow >= ampthresh) self->gate = 1.0 + self->risefactor * (self->gate - 1.0); else self->gate = self->fallfactor * self->gate; /* Look ahead */ ind = self->lh_in_count - self->lh_delay; if (ind < 0) ind += self->lh_size; samp = self->lh_buffer[ind]; self->lh_buffer[self->lh_in_count] = in[i]; self->lh_in_count++; if (self->lh_in_count >= self->lh_size) self->lh_in_count = 0; /* Gate the signal */ if (self->outputAmp == 0) self->data[i] = samp * self->gate; else self->data[i] = self->gate; } } static void Gate_filters_iai(Gate *self) { MYFLT samp, absin, thresh, ampthresh, risetime, falltime; int i, ind; MYFLT *in = Stream_getData((Stream *)self->input_stream); thresh = PyFloat_AS_DOUBLE(self->thresh); MYFLT *rise = Stream_getData((Stream *)self->risetime_stream); falltime = PyFloat_AS_DOUBLE(self->falltime); if (falltime <= 0.0) falltime = GATE_MIN_RAMP_TIME; if (falltime != self->last_falltime) { self->fallfactor = MYEXP(-1.0 / (self->sr * falltime)); self->last_falltime = falltime; } ampthresh = MYPOW(10.0, thresh * 0.05); for (i=0; ibufsize; i++) { risetime = rise[i]; if (risetime <= 0.0) risetime = GATE_MIN_RAMP_TIME; if (risetime != self->last_risetime) { self->risefactor = MYEXP(-1.0 / (self->sr * risetime)); self->last_risetime = risetime; } /* Follower */ absin = in[i] * in[i]; self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin); /* Gate slope */ if (self->lpfollow >= ampthresh) self->gate = 1.0 + self->risefactor * (self->gate - 1.0); else self->gate = self->fallfactor * self->gate; /* Look ahead */ ind = self->lh_in_count - self->lh_delay; if (ind < 0) ind += self->lh_size; samp = self->lh_buffer[ind]; self->lh_buffer[self->lh_in_count] = in[i]; self->lh_in_count++; if (self->lh_in_count >= self->lh_size) self->lh_in_count = 0; /* Gate the signal */ if (self->outputAmp == 0) self->data[i] = samp * self->gate; else self->data[i] = self->gate; } } static void Gate_filters_aai(Gate *self) { MYFLT samp, absin, thresh, ampthresh, risetime, falltime; int i, ind; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *tr = Stream_getData((Stream *)self->thresh_stream); MYFLT *rise = Stream_getData((Stream *)self->risetime_stream); falltime = PyFloat_AS_DOUBLE(self->falltime); if (falltime <= 0.0) falltime = GATE_MIN_RAMP_TIME; if (falltime != self->last_falltime) { self->fallfactor = MYEXP(-1.0 / (self->sr * falltime)); self->last_falltime = falltime; } for (i=0; ibufsize; i++) { thresh = tr[i]; ampthresh = MYPOW(10.0, thresh * 0.05); risetime = rise[i]; if (risetime <= 0.0) risetime = GATE_MIN_RAMP_TIME; if (risetime != self->last_risetime) { self->risefactor = MYEXP(-1.0 / (self->sr * risetime)); self->last_risetime = risetime; } /* Follower */ absin = in[i] * in[i]; self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin); /* Gate slope */ if (self->lpfollow >= ampthresh) self->gate = 1.0 + self->risefactor * (self->gate - 1.0); else self->gate = self->fallfactor * self->gate; /* Look ahead */ ind = self->lh_in_count - self->lh_delay; if (ind < 0) ind += self->lh_size; samp = self->lh_buffer[ind]; self->lh_buffer[self->lh_in_count] = in[i]; self->lh_in_count++; if (self->lh_in_count >= self->lh_size) self->lh_in_count = 0; /* Gate the signal */ if (self->outputAmp == 0) self->data[i] = samp * self->gate; else self->data[i] = self->gate; } } static void Gate_filters_iia(Gate *self) { MYFLT samp, absin, thresh, ampthresh, risetime, falltime; int i, ind; MYFLT *in = Stream_getData((Stream *)self->input_stream); thresh = PyFloat_AS_DOUBLE(self->thresh); risetime = PyFloat_AS_DOUBLE(self->risetime); if (risetime <= 0.0) risetime = GATE_MIN_RAMP_TIME; MYFLT *fall = Stream_getData((Stream *)self->falltime_stream); if (risetime != self->last_risetime) { self->risefactor = MYEXP(-1.0 / (self->sr * risetime)); self->last_risetime = risetime; } ampthresh = MYPOW(10.0, thresh * 0.05); for (i=0; ibufsize; i++) { falltime = fall[i]; if (falltime <= 0.0) falltime = GATE_MIN_RAMP_TIME; if (falltime != self->last_falltime) { self->fallfactor = MYEXP(-1.0 / (self->sr * falltime)); self->last_falltime = falltime; } /* Follower */ absin = in[i] * in[i]; self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin); /* Gate slope */ if (self->lpfollow >= ampthresh) self->gate = 1.0 + self->risefactor * (self->gate - 1.0); else self->gate = self->fallfactor * self->gate; /* Look ahead */ ind = self->lh_in_count - self->lh_delay; if (ind < 0) ind += self->lh_size; samp = self->lh_buffer[ind]; self->lh_buffer[self->lh_in_count] = in[i]; self->lh_in_count++; if (self->lh_in_count >= self->lh_size) self->lh_in_count = 0; /* Gate the signal */ if (self->outputAmp == 0) self->data[i] = samp * self->gate; else self->data[i] = self->gate; } } static void Gate_filters_aia(Gate *self) { MYFLT samp, absin, thresh, ampthresh, risetime, falltime; int i, ind; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *tr = Stream_getData((Stream *)self->thresh_stream); risetime = PyFloat_AS_DOUBLE(self->risetime); if (risetime <= 0.0) risetime = GATE_MIN_RAMP_TIME; MYFLT *fall = Stream_getData((Stream *)self->falltime_stream); if (risetime != self->last_risetime) { self->risefactor = MYEXP(-1.0 / (self->sr * risetime)); self->last_risetime = risetime; } for (i=0; ibufsize; i++) { thresh = tr[i]; ampthresh = MYPOW(10.0, thresh * 0.05); falltime = fall[i]; if (falltime <= 0.0) falltime = GATE_MIN_RAMP_TIME; if (falltime != self->last_falltime) { self->fallfactor = MYEXP(-1.0 / (self->sr * falltime)); self->last_falltime = falltime; } /* Follower */ absin = in[i] * in[i]; self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin); /* Gate slope */ if (self->lpfollow >= ampthresh) self->gate = 1.0 + self->risefactor * (self->gate - 1.0); else self->gate = self->fallfactor * self->gate; /* Look ahead */ ind = self->lh_in_count - self->lh_delay; if (ind < 0) ind += self->lh_size; samp = self->lh_buffer[ind]; self->lh_buffer[self->lh_in_count] = in[i]; self->lh_in_count++; if (self->lh_in_count >= self->lh_size) self->lh_in_count = 0; /* Gate the signal */ if (self->outputAmp == 0) self->data[i] = samp * self->gate; else self->data[i] = self->gate; } } static void Gate_filters_iaa(Gate *self) { MYFLT samp, absin, thresh, ampthresh, risetime, falltime; int i, ind; MYFLT *in = Stream_getData((Stream *)self->input_stream); thresh = PyFloat_AS_DOUBLE(self->thresh); MYFLT *rise = Stream_getData((Stream *)self->risetime_stream); MYFLT *fall = Stream_getData((Stream *)self->falltime_stream); ampthresh = MYPOW(10.0, thresh * 0.05); for (i=0; ibufsize; i++) { risetime = rise[i]; if (risetime <= 0.0) risetime = GATE_MIN_RAMP_TIME; if (risetime != self->last_risetime) { self->risefactor = MYEXP(-1.0 / (self->sr * risetime)); self->last_risetime = risetime; } falltime = fall[i]; if (falltime <= 0.0) falltime = GATE_MIN_RAMP_TIME; if (falltime != self->last_falltime) { self->fallfactor = MYEXP(-1.0 / (self->sr * falltime)); self->last_falltime = falltime; } /* Follower */ absin = in[i] * in[i]; self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin); /* Gate slope */ if (self->lpfollow >= ampthresh) self->gate = 1.0 + self->risefactor * (self->gate - 1.0); else self->gate = self->fallfactor * self->gate; /* Look ahead */ ind = self->lh_in_count - self->lh_delay; if (ind < 0) ind += self->lh_size; samp = self->lh_buffer[ind]; self->lh_buffer[self->lh_in_count] = in[i]; self->lh_in_count++; if (self->lh_in_count >= self->lh_size) self->lh_in_count = 0; /* Gate the signal */ if (self->outputAmp == 0) self->data[i] = samp * self->gate; else self->data[i] = self->gate; } } static void Gate_filters_aaa(Gate *self) { MYFLT samp, absin, thresh, ampthresh, risetime, falltime; int i, ind; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *tr = Stream_getData((Stream *)self->thresh_stream); MYFLT *rise = Stream_getData((Stream *)self->risetime_stream); MYFLT *fall = Stream_getData((Stream *)self->falltime_stream); for (i=0; ibufsize; i++) { thresh = tr[i]; ampthresh = MYPOW(10.0, thresh * 0.05); risetime = rise[i]; if (risetime <= 0.0) risetime = 0.001; if (risetime != self->last_risetime) { self->risefactor = MYEXP(-1.0 / (self->sr * risetime)); self->last_risetime = risetime; } falltime = fall[i]; if (falltime <= 0.0) falltime = 0.001; if (falltime != self->last_falltime) { self->fallfactor = MYEXP(-1.0 / (self->sr * falltime)); self->last_falltime = falltime; } /* Follower */ absin = in[i] * in[i]; self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin); /* Gate slope */ if (self->lpfollow >= ampthresh) self->gate = 1.0 + self->risefactor * (self->gate - 1.0); else self->gate = self->fallfactor * self->gate; /* Look ahead */ ind = self->lh_in_count - self->lh_delay; if (ind < 0) ind += self->lh_size; samp = self->lh_buffer[ind]; self->lh_buffer[self->lh_in_count] = in[i]; self->lh_in_count++; if (self->lh_in_count >= self->lh_size) self->lh_in_count = 0; /* Gate the signal */ if (self->outputAmp == 0) self->data[i] = samp * self->gate; else self->data[i] = self->gate; } } static void Gate_postprocessing_ii(Gate *self) { POST_PROCESSING_II }; static void Gate_postprocessing_ai(Gate *self) { POST_PROCESSING_AI }; static void Gate_postprocessing_ia(Gate *self) { POST_PROCESSING_IA }; static void Gate_postprocessing_aa(Gate *self) { POST_PROCESSING_AA }; static void Gate_postprocessing_ireva(Gate *self) { POST_PROCESSING_IREVA }; static void Gate_postprocessing_areva(Gate *self) { POST_PROCESSING_AREVA }; static void Gate_postprocessing_revai(Gate *self) { POST_PROCESSING_REVAI }; static void Gate_postprocessing_revaa(Gate *self) { POST_PROCESSING_REVAA }; static void Gate_postprocessing_revareva(Gate *self) { POST_PROCESSING_REVAREVA }; static void Gate_setProcMode(Gate *self) { int procmode, muladdmode; procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Gate_filters_iii; break; case 1: self->proc_func_ptr = Gate_filters_aii; break; case 10: self->proc_func_ptr = Gate_filters_iai; break; case 11: self->proc_func_ptr = Gate_filters_aai; break; case 100: self->proc_func_ptr = Gate_filters_iia; break; case 101: self->proc_func_ptr = Gate_filters_aia; break; case 110: self->proc_func_ptr = Gate_filters_iaa; break; case 111: self->proc_func_ptr = Gate_filters_aaa; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Gate_postprocessing_ii; break; case 1: self->muladd_func_ptr = Gate_postprocessing_ai; break; case 2: self->muladd_func_ptr = Gate_postprocessing_revai; break; case 10: self->muladd_func_ptr = Gate_postprocessing_ia; break; case 11: self->muladd_func_ptr = Gate_postprocessing_aa; break; case 12: self->muladd_func_ptr = Gate_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Gate_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Gate_postprocessing_areva; break; case 22: self->muladd_func_ptr = Gate_postprocessing_revareva; break; } } static void Gate_compute_next_data_frame(Gate *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Gate_traverse(Gate *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->thresh); Py_VISIT(self->thresh_stream); Py_VISIT(self->risetime); Py_VISIT(self->risetime_stream); Py_VISIT(self->falltime); Py_VISIT(self->falltime_stream); return 0; } static int Gate_clear(Gate *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->thresh); Py_CLEAR(self->thresh_stream); Py_CLEAR(self->risetime); Py_CLEAR(self->risetime_stream); Py_CLEAR(self->falltime); Py_CLEAR(self->falltime_stream); return 0; } static void Gate_dealloc(Gate* self) { pyo_DEALLOC free(self->lh_buffer); Gate_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Gate_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *threshtmp=NULL, *risetimetmp=NULL, *falltimetmp=NULL, *multmp=NULL, *addtmp=NULL; PyObject *looktmp=NULL; Gate *self; self = (Gate *)type->tp_alloc(type, 0); self->thresh = PyFloat_FromDouble(-70.0); self->risetime = PyFloat_FromDouble(0.01); self->falltime = PyFloat_FromDouble(0.05); self->gate = self->lpfollow = 0.0; self->last_risetime = -1.0; self->last_falltime = -1.0; self->risefactor = self->fallfactor = 0.99; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; self->modebuffer[3] = 0; self->modebuffer[4] = 0; self->lh_delay = 0; self->lh_in_count = 0; self->outputAmp = 0; INIT_OBJECT_COMMON self->lpfactor = MYEXP(-1.0 / (self->sr / 20.0)); Stream_setFunctionPtr(self->stream, Gate_compute_next_data_frame); self->mode_func_ptr = Gate_setProcMode; static char *kwlist[] = {"input", "thresh", "risetime", "falltime", "lookahead", "outputAmp", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOiOO", kwlist, &inputtmp, &threshtmp, &risetimetmp, &falltimetmp, &looktmp, &self->outputAmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (threshtmp) { PyObject_CallMethod((PyObject *)self, "setThresh", "O", threshtmp); } if (risetimetmp) { PyObject_CallMethod((PyObject *)self, "setRiseTime", "O", risetimetmp); } if (falltimetmp) { PyObject_CallMethod((PyObject *)self, "setFallTime", "O", falltimetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod((PyObject *)self, "setLookAhead", "O", looktmp); self->lh_size = (long)(0.025 * self->sr + 0.5); self->lh_buffer = (MYFLT *)realloc(self->lh_buffer, (self->lh_size+1) * sizeof(MYFLT)); for (i=0; i<(self->lh_size+1); i++) { self->lh_buffer[i] = 0.; } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Gate_getServer(Gate* self) { GET_SERVER }; static PyObject * Gate_getStream(Gate* self) { GET_STREAM }; static PyObject * Gate_setMul(Gate *self, PyObject *arg) { SET_MUL }; static PyObject * Gate_setAdd(Gate *self, PyObject *arg) { SET_ADD }; static PyObject * Gate_setSub(Gate *self, PyObject *arg) { SET_SUB }; static PyObject * Gate_setDiv(Gate *self, PyObject *arg) { SET_DIV }; static PyObject * Gate_play(Gate *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Gate_out(Gate *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Gate_stop(Gate *self) { STOP }; static PyObject * Gate_multiply(Gate *self, PyObject *arg) { MULTIPLY }; static PyObject * Gate_inplace_multiply(Gate *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Gate_add(Gate *self, PyObject *arg) { ADD }; static PyObject * Gate_inplace_add(Gate *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Gate_sub(Gate *self, PyObject *arg) { SUB }; static PyObject * Gate_inplace_sub(Gate *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Gate_div(Gate *self, PyObject *arg) { DIV }; static PyObject * Gate_inplace_div(Gate *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Gate_setThresh(Gate *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->thresh); if (isNumber == 1) { self->thresh = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->thresh = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->thresh, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->thresh_stream); self->thresh_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Gate_setRiseTime(Gate *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->risetime); if (isNumber == 1) { self->risetime = PyNumber_Float(tmp); self->modebuffer[3] = 0; } else { self->risetime = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->risetime, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->risetime_stream); self->risetime_stream = (Stream *)streamtmp; self->modebuffer[3] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Gate_setFallTime(Gate *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->falltime); if (isNumber == 1) { self->falltime = PyNumber_Float(tmp); self->modebuffer[4] = 0; } else { self->falltime = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->falltime, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->falltime_stream); self->falltime_stream = (Stream *)streamtmp; self->modebuffer[4] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Gate_setLookAhead(Gate *self, PyObject *arg) { MYFLT tmp; ASSERT_ARG_NOT_NULL if (PyNumber_Check(arg)) { tmp = PyFloat_AsDouble(arg); if (tmp <= 25.0) self->lh_delay = (long)(tmp * 0.001 * self->sr); else printf("lookahead must be less than 25.0 ms.\n"); } Py_INCREF(Py_None); return Py_None; } static PyMemberDef Gate_members[] = { {"server", T_OBJECT_EX, offsetof(Gate, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Gate, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Gate, input), 0, "Input sound object."}, {"thresh", T_OBJECT_EX, offsetof(Gate, thresh), 0, "Threshold in dB."}, {"risetime", T_OBJECT_EX, offsetof(Gate, risetime), 0, "Risetime in second."}, {"falltime", T_OBJECT_EX, offsetof(Gate, falltime), 0, "Falltime in second."}, {"mul", T_OBJECT_EX, offsetof(Gate, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Gate, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Gate_methods[] = { {"getServer", (PyCFunction)Gate_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Gate_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Gate_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Gate_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Gate_stop, METH_NOARGS, "Stops computing."}, {"setThresh", (PyCFunction)Gate_setThresh, METH_O, "Sets the threshold in dB."}, {"setRiseTime", (PyCFunction)Gate_setRiseTime, METH_O, "Sets filter risetime in second."}, {"setFallTime", (PyCFunction)Gate_setFallTime, METH_O, "Sets filter falltime in second."}, {"setLookAhead", (PyCFunction)Gate_setLookAhead, METH_O, "Sets look ahead time in ms."}, {"setMul", (PyCFunction)Gate_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Gate_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Gate_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Gate_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Gate_as_number = { (binaryfunc)Gate_add, /*nb_add*/ (binaryfunc)Gate_sub, /*nb_subtract*/ (binaryfunc)Gate_multiply, /*nb_multiply*/ (binaryfunc)Gate_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Gate_inplace_add, /*inplace_add*/ (binaryfunc)Gate_inplace_sub, /*inplace_subtract*/ (binaryfunc)Gate_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Gate_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject GateType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Gate_base", /*tp_name*/ sizeof(Gate), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Gate_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Gate_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Gate objects. Noise gate dynamic processor.", /* tp_doc */ (traverseproc)Gate_traverse, /* tp_traverse */ (inquiry)Gate_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Gate_methods, /* tp_methods */ Gate_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Gate_new, /* tp_new */ }; /************/ /* Balance */ /************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *input2; Stream *input2_stream; PyObject *freq; Stream *freq_stream; int modebuffer[3]; // need at least 2 slots for mul & add MYFLT follow1; MYFLT follow2; MYFLT last_freq; MYFLT factor; } Balance; static void Balance_filters_i(Balance *self) { MYFLT absin, freq; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); freq = PyFloat_AS_DOUBLE(self->freq); if (freq < 0.1) freq = 0.1; if (freq != self->last_freq) { self->factor = MYEXP(-1.0 / (self->sr / freq)); self->last_freq = freq; } for (i=0; ibufsize; i++) { absin = in[i]; if (absin < 0.0) absin = -absin; self->follow1 = absin + self->factor * (self->follow1 - absin); if (self->follow1 < 0.001) self->follow1 = 0.001; absin = in2[i]; if (absin < 0.0) absin = -absin; self->follow2 = absin + self->factor * (self->follow2 - absin); self->data[i] = in[i] * (self->follow2 / self->follow1); } } static void Balance_filters_a(Balance *self) { MYFLT absin, freq; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *in2 = Stream_getData((Stream *)self->input2_stream); MYFLT *fr = Stream_getData((Stream *)self->freq_stream); for (i=0; ibufsize; i++) { freq = fr[i]; if (freq < 0.1) freq = 0.1; if (freq != self->last_freq) { self->factor = MYEXP(-1.0 / (self->sr / freq)); self->last_freq = freq; } absin = in[i]; if (absin < 0.0) absin = -absin; self->follow1 = absin + self->factor * (self->follow1 - absin); if (self->follow1 < 0.001) self->follow1 = 0.001; absin = in2[i]; if (absin < 0.0) absin = -absin; self->follow2 = absin + self->factor * (self->follow2 - absin); self->data[i] = in[i] * (self->follow2 / self->follow1); } } static void Balance_postprocessing_ii(Balance *self) { POST_PROCESSING_II }; static void Balance_postprocessing_ai(Balance *self) { POST_PROCESSING_AI }; static void Balance_postprocessing_ia(Balance *self) { POST_PROCESSING_IA }; static void Balance_postprocessing_aa(Balance *self) { POST_PROCESSING_AA }; static void Balance_postprocessing_ireva(Balance *self) { POST_PROCESSING_IREVA }; static void Balance_postprocessing_areva(Balance *self) { POST_PROCESSING_AREVA }; static void Balance_postprocessing_revai(Balance *self) { POST_PROCESSING_REVAI }; static void Balance_postprocessing_revaa(Balance *self) { POST_PROCESSING_REVAA }; static void Balance_postprocessing_revareva(Balance *self) { POST_PROCESSING_REVAREVA }; static void Balance_setProcMode(Balance *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Balance_filters_i; break; case 1: self->proc_func_ptr = Balance_filters_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Balance_postprocessing_ii; break; case 1: self->muladd_func_ptr = Balance_postprocessing_ai; break; case 2: self->muladd_func_ptr = Balance_postprocessing_revai; break; case 10: self->muladd_func_ptr = Balance_postprocessing_ia; break; case 11: self->muladd_func_ptr = Balance_postprocessing_aa; break; case 12: self->muladd_func_ptr = Balance_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Balance_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Balance_postprocessing_areva; break; case 22: self->muladd_func_ptr = Balance_postprocessing_revareva; break; } } static void Balance_compute_next_data_frame(Balance *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Balance_traverse(Balance *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->input2); Py_VISIT(self->input2_stream); Py_VISIT(self->freq); Py_VISIT(self->freq_stream); return 0; } static int Balance_clear(Balance *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->input2); Py_CLEAR(self->input2_stream); Py_CLEAR(self->freq); Py_CLEAR(self->freq_stream); return 0; } static void Balance_dealloc(Balance* self) { pyo_DEALLOC Balance_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Balance_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL; Balance *self; self = (Balance *)type->tp_alloc(type, 0); self->freq = PyFloat_FromDouble(10); self->follow1 = self->follow2 = 0.0; self->last_freq = -1.0; self->factor = 0.99; self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Balance_compute_next_data_frame); self->mode_func_ptr = Balance_setProcMode; static char *kwlist[] = {"input", "input2", "freq", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO", kwlist, &inputtmp, &input2tmp, &freqtmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM Py_XDECREF(self->input2); self->input2 = input2tmp; input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL); Py_INCREF(input2_streamtmp); Py_XDECREF(self->input2_stream); self->input2_stream = (Stream *)input2_streamtmp; if (freqtmp) { PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Balance_getServer(Balance* self) { GET_SERVER }; static PyObject * Balance_getStream(Balance* self) { GET_STREAM }; static PyObject * Balance_setMul(Balance *self, PyObject *arg) { SET_MUL }; static PyObject * Balance_setAdd(Balance *self, PyObject *arg) { SET_ADD }; static PyObject * Balance_setSub(Balance *self, PyObject *arg) { SET_SUB }; static PyObject * Balance_setDiv(Balance *self, PyObject *arg) { SET_DIV }; static PyObject * Balance_play(Balance *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Balance_out(Balance *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Balance_stop(Balance *self) { STOP }; static PyObject * Balance_multiply(Balance *self, PyObject *arg) { MULTIPLY }; static PyObject * Balance_inplace_multiply(Balance *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Balance_add(Balance *self, PyObject *arg) { ADD }; static PyObject * Balance_inplace_add(Balance *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Balance_sub(Balance *self, PyObject *arg) { SUB }; static PyObject * Balance_inplace_sub(Balance *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Balance_div(Balance *self, PyObject *arg) { DIV }; static PyObject * Balance_inplace_div(Balance *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Balance_setFreq(Balance *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->freq); if (isNumber == 1) { self->freq = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->freq = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->freq_stream); self->freq_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Balance_members[] = { {"server", T_OBJECT_EX, offsetof(Balance, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Balance, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Balance, input), 0, "Input sound object."}, {"input2", T_OBJECT_EX, offsetof(Balance, input2), 0, "Comparator input sound object."}, {"freq", T_OBJECT_EX, offsetof(Balance, freq), 0, "Cutoff frequency in cycle per second."}, {"mul", T_OBJECT_EX, offsetof(Balance, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Balance, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Balance_methods[] = { {"getServer", (PyCFunction)Balance_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Balance_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Balance_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Balance_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Balance_stop, METH_NOARGS, "Stops computing."}, {"setFreq", (PyCFunction)Balance_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."}, {"setMul", (PyCFunction)Balance_setMul, METH_O, "Sets oscillator mul factor."}, {"setAdd", (PyCFunction)Balance_setAdd, METH_O, "Sets oscillator add factor."}, {"setSub", (PyCFunction)Balance_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Balance_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Balance_as_number = { (binaryfunc)Balance_add, /*nb_add*/ (binaryfunc)Balance_sub, /*nb_subtract*/ (binaryfunc)Balance_multiply, /*nb_multiply*/ (binaryfunc)Balance_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Balance_inplace_add, /*inplace_add*/ (binaryfunc)Balance_inplace_sub, /*inplace_subtract*/ (binaryfunc)Balance_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Balance_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject BalanceType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Balance_base", /*tp_name*/ sizeof(Balance), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Balance_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Balance_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Balance objects. The rms power of a signal is adjusted to match that of a comparator signal.", /* tp_doc */ (traverseproc)Balance_traverse, /* tp_traverse */ (inquiry)Balance_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Balance_methods, /* tp_methods */ Balance_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Balance_new, /* tp_new */ }; pyo/src/objects/panmodule.c0000644000175000017500000034006312652732202015234 0ustar tiagotiago/************************************************************************** * Copyright 2009-2015 Olivier Belanger * * * * This file is part of pyo, a python module to help digital signal * * processing script creation. * * * * pyo is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * pyo is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with pyo. If not, see . * *************************************************************************/ #include #include "structmember.h" #include #include "pyomodule.h" #include "streammodule.h" #include "servermodule.h" #include "dummymodule.h" typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *pan; Stream *pan_stream; PyObject *spread; Stream *spread_stream; int chnls; int modebuffer[2]; MYFLT *buffer_streams; } Panner; static MYFLT P_clip(MYFLT p) { if (p < 0.0) return 0.0; else if (p > 1.0) return 1.0; else return p; } static void Panner_splitter_thru(Panner *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->buffer_streams[i] = in[i]; } } static void Panner_splitter_st_i(Panner *self) { MYFLT val, inval; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT pan = PyFloat_AS_DOUBLE(self->pan); pan = P_clip(pan); for (i=0; ibufsize; i++) { inval = in[i]; val = inval * MYSQRT(1.0 - pan); self->buffer_streams[i] = val; val = inval * MYSQRT(pan); self->buffer_streams[i+self->bufsize] = val; } } static void Panner_splitter_st_a(Panner *self) { MYFLT val, inval, panval; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *pan = Stream_getData((Stream *)self->pan_stream); for (i=0; ibufsize; i++) { inval = in[i]; panval = P_clip(pan[i]); val = inval * MYSQRT(1.0 - panval); self->buffer_streams[i] = val; val = inval * MYSQRT(panval); self->buffer_streams[i+self->bufsize] = val; } } static void Panner_splitter_ii(Panner *self) { MYFLT val, inval, phase, sprd; int j, i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT pan = PyFloat_AS_DOUBLE(self->pan); MYFLT spd = PyFloat_AS_DOUBLE(self->spread); pan = P_clip(pan); spd = P_clip(spd); sprd = 20.0 - (MYSQRT(spd) * 20.0) + 0.1; for (i=0; ibufsize; i++) { inval = in[i]; for (j=0; jchnls; j++) { phase = j / (MYFLT)self->chnls; val = inval * MYPOW(MYCOS((pan - phase) * TWOPI) * 0.5 + 0.5, sprd); self->buffer_streams[i+j*self->bufsize] = val; } } } static void Panner_splitter_ai(Panner *self) { MYFLT val, inval, phase, sprd; int j, i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *pan = Stream_getData((Stream *)self->pan_stream); MYFLT spd = PyFloat_AS_DOUBLE(self->spread); spd = P_clip(spd); sprd = 20.0 - (MYSQRT(spd) * 20.0) + 0.1; for (i=0; ibufsize; i++) { inval = in[i]; for (j=0; jchnls; j++) { phase = j / (MYFLT)self->chnls; val = inval * MYPOW(MYCOS((P_clip(pan[i]) - phase) * TWOPI) * 0.5 + 0.5, sprd); self->buffer_streams[i+j*self->bufsize] = val; } } } static void Panner_splitter_ia(Panner *self) { MYFLT val, inval, phase, spdval, sprd; int j, i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT pan = PyFloat_AS_DOUBLE(self->pan); MYFLT *spd = Stream_getData((Stream *)self->spread_stream); pan = P_clip(pan); for (i=0; ibufsize; i++) { inval = in[i]; spdval = P_clip(spd[i]); sprd = 20.0 - (MYSQRT(spdval) * 20.0) + 0.1; for (j=0; jchnls; j++) { phase = j / (MYFLT)self->chnls; val = inval * MYPOW(MYCOS((pan - phase) * TWOPI) * 0.5 + 0.5, sprd); self->buffer_streams[i+j*self->bufsize] = val; } } } static void Panner_splitter_aa(Panner *self) { MYFLT val, inval, phase, spdval, sprd; int j, i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *pan = Stream_getData((Stream *)self->pan_stream); MYFLT *spd = Stream_getData((Stream *)self->spread_stream); for (i=0; ibufsize; i++) { inval = in[i]; spdval = P_clip(spd[i]); sprd = 20.0 - (MYSQRT(spdval) * 20.0) + 0.1; for (j=0; jchnls; j++) { phase = j / (MYFLT)self->chnls; val = inval * MYPOW(MYCOS((P_clip(pan[i]) - phase) * TWOPI) * 0.5 + 0.5, sprd); self->buffer_streams[i+j*self->bufsize] = val; } } } MYFLT * Panner_getSamplesBuffer(Panner *self) { return (MYFLT *)self->buffer_streams; } static void Panner_setProcMode(Panner *self) { int procmode; procmode = self->modebuffer[0] + self->modebuffer[1] * 10; if (self->chnls > 2) { switch (procmode) { case 0: self->proc_func_ptr = Panner_splitter_ii; break; case 1: self->proc_func_ptr = Panner_splitter_ai; break; case 10: self->proc_func_ptr = Panner_splitter_ia; break; case 11: self->proc_func_ptr = Panner_splitter_aa; break; } } else if (self->chnls == 2) { switch (self->modebuffer[0]) { case 0: self->proc_func_ptr = Panner_splitter_st_i; break; case 1: self->proc_func_ptr = Panner_splitter_st_a; break; } } else if (self->chnls == 1) { self->proc_func_ptr = Panner_splitter_thru; } } static void Panner_compute_next_data_frame(Panner *self) { (*self->proc_func_ptr)(self); } static int Panner_traverse(Panner *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pan); Py_VISIT(self->pan_stream); Py_VISIT(self->spread); Py_VISIT(self->spread_stream); return 0; } static int Panner_clear(Panner *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pan); Py_CLEAR(self->pan_stream); Py_CLEAR(self->spread); Py_CLEAR(self->spread_stream); return 0; } static void Panner_dealloc(Panner* self) { pyo_DEALLOC free(self->buffer_streams); Panner_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Panner_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *pantmp=NULL, *spreadtmp=NULL; Panner *self; self = (Panner *)type->tp_alloc(type, 0); INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Panner_compute_next_data_frame); self->mode_func_ptr = Panner_setProcMode; self->pan = PyFloat_FromDouble(0.5); self->spread = PyFloat_FromDouble(0.5); self->chnls = 2; self->modebuffer[0] = 0; self->modebuffer[1] = 0; static char *kwlist[] = {"input", "outs", "pan", "spread", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &inputtmp, &self->chnls, &pantmp, &spreadtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (pantmp) { PyObject_CallMethod((PyObject *)self, "setPan", "O", pantmp); } if (spreadtmp) { PyObject_CallMethod((PyObject *)self, "setSpread", "O", spreadtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (self->chnls < 1) self->chnls = 1; self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->chnls * self->bufsize * sizeof(MYFLT)); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Panner_getServer(Panner* self) { GET_SERVER }; static PyObject * Panner_getStream(Panner* self) { GET_STREAM }; static PyObject * Panner_play(Panner *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Panner_stop(Panner *self) { STOP }; static PyObject * Panner_setPan(Panner *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pan); if (isNumber == 1) { self->pan = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->pan = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pan, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pan_stream); self->pan_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyObject * Panner_setSpread(Panner *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->spread); if (isNumber == 1) { self->spread = PyNumber_Float(tmp); self->modebuffer[1] = 0; } else { self->spread = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->spread, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->spread_stream); self->spread_stream = (Stream *)streamtmp; self->modebuffer[1] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Panner_members[] = { {"server", T_OBJECT_EX, offsetof(Panner, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Panner, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Panner, input), 0, "Input sound object."}, {"pan", T_OBJECT_EX, offsetof(Panner, pan), 0, "Pan object."}, {"spread", T_OBJECT_EX, offsetof(Panner, spread), 0, "Spread object."}, {NULL} /* Sentinel */ }; static PyMethodDef Panner_methods[] = { {"getServer", (PyCFunction)Panner_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Panner_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Panner_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Panner_stop, METH_NOARGS, "Stops computing."}, {"setPan", (PyCFunction)Panner_setPan, METH_O, "Sets panning value between 0 and 1."}, {"setSpread", (PyCFunction)Panner_setSpread, METH_O, "Sets spreading value between 0 and 1."}, {NULL} /* Sentinel */ }; PyTypeObject PannerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Panner_base", /*tp_name*/ sizeof(Panner), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Panner_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Panner main objects.", /* tp_doc */ (traverseproc)Panner_traverse, /* tp_traverse */ (inquiry)Panner_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Panner_methods, /* tp_methods */ Panner_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Panner_new, /* tp_new */ }; /************************************************************************************************/ /* Pan streamer object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD Panner *mainSplitter; int modebuffer[2]; int chnl; // panning order } Pan; static void Pan_postprocessing_ii(Pan *self) { POST_PROCESSING_II }; static void Pan_postprocessing_ai(Pan *self) { POST_PROCESSING_AI }; static void Pan_postprocessing_ia(Pan *self) { POST_PROCESSING_IA }; static void Pan_postprocessing_aa(Pan *self) { POST_PROCESSING_AA }; static void Pan_postprocessing_ireva(Pan *self) { POST_PROCESSING_IREVA }; static void Pan_postprocessing_areva(Pan *self) { POST_PROCESSING_AREVA }; static void Pan_postprocessing_revai(Pan *self) { POST_PROCESSING_REVAI }; static void Pan_postprocessing_revaa(Pan *self) { POST_PROCESSING_REVAA }; static void Pan_postprocessing_revareva(Pan *self) { POST_PROCESSING_REVAREVA }; static void Pan_setProcMode(Pan *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Pan_postprocessing_ii; break; case 1: self->muladd_func_ptr = Pan_postprocessing_ai; break; case 2: self->muladd_func_ptr = Pan_postprocessing_revai; break; case 10: self->muladd_func_ptr = Pan_postprocessing_ia; break; case 11: self->muladd_func_ptr = Pan_postprocessing_aa; break; case 12: self->muladd_func_ptr = Pan_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Pan_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Pan_postprocessing_areva; break; case 22: self->muladd_func_ptr = Pan_postprocessing_revareva; break; } } static void Pan_compute_next_data_frame(Pan *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = Panner_getSamplesBuffer((Panner *)self->mainSplitter); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int Pan_traverse(Pan *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainSplitter); return 0; } static int Pan_clear(Pan *self) { pyo_CLEAR Py_CLEAR(self->mainSplitter); return 0; } static void Pan_dealloc(Pan* self) { pyo_DEALLOC Pan_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Pan_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; Pan *self; self = (Pan *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Pan_compute_next_data_frame); self->mode_func_ptr = Pan_setProcMode; static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainSplitter); Py_INCREF(maintmp); self->mainSplitter = (Panner *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Pan_getServer(Pan* self) { GET_SERVER }; static PyObject * Pan_getStream(Pan* self) { GET_STREAM }; static PyObject * Pan_setMul(Pan *self, PyObject *arg) { SET_MUL }; static PyObject * Pan_setAdd(Pan *self, PyObject *arg) { SET_ADD }; static PyObject * Pan_setSub(Pan *self, PyObject *arg) { SET_SUB }; static PyObject * Pan_setDiv(Pan *self, PyObject *arg) { SET_DIV }; static PyObject * Pan_play(Pan *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Pan_out(Pan *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Pan_stop(Pan *self) { STOP }; static PyObject * Pan_multiply(Pan *self, PyObject *arg) { MULTIPLY }; static PyObject * Pan_inplace_multiply(Pan *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Pan_add(Pan *self, PyObject *arg) { ADD }; static PyObject * Pan_inplace_add(Pan *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Pan_sub(Pan *self, PyObject *arg) { SUB }; static PyObject * Pan_inplace_sub(Pan *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Pan_div(Pan *self, PyObject *arg) { DIV }; static PyObject * Pan_inplace_div(Pan *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Pan_members[] = { {"server", T_OBJECT_EX, offsetof(Pan, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Pan, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Pan, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Pan, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Pan_methods[] = { {"getServer", (PyCFunction)Pan_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Pan_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Pan_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Pan_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Pan_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Pan_setMul, METH_O, "Sets Pan mul factor."}, {"setAdd", (PyCFunction)Pan_setAdd, METH_O, "Sets Pan add factor."}, {"setSub", (PyCFunction)Pan_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Pan_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Pan_as_number = { (binaryfunc)Pan_add, /*nb_add*/ (binaryfunc)Pan_sub, /*nb_subtract*/ (binaryfunc)Pan_multiply, /*nb_multiply*/ (binaryfunc)Pan_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Pan_inplace_add, /*inplace_add*/ (binaryfunc)Pan_inplace_sub, /*inplace_subtract*/ (binaryfunc)Pan_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Pan_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject PanType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Pan_base", /*tp_name*/ sizeof(Pan), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Pan_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Pan_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Pan objects. Reads one band from a Panner.", /* tp_doc */ (traverseproc)Pan_traverse, /* tp_traverse */ (inquiry)Pan_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Pan_methods, /* tp_methods */ Pan_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Pan_new, /* tp_new */ }; /*********************/ /*** Simple panner ***/ /*********************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *pan; Stream *pan_stream; int chnls; int k1; int k2; int modebuffer[1]; MYFLT *buffer_streams; } SPanner; static void SPanner_splitter_thru(SPanner *self) { int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) { self->buffer_streams[i] = in[i]; } } static void SPanner_splitter_st_i(SPanner *self) { MYFLT val, inval; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT pan = PyFloat_AS_DOUBLE(self->pan); pan = P_clip(pan); for (i=0; ibufsize; i++) { inval = in[i]; val = inval * MYSQRT(1.0 - pan); self->buffer_streams[i] = val; val = inval * MYSQRT(pan); self->buffer_streams[i+self->bufsize] = val; } } static void SPanner_splitter_st_a(SPanner *self) { MYFLT val, inval, panval; int i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *pan = Stream_getData((Stream *)self->pan_stream); for (i=0; ibufsize; i++) { inval = in[i]; panval = P_clip(pan[i]); val = inval * MYSQRT(1.0 - panval); self->buffer_streams[i] = val; val = inval * MYSQRT(panval); self->buffer_streams[i+self->bufsize] = val; } } static void SPanner_splitter_i(SPanner *self) { MYFLT val, inval, min, pan1, pan2; int j, i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT pan = PyFloat_AS_DOUBLE(self->pan); MYFLT fchnls = (MYFLT)self->chnls; for (i=0; ibufsize; i++) { self->buffer_streams[i+self->k1] = 0.0; self->buffer_streams[i+self->k2] = 0.0; } min = 0; self->k1 = 0; self->k2 = self->bufsize; for (j=self->chnls; j>0; j--) { int j1 = j - 1; min = j1 / fchnls; if (pan > min) { self->k1 = j1 * self->bufsize; if (j == self->chnls) self->k2 = 0; else self->k2 = j * self->bufsize; break; } } pan = P_clip((pan - min) * self->chnls); pan1 = MYSQRT(1.0 - pan); pan2 = MYSQRT(pan); for (i=0; ibufsize; i++) { inval = in[i]; val = inval * pan1; self->buffer_streams[i+self->k1] = val; val = inval * pan2; self->buffer_streams[i+self->k2] = val; } } static void SPanner_splitter_a(SPanner *self) { MYFLT val, inval, min, pan; int i, j, j1, len; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *apan = Stream_getData((Stream *)self->pan_stream); MYFLT fchnls = (MYFLT)self->chnls; len = self->chnls * self->bufsize; for (i=0; ibuffer_streams[i] = 0.0; } for (i=0; ibufsize; i++) { pan = apan[i]; inval = in[i]; min = 0; self->k1 = 0; self->k2 = self->bufsize; for (j=self->chnls; j>0; j--) { j1 = j - 1; min = j1 / fchnls; if (pan > min) { self->k1 = j1 * self->bufsize; if (j == self->chnls) self->k2 = 0; else self->k2 = j * self->bufsize; break; } } pan = P_clip((pan - min) * self->chnls); val = inval * MYSQRT(1.0 - pan); self->buffer_streams[i+self->k1] = val; val = inval * MYSQRT(pan); self->buffer_streams[i+self->k2] = val; } } MYFLT * SPanner_getSamplesBuffer(SPanner *self) { return (MYFLT *)self->buffer_streams; } static void SPanner_setProcMode(SPanner *self) { int procmode; procmode = self->modebuffer[0]; if (self->chnls > 2) { switch (procmode) { case 0: self->proc_func_ptr = SPanner_splitter_i; break; case 1: self->proc_func_ptr = SPanner_splitter_a; break; } } else if (self->chnls == 2) { switch (self->modebuffer[0]) { case 0: self->proc_func_ptr = SPanner_splitter_st_i; break; case 1: self->proc_func_ptr = SPanner_splitter_st_a; break; } } else if (self->chnls == 1) { self->proc_func_ptr = SPanner_splitter_thru; } } static void SPanner_compute_next_data_frame(SPanner *self) { (*self->proc_func_ptr)(self); } static int SPanner_traverse(SPanner *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->pan); Py_VISIT(self->pan_stream); return 0; } static int SPanner_clear(SPanner *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->pan); Py_CLEAR(self->pan_stream); return 0; } static void SPanner_dealloc(SPanner* self) { pyo_DEALLOC free(self->buffer_streams); SPanner_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SPanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *pantmp=NULL; SPanner *self; self = (SPanner *)type->tp_alloc(type, 0); INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, SPanner_compute_next_data_frame); self->mode_func_ptr = SPanner_setProcMode; self->pan = PyFloat_FromDouble(0.5); self->chnls = 2; self->k1 = 0; self->k2 = self->bufsize; self->modebuffer[0] = 0; static char *kwlist[] = {"input", "outs", "pan", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iO", kwlist, &inputtmp, &self->chnls, &pantmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (pantmp) { PyObject_CallMethod((PyObject *)self, "setPan", "O", pantmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); if (self->chnls < 1) self->chnls = 1; self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->chnls * self->bufsize * sizeof(MYFLT)); (*self->mode_func_ptr)(self); int len = self->chnls*self->bufsize; for (i=0; ibuffer_streams[i] = 0.0; } return (PyObject *)self; } static PyObject * SPanner_getServer(SPanner* self) { GET_SERVER }; static PyObject * SPanner_getStream(SPanner* self) { GET_STREAM }; static PyObject * SPanner_play(SPanner *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SPanner_stop(SPanner *self) { STOP }; static PyObject * SPanner_setPan(SPanner *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->pan); if (isNumber == 1) { self->pan = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->pan = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->pan, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->pan_stream); self->pan_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef SPanner_members[] = { {"server", T_OBJECT_EX, offsetof(SPanner, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SPanner, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(SPanner, input), 0, "Input sound object."}, {"pan", T_OBJECT_EX, offsetof(SPanner, pan), 0, "Pan object."}, {NULL} /* Sentinel */ }; static PyMethodDef SPanner_methods[] = { {"getServer", (PyCFunction)SPanner_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SPanner_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SPanner_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)SPanner_stop, METH_NOARGS, "Stops computing."}, {"setPan", (PyCFunction)SPanner_setPan, METH_O, "Sets panning value between 0 and 1."}, {NULL} /* Sentinel */ }; PyTypeObject SPannerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SPanner_base", /*tp_name*/ sizeof(SPanner), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SPanner_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SPanner main objects. Simple equal power panner", /* tp_doc */ (traverseproc)SPanner_traverse, /* tp_traverse */ (inquiry)SPanner_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SPanner_methods, /* tp_methods */ SPanner_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SPanner_new, /* tp_new */ }; /************************************************************************************************/ /* SSPan streamer object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD SPanner *mainSplitter; int modebuffer[2]; int chnl; // panning order } SPan; static void SPan_postprocessing_ii(SPan *self) { POST_PROCESSING_II }; static void SPan_postprocessing_ai(SPan *self) { POST_PROCESSING_AI }; static void SPan_postprocessing_ia(SPan *self) { POST_PROCESSING_IA }; static void SPan_postprocessing_aa(SPan *self) { POST_PROCESSING_AA }; static void SPan_postprocessing_ireva(SPan *self) { POST_PROCESSING_IREVA }; static void SPan_postprocessing_areva(SPan *self) { POST_PROCESSING_AREVA }; static void SPan_postprocessing_revai(SPan *self) { POST_PROCESSING_REVAI }; static void SPan_postprocessing_revaa(SPan *self) { POST_PROCESSING_REVAA }; static void SPan_postprocessing_revareva(SPan *self) { POST_PROCESSING_REVAREVA }; static void SPan_setProcMode(SPan *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = SPan_postprocessing_ii; break; case 1: self->muladd_func_ptr = SPan_postprocessing_ai; break; case 2: self->muladd_func_ptr = SPan_postprocessing_revai; break; case 10: self->muladd_func_ptr = SPan_postprocessing_ia; break; case 11: self->muladd_func_ptr = SPan_postprocessing_aa; break; case 12: self->muladd_func_ptr = SPan_postprocessing_revaa; break; case 20: self->muladd_func_ptr = SPan_postprocessing_ireva; break; case 21: self->muladd_func_ptr = SPan_postprocessing_areva; break; case 22: self->muladd_func_ptr = SPan_postprocessing_revareva; break; } } static void SPan_compute_next_data_frame(SPan *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = SPanner_getSamplesBuffer((SPanner *)self->mainSplitter); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int SPan_traverse(SPan *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainSplitter); return 0; } static int SPan_clear(SPan *self) { pyo_CLEAR Py_CLEAR(self->mainSplitter); return 0; } static void SPan_dealloc(SPan* self) { pyo_DEALLOC SPan_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * SPan_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; SPan *self; self = (SPan *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, SPan_compute_next_data_frame); self->mode_func_ptr = SPan_setProcMode; static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainSplitter); Py_INCREF(maintmp); self->mainSplitter = (SPanner *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * SPan_getServer(SPan* self) { GET_SERVER }; static PyObject * SPan_getStream(SPan* self) { GET_STREAM }; static PyObject * SPan_setMul(SPan *self, PyObject *arg) { SET_MUL }; static PyObject * SPan_setAdd(SPan *self, PyObject *arg) { SET_ADD }; static PyObject * SPan_setSub(SPan *self, PyObject *arg) { SET_SUB }; static PyObject * SPan_setDiv(SPan *self, PyObject *arg) { SET_DIV }; static PyObject * SPan_play(SPan *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * SPan_out(SPan *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * SPan_stop(SPan *self) { STOP }; static PyObject * SPan_multiply(SPan *self, PyObject *arg) { MULTIPLY }; static PyObject * SPan_inplace_multiply(SPan *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * SPan_add(SPan *self, PyObject *arg) { ADD }; static PyObject * SPan_inplace_add(SPan *self, PyObject *arg) { INPLACE_ADD }; static PyObject * SPan_sub(SPan *self, PyObject *arg) { SUB }; static PyObject * SPan_inplace_sub(SPan *self, PyObject *arg) { INPLACE_SUB }; static PyObject * SPan_div(SPan *self, PyObject *arg) { DIV }; static PyObject * SPan_inplace_div(SPan *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef SPan_members[] = { {"server", T_OBJECT_EX, offsetof(SPan, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(SPan, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(SPan, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(SPan, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef SPan_methods[] = { {"getServer", (PyCFunction)SPan_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)SPan_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)SPan_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)SPan_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)SPan_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)SPan_setMul, METH_O, "Sets SPan mul factor."}, {"setAdd", (PyCFunction)SPan_setAdd, METH_O, "Sets SPan add factor."}, {"setSub", (PyCFunction)SPan_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)SPan_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods SPan_as_number = { (binaryfunc)SPan_add, /*nb_add*/ (binaryfunc)SPan_sub, /*nb_subtract*/ (binaryfunc)SPan_multiply, /*nb_multiply*/ (binaryfunc)SPan_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)SPan_inplace_add, /*inplace_add*/ (binaryfunc)SPan_inplace_sub, /*inplace_subtract*/ (binaryfunc)SPan_inplace_multiply, /*inplace_multiply*/ (binaryfunc)SPan_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SPanType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.SPan_base", /*tp_name*/ sizeof(SPan), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)SPan_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &SPan_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "SPan objects. Reads one band from a SPanner.", /* tp_doc */ (traverseproc)SPan_traverse, /* tp_traverse */ (inquiry)SPan_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ SPan_methods, /* tp_methods */ SPan_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ SPan_new, /* tp_new */ }; /*********************/ /***** Switcher ******/ /*********************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; PyObject *voice; Stream *voice_stream; int chnls; int k1; int k2; int modebuffer[1]; MYFLT *buffer_streams; } Switcher; static MYFLT Switcher_clip_voice(Switcher *self, MYFLT v) { int chnls = self->chnls - 1; if (v < 0.0) return 0.0; else if (v > chnls) return chnls; else return v; } static void Switcher_splitter_i(Switcher *self) { MYFLT val, inval, voice1, voice2; int j1, j, i; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT voice = Switcher_clip_voice(self, PyFloat_AS_DOUBLE(self->voice)); for (i=0; ibufsize; i++) { self->buffer_streams[i+self->k1] = 0.0; self->buffer_streams[i+self->k2] = 0.0; } j1 = (int)voice; j = j1 + 1; if (j1 >= (self->chnls-1)) { j1--; j--; } self->k1 = j1 * self->bufsize; self->k2 = j * self->bufsize; voice = P_clip(voice - j1); voice1 = MYSQRT(1.0 - voice); voice2 = MYSQRT(voice); for (i=0; ibufsize; i++) { inval = in[i]; val = inval * voice1; self->buffer_streams[i+self->k1] = val; val = inval * voice2; self->buffer_streams[i+self->k2] = val; } } static void Switcher_splitter_a(Switcher *self) { MYFLT inval, voice; int i, j, j1, len; MYFLT *in = Stream_getData((Stream *)self->input_stream); MYFLT *avoice = Stream_getData((Stream *)self->voice_stream); len = self->chnls * self->bufsize; for (i=0; ibuffer_streams[i] = 0.0; } for (i=0; ibufsize; i++) { voice = Switcher_clip_voice(self, avoice[i]); inval = in[i]; j1 = (int)voice; j = j1 + 1; if (j1 >= (self->chnls-1)) { j1--; j--; } self->k1 = j1 * self->bufsize; self->k2 = j * self->bufsize; voice = P_clip(voice - j1); self->buffer_streams[i+self->k1] = inval * MYSQRT(1.0 - voice); self->buffer_streams[i+self->k2] = inval * MYSQRT(voice); } } MYFLT * Switcher_getSamplesBuffer(Switcher *self) { return (MYFLT *)self->buffer_streams; } static void Switcher_setProcMode(Switcher *self) { switch (self->modebuffer[0]) { case 0: self->proc_func_ptr = Switcher_splitter_i; break; case 1: self->proc_func_ptr = Switcher_splitter_a; break; } } static void Switcher_compute_next_data_frame(Switcher *self) { (*self->proc_func_ptr)(self); } static int Switcher_traverse(Switcher *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->voice); Py_VISIT(self->voice_stream); return 0; } static int Switcher_clear(Switcher *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->voice); Py_CLEAR(self->voice_stream); return 0; } static void Switcher_dealloc(Switcher* self) { pyo_DEALLOC free(self->buffer_streams); Switcher_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Switcher_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *voicetmp=NULL; Switcher *self; self = (Switcher *)type->tp_alloc(type, 0); INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Switcher_compute_next_data_frame); self->mode_func_ptr = Switcher_setProcMode; self->voice = PyFloat_FromDouble(0.0); self->chnls = 2; self->k1 = 0; self->k2 = self->bufsize; self->modebuffer[0] = 0; static char *kwlist[] = {"input", "outs", "voice", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iO", kwlist, &inputtmp, &self->chnls, &voicetmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (voicetmp) { PyObject_CallMethod((PyObject *)self, "setVoice", "O", voicetmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->chnls * self->bufsize * sizeof(MYFLT)); (*self->mode_func_ptr)(self); int len = self->chnls*self->bufsize; for (i=0; ibuffer_streams[i] = 0.0; } return (PyObject *)self; } static PyObject * Switcher_getServer(Switcher* self) { GET_SERVER }; static PyObject * Switcher_getStream(Switcher* self) { GET_STREAM }; static PyObject * Switcher_play(Switcher *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Switcher_stop(Switcher *self) { STOP }; static PyObject * Switcher_setVoice(Switcher *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->voice); if (isNumber == 1) { self->voice = PyNumber_Float(tmp); self->modebuffer[0] = 0; } else { self->voice = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->voice, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->voice_stream); self->voice_stream = (Stream *)streamtmp; self->modebuffer[0] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Switcher_members[] = { {"server", T_OBJECT_EX, offsetof(Switcher, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Switcher, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(Switcher, input), 0, "Input sound object."}, {"voice", T_OBJECT_EX, offsetof(Switcher, voice), 0, "voice object."}, {NULL} /* Sentinel */ }; static PyMethodDef Switcher_methods[] = { {"getServer", (PyCFunction)Switcher_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Switcher_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Switcher_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Switcher_stop, METH_NOARGS, "Stops computing."}, {"setVoice", (PyCFunction)Switcher_setVoice, METH_O, "Sets voice value between 0 and outs-1."}, {NULL} /* Sentinel */ }; PyTypeObject SwitcherType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Switcher_base", /*tp_name*/ sizeof(Switcher), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Switcher_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Switcher main objects. Simple equal power voicener", /* tp_doc */ (traverseproc)Switcher_traverse, /* tp_traverse */ (inquiry)Switcher_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Switcher_methods, /* tp_methods */ Switcher_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Switcher_new, /* tp_new */ }; /************************************************************************************************/ /* SSwitch streamer object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD Switcher *mainSplitter; int modebuffer[2]; int chnl; // switch order } Switch; static void Switch_postprocessing_ii(Switch *self) { POST_PROCESSING_II }; static void Switch_postprocessing_ai(Switch *self) { POST_PROCESSING_AI }; static void Switch_postprocessing_ia(Switch *self) { POST_PROCESSING_IA }; static void Switch_postprocessing_aa(Switch *self) { POST_PROCESSING_AA }; static void Switch_postprocessing_ireva(Switch *self) { POST_PROCESSING_IREVA }; static void Switch_postprocessing_areva(Switch *self) { POST_PROCESSING_AREVA }; static void Switch_postprocessing_revai(Switch *self) { POST_PROCESSING_REVAI }; static void Switch_postprocessing_revaa(Switch *self) { POST_PROCESSING_REVAA }; static void Switch_postprocessing_revareva(Switch *self) { POST_PROCESSING_REVAREVA }; static void Switch_setProcMode(Switch *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = Switch_postprocessing_ii; break; case 1: self->muladd_func_ptr = Switch_postprocessing_ai; break; case 2: self->muladd_func_ptr = Switch_postprocessing_revai; break; case 10: self->muladd_func_ptr = Switch_postprocessing_ia; break; case 11: self->muladd_func_ptr = Switch_postprocessing_aa; break; case 12: self->muladd_func_ptr = Switch_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Switch_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Switch_postprocessing_areva; break; case 22: self->muladd_func_ptr = Switch_postprocessing_revareva; break; } } static void Switch_compute_next_data_frame(Switch *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = Switcher_getSamplesBuffer((Switcher *)self->mainSplitter); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int Switch_traverse(Switch *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainSplitter); return 0; } static int Switch_clear(Switch *self) { pyo_CLEAR Py_CLEAR(self->mainSplitter); return 0; } static void Switch_dealloc(Switch* self) { pyo_DEALLOC Switch_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Switch_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; Switch *self; self = (Switch *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Switch_compute_next_data_frame); self->mode_func_ptr = Switch_setProcMode; static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainSplitter); Py_INCREF(maintmp); self->mainSplitter = (Switcher *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Switch_getServer(Switch* self) { GET_SERVER }; static PyObject * Switch_getStream(Switch* self) { GET_STREAM }; static PyObject * Switch_setMul(Switch *self, PyObject *arg) { SET_MUL }; static PyObject * Switch_setAdd(Switch *self, PyObject *arg) { SET_ADD }; static PyObject * Switch_setSub(Switch *self, PyObject *arg) { SET_SUB }; static PyObject * Switch_setDiv(Switch *self, PyObject *arg) { SET_DIV }; static PyObject * Switch_play(Switch *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Switch_out(Switch *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Switch_stop(Switch *self) { STOP }; static PyObject * Switch_multiply(Switch *self, PyObject *arg) { MULTIPLY }; static PyObject * Switch_inplace_multiply(Switch *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Switch_add(Switch *self, PyObject *arg) { ADD }; static PyObject * Switch_inplace_add(Switch *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Switch_sub(Switch *self, PyObject *arg) { SUB }; static PyObject * Switch_inplace_sub(Switch *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Switch_div(Switch *self, PyObject *arg) { DIV }; static PyObject * Switch_inplace_div(Switch *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef Switch_members[] = { {"server", T_OBJECT_EX, offsetof(Switch, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Switch, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(Switch, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Switch, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Switch_methods[] = { {"getServer", (PyCFunction)Switch_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Switch_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Switch_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Switch_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Switch_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)Switch_setMul, METH_O, "Sets Switch mul factor."}, {"setAdd", (PyCFunction)Switch_setAdd, METH_O, "Sets Switch add factor."}, {"setSub", (PyCFunction)Switch_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Switch_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Switch_as_number = { (binaryfunc)Switch_add, /*nb_add*/ (binaryfunc)Switch_sub, /*nb_subtract*/ (binaryfunc)Switch_multiply, /*nb_multiply*/ (binaryfunc)Switch_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Switch_inplace_add, /*inplace_add*/ (binaryfunc)Switch_inplace_sub, /*inplace_subtract*/ (binaryfunc)Switch_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Switch_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SwitchType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Switch_base", /*tp_name*/ sizeof(Switch), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Switch_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Switch_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Switch objects. Reads one band from a Switchner.", /* tp_doc */ (traverseproc)Switch_traverse, /* tp_traverse */ (inquiry)Switch_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Switch_methods, /* tp_methods */ Switch_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Switch_new, /* tp_new */ }; /****************/ /**** VoiceManager *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *input; Stream *input_stream; Stream **trigger_streams; int maxVoices; int *voices; int modebuffer[2]; // need at least 2 slots for mul & add } VoiceManager; static void VoiceManager_generate(VoiceManager *self) { int j, i; MYFLT *in = Stream_getData((Stream *)self->input_stream); for (i=0; ibufsize; i++) self->data[i] = -1.0; if (self->maxVoices > 0) { for (i=0; ibufsize; i++) { for (j=0; jmaxVoices; j++) { if (Stream_getData(self->trigger_streams[j])[i] == 1.0) self->voices[j] = 0; } if (in[i] == 1.0) { for (j=0; jmaxVoices; j++) { if (self->voices[j] == 0) { self->data[i] = (MYFLT)j; self->voices[j] = 1; break; } } } } } } static void VoiceManager_postprocessing_ii(VoiceManager *self) { POST_PROCESSING_II }; static void VoiceManager_postprocessing_ai(VoiceManager *self) { POST_PROCESSING_AI }; static void VoiceManager_postprocessing_ia(VoiceManager *self) { POST_PROCESSING_IA }; static void VoiceManager_postprocessing_aa(VoiceManager *self) { POST_PROCESSING_AA }; static void VoiceManager_postprocessing_ireva(VoiceManager *self) { POST_PROCESSING_IREVA }; static void VoiceManager_postprocessing_areva(VoiceManager *self) { POST_PROCESSING_AREVA }; static void VoiceManager_postprocessing_revai(VoiceManager *self) { POST_PROCESSING_REVAI }; static void VoiceManager_postprocessing_revaa(VoiceManager *self) { POST_PROCESSING_REVAA }; static void VoiceManager_postprocessing_revareva(VoiceManager *self) { POST_PROCESSING_REVAREVA }; static void VoiceManager_setProcMode(VoiceManager *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; self->proc_func_ptr = VoiceManager_generate; switch (muladdmode) { case 0: self->muladd_func_ptr = VoiceManager_postprocessing_ii; break; case 1: self->muladd_func_ptr = VoiceManager_postprocessing_ai; break; case 2: self->muladd_func_ptr = VoiceManager_postprocessing_revai; break; case 10: self->muladd_func_ptr = VoiceManager_postprocessing_ia; break; case 11: self->muladd_func_ptr = VoiceManager_postprocessing_aa; break; case 12: self->muladd_func_ptr = VoiceManager_postprocessing_revaa; break; case 20: self->muladd_func_ptr = VoiceManager_postprocessing_ireva; break; case 21: self->muladd_func_ptr = VoiceManager_postprocessing_areva; break; case 22: self->muladd_func_ptr = VoiceManager_postprocessing_revareva; break; } } static void VoiceManager_compute_next_data_frame(VoiceManager *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int VoiceManager_traverse(VoiceManager *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->input); Py_VISIT(self->input_stream); Py_VISIT(self->trigger_streams); return 0; } static int VoiceManager_clear(VoiceManager *self) { pyo_CLEAR Py_CLEAR(self->input); Py_CLEAR(self->input_stream); Py_CLEAR(self->trigger_streams); return 0; } static void VoiceManager_dealloc(VoiceManager* self) { pyo_DEALLOC if (self->voices != NULL) free(self->voices); VoiceManager_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * VoiceManager_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputtmp, *input_streamtmp, *triggerstmp=NULL, *multmp=NULL, *addtmp=NULL; VoiceManager *self; self = (VoiceManager *)type->tp_alloc(type, 0); self->voices = NULL; self->maxVoices = 0; self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, VoiceManager_compute_next_data_frame); self->mode_func_ptr = VoiceManager_setProcMode; static char *kwlist[] = {"input", "triggers", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &triggerstmp, &multmp, &addtmp)) Py_RETURN_NONE; INIT_INPUT_STREAM if (triggerstmp && triggerstmp != Py_None) { PyObject_CallMethod((PyObject *)self, "setTriggers", "O", triggerstmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * VoiceManager_getServer(VoiceManager* self) { GET_SERVER }; static PyObject * VoiceManager_getStream(VoiceManager* self) { GET_STREAM }; static PyObject * VoiceManager_setMul(VoiceManager *self, PyObject *arg) { SET_MUL }; static PyObject * VoiceManager_setAdd(VoiceManager *self, PyObject *arg) { SET_ADD }; static PyObject * VoiceManager_setSub(VoiceManager *self, PyObject *arg) { SET_SUB }; static PyObject * VoiceManager_setDiv(VoiceManager *self, PyObject *arg) { SET_DIV }; static PyObject * VoiceManager_play(VoiceManager *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * VoiceManager_stop(VoiceManager *self) { STOP }; static PyObject * VoiceManager_multiply(VoiceManager *self, PyObject *arg) { MULTIPLY }; static PyObject * VoiceManager_inplace_multiply(VoiceManager *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * VoiceManager_add(VoiceManager *self, PyObject *arg) { ADD }; static PyObject * VoiceManager_inplace_add(VoiceManager *self, PyObject *arg) { INPLACE_ADD }; static PyObject * VoiceManager_sub(VoiceManager *self, PyObject *arg) { SUB }; static PyObject * VoiceManager_inplace_sub(VoiceManager *self, PyObject *arg) { INPLACE_SUB }; static PyObject * VoiceManager_div(VoiceManager *self, PyObject *arg) { DIV }; static PyObject * VoiceManager_inplace_div(VoiceManager *self, PyObject *arg) { INPLACE_DIV }; static PyObject * VoiceManager_setTriggers(VoiceManager *self, PyObject *arg) { int i; if (! PyList_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The triggers attribute must be a list."); Py_INCREF(Py_None); return Py_None; } self->maxVoices = PyList_Size(arg); self->trigger_streams = (Stream **)realloc(self->trigger_streams, self->maxVoices * sizeof(Stream *)); self->voices = (int *)realloc(self->voices, self->maxVoices * sizeof(int)); for (i=0; imaxVoices; i++) { self->trigger_streams[i] = (Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(arg, i), "_getStream", NULL); self->voices[i] = 0; } Py_RETURN_NONE; } static PyMemberDef VoiceManager_members[] = { {"server", T_OBJECT_EX, offsetof(VoiceManager, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(VoiceManager, stream), 0, "Stream object."}, {"input", T_OBJECT_EX, offsetof(VoiceManager, input), 0, "Input sound object."}, {"trigger_streams", T_OBJECT_EX, offsetof(VoiceManager, trigger_streams), 0, "Array of trigger streams."}, {"mul", T_OBJECT_EX, offsetof(VoiceManager, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(VoiceManager, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef VoiceManager_methods[] = { {"getServer", (PyCFunction)VoiceManager_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)VoiceManager_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)VoiceManager_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)VoiceManager_stop, METH_NOARGS, "Stops computing."}, {"setTriggers", (PyCFunction)VoiceManager_setTriggers, METH_O, "Sets list of trigger streams."}, {"setMul", (PyCFunction)VoiceManager_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)VoiceManager_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)VoiceManager_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)VoiceManager_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods VoiceManager_as_number = { (binaryfunc)VoiceManager_add, /*nb_add*/ (binaryfunc)VoiceManager_sub, /*nb_subtract*/ (binaryfunc)VoiceManager_multiply, /*nb_multiply*/ (binaryfunc)VoiceManager_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)VoiceManager_inplace_add, /*inplace_add*/ (binaryfunc)VoiceManager_inplace_sub, /*inplace_subtract*/ (binaryfunc)VoiceManager_inplace_multiply, /*inplace_multiply*/ (binaryfunc)VoiceManager_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject VoiceManagerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.VoiceManager_base", /*tp_name*/ sizeof(VoiceManager), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)VoiceManager_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &VoiceManager_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "VoiceManager objects. Return the first free voices when receiving a trigger signal.", /* tp_doc */ (traverseproc)VoiceManager_traverse, /* tp_traverse */ (inquiry)VoiceManager_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ VoiceManager_methods, /* tp_methods */ VoiceManager_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ VoiceManager_new, /* tp_new */ }; /****************/ /**** Mixer *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *inputs; PyObject *gains; PyObject *lastGains; PyObject *currentGains; PyObject *stepVals; PyObject *timeCounts; int num_outs; MYFLT time; long timeStep; MYFLT *buffer_streams; } Mixer; static void Mixer_generate(Mixer *self) { int num, k, j, i, tmpCount; MYFLT amp, lastAmp, currentAmp, tmpStepVal; PyObject *keys; PyObject *key; PyObject *list_of_gains, *list_of_last_gains, *list_of_current_gains, *list_of_step_vals, *list_of_time_counts; for (i=0; i<(self->num_outs * self->bufsize); i++) { self->buffer_streams[i] = 0.0; } keys = PyDict_Keys(self->inputs); num = PyList_Size(keys); for (j=0; jinputs, key), "_getStream", NULL)); list_of_gains = PyDict_GetItem(self->gains, key); list_of_last_gains = PyDict_GetItem(self->lastGains, key); list_of_current_gains = PyDict_GetItem(self->currentGains, key); list_of_step_vals = PyDict_GetItem(self->stepVals, key); list_of_time_counts = PyDict_GetItem(self->timeCounts, key); for (k=0; knum_outs; k++) { amp = (MYFLT)PyFloat_AS_DOUBLE(PyList_GetItem(list_of_gains, k)); lastAmp = (MYFLT)PyFloat_AS_DOUBLE(PyList_GetItem(list_of_last_gains, k)); currentAmp = (MYFLT)PyFloat_AS_DOUBLE(PyList_GetItem(list_of_current_gains, k)); tmpStepVal = (MYFLT)PyFloat_AS_DOUBLE(PyList_GetItem(list_of_step_vals, k)); tmpCount = (int)PyLong_AsLong(PyList_GetItem(list_of_time_counts, k)); if (amp != lastAmp) { tmpCount = 0; tmpStepVal = (amp - currentAmp) / self->timeStep; PyList_SetItem(list_of_last_gains, k, PyFloat_FromDouble(amp)); } for (i=0; ibufsize; i++) { if (tmpCount == (self->timeStep - 1)) { currentAmp = amp; tmpCount++; } else if (tmpCount < self->timeStep) { currentAmp += tmpStepVal; tmpCount++; } self->buffer_streams[self->bufsize * k + i] += st[i] * currentAmp; } PyList_SetItem(list_of_current_gains, k, PyFloat_FromDouble(currentAmp)); PyList_SetItem(list_of_step_vals, k, PyFloat_FromDouble(tmpStepVal)); PyList_SetItem(list_of_time_counts, k, PyLong_FromLong(tmpCount)); } } Py_XDECREF(keys); } MYFLT * Mixer_getSamplesBuffer(Mixer *self) { return (MYFLT *)self->buffer_streams; } static void Mixer_setProcMode(Mixer *self) { self->proc_func_ptr = Mixer_generate; } static void Mixer_compute_next_data_frame(Mixer *self) { (*self->proc_func_ptr)(self); } static int Mixer_traverse(Mixer *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->inputs); Py_VISIT(self->gains); Py_VISIT(self->lastGains); Py_VISIT(self->currentGains); Py_VISIT(self->stepVals); Py_VISIT(self->timeCounts); return 0; } static int Mixer_clear(Mixer *self) { pyo_CLEAR Py_CLEAR(self->inputs); Py_CLEAR(self->gains); Py_CLEAR(self->lastGains); Py_CLEAR(self->currentGains); Py_CLEAR(self->stepVals); Py_CLEAR(self->timeCounts); return 0; } static void Mixer_dealloc(Mixer* self) { pyo_DEALLOC free(self->buffer_streams); Mixer_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Mixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *timetmp=NULL; Mixer *self; self = (Mixer *)type->tp_alloc(type, 0); self->inputs = PyDict_New(); self->gains = PyDict_New(); self->lastGains = PyDict_New(); self->currentGains = PyDict_New(); self->stepVals = PyDict_New(); self->timeCounts = PyDict_New(); self->num_outs = 2; self->time = 0.025; self->timeStep = (long)(self->time * self->sr); INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Mixer_compute_next_data_frame); self->mode_func_ptr = Mixer_setProcMode; static char *kwlist[] = {"outs", "time", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iO", kwlist, &self->num_outs, &timetmp)) Py_RETURN_NONE; if (timetmp) { PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->num_outs * self->bufsize * sizeof(MYFLT)); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Mixer_getServer(Mixer* self) { GET_SERVER }; static PyObject * Mixer_getStream(Mixer* self) { GET_STREAM }; static PyObject * Mixer_play(Mixer *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Mixer_stop(Mixer *self) { STOP }; static PyObject * Mixer_setTime(Mixer *self, PyObject *arg) { int i, j, num; PyObject *tmp, *keys, *key, *list_of_time_counts; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); if (isNumber == 1) { self->time = PyFloat_AsDouble(tmp); self->timeStep = (long)(self->time * self->sr); keys = PyDict_Keys(self->inputs); num = PyList_Size(keys); if (num != 0) { for (j=0; jtimeCounts, key); for (i=0; inum_outs; i++) { PyList_SET_ITEM(list_of_time_counts, i, PyLong_FromLong(self->timeStep-1)); } } } } Py_INCREF(Py_None); return Py_None; } static PyObject * Mixer_addInput(Mixer *self, PyObject *args, PyObject *kwds) { int i; PyObject *tmp; PyObject *initGains; PyObject *initLastGains; PyObject *initCurrentGains; PyObject *initStepVals; PyObject *initTimeCounts; PyObject *voice; static char *kwlist[] = {"voice", "input", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &voice, &tmp)) { Py_INCREF(Py_None); return Py_None; } PyDict_SetItem(self->inputs, voice, tmp); initGains = PyList_New(self->num_outs); initLastGains = PyList_New(self->num_outs); initCurrentGains = PyList_New(self->num_outs); initStepVals = PyList_New(self->num_outs); initTimeCounts = PyList_New(self->num_outs); for (i=0; inum_outs; i++) { PyList_SET_ITEM(initGains, i, PyFloat_FromDouble(0.0)); PyList_SET_ITEM(initLastGains, i, PyFloat_FromDouble(0.0)); PyList_SET_ITEM(initCurrentGains, i, PyFloat_FromDouble(0.0)); PyList_SET_ITEM(initStepVals, i, PyFloat_FromDouble(0.0)); PyList_SET_ITEM(initTimeCounts, i, PyInt_FromLong(0)); } PyDict_SetItem(self->gains, voice, initGains); PyDict_SetItem(self->lastGains, voice, initLastGains); PyDict_SetItem(self->currentGains, voice, initCurrentGains); PyDict_SetItem(self->stepVals, voice, initStepVals); PyDict_SetItem(self->timeCounts, voice, initTimeCounts); Py_INCREF(Py_None); return Py_None; } static PyObject * Mixer_delInput(Mixer *self, PyObject *arg) { int ret; PyObject *key = arg; ret = PyDict_DelItem(self->inputs, key); if (ret == 0) { PyDict_DelItem(self->gains, key); PyDict_DelItem(self->lastGains, key); PyDict_DelItem(self->currentGains, key); PyDict_DelItem(self->stepVals, key); PyDict_DelItem(self->timeCounts, key); } else { Py_INCREF(Py_None); return Py_None; } Py_INCREF(Py_None); return Py_None; } static PyObject * Mixer_setAmp(Mixer *self, PyObject *args, PyObject *kwds) { int tmpout; PyObject *tmpin, *amp; static char *kwlist[] = {"vin", "vout", "amp", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "OiO", kwlist, &tmpin, &tmpout, &)) { Py_INCREF(Py_None); return Py_None; } if (! PyNumber_Check(amp)) { printf("Amplitude must be a number!n"); Py_INCREF(Py_None); return Py_None; } Py_INCREF(amp); PyList_SET_ITEM(PyDict_GetItem(self->gains, tmpin), tmpout, PyNumber_Float(amp)); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Mixer_members[] = { {"server", T_OBJECT_EX, offsetof(Mixer, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Mixer, stream), 0, "Stream object."}, {"inputs", T_OBJECT_EX, offsetof(Mixer, inputs), 0, "Dictionary of input streams."}, {"gains", T_OBJECT_EX, offsetof(Mixer, gains), 0, "Dictionary of list of amplitudes."}, {NULL} /* Sentinel */ }; static PyMethodDef Mixer_methods[] = { {"getServer", (PyCFunction)Mixer_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Mixer_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Mixer_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"stop", (PyCFunction)Mixer_stop, METH_NOARGS, "Stops computing."}, {"setTime", (PyCFunction)Mixer_setTime, METH_O, "Sets ramp time in seconds."}, {"addInput", (PyCFunction)Mixer_addInput, METH_VARARGS|METH_KEYWORDS, "Adds an input to the mixer."}, {"delInput", (PyCFunction)Mixer_delInput, METH_O, "Removes an input from the mixer."}, {"setAmp", (PyCFunction)Mixer_setAmp, METH_VARARGS|METH_KEYWORDS, "Sets the amplitude of a specific input toward a specific output."}, {NULL} /* Sentinel */ }; PyTypeObject MixerType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Mixer_base", /*tp_name*/ sizeof(Mixer), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Mixer_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Mixer objects. Mixes multiple inputs toward multiple outputs.", /* tp_doc */ (traverseproc)Mixer_traverse, /* tp_traverse */ (inquiry)Mixer_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Mixer_methods, /* tp_methods */ Mixer_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Mixer_new, /* tp_new */ }; /************************************************************************************************/ /* MixerVoice streamer object */ /************************************************************************************************/ typedef struct { pyo_audio_HEAD Mixer *mainMixer; int modebuffer[2]; int chnl; // voice order } MixerVoice; static void MixerVoice_postprocessing_ii(MixerVoice *self) { POST_PROCESSING_II }; static void MixerVoice_postprocessing_ai(MixerVoice *self) { POST_PROCESSING_AI }; static void MixerVoice_postprocessing_ia(MixerVoice *self) { POST_PROCESSING_IA }; static void MixerVoice_postprocessing_aa(MixerVoice *self) { POST_PROCESSING_AA }; static void MixerVoice_postprocessing_ireva(MixerVoice *self) { POST_PROCESSING_IREVA }; static void MixerVoice_postprocessing_areva(MixerVoice *self) { POST_PROCESSING_AREVA }; static void MixerVoice_postprocessing_revai(MixerVoice *self) { POST_PROCESSING_REVAI }; static void MixerVoice_postprocessing_revaa(MixerVoice *self) { POST_PROCESSING_REVAA }; static void MixerVoice_postprocessing_revareva(MixerVoice *self) { POST_PROCESSING_REVAREVA }; static void MixerVoice_setProcMode(MixerVoice *self) { int muladdmode; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (muladdmode) { case 0: self->muladd_func_ptr = MixerVoice_postprocessing_ii; break; case 1: self->muladd_func_ptr = MixerVoice_postprocessing_ai; break; case 2: self->muladd_func_ptr = MixerVoice_postprocessing_revai; break; case 10: self->muladd_func_ptr = MixerVoice_postprocessing_ia; break; case 11: self->muladd_func_ptr = MixerVoice_postprocessing_aa; break; case 12: self->muladd_func_ptr = MixerVoice_postprocessing_revaa; break; case 20: self->muladd_func_ptr = MixerVoice_postprocessing_ireva; break; case 21: self->muladd_func_ptr = MixerVoice_postprocessing_areva; break; case 22: self->muladd_func_ptr = MixerVoice_postprocessing_revareva; break; } } static void MixerVoice_compute_next_data_frame(MixerVoice *self) { int i; MYFLT *tmp; int offset = self->chnl * self->bufsize; tmp = Mixer_getSamplesBuffer((Mixer *)self->mainMixer); for (i=0; ibufsize; i++) { self->data[i] = tmp[i + offset]; } (*self->muladd_func_ptr)(self); } static int MixerVoice_traverse(MixerVoice *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->mainMixer); return 0; } static int MixerVoice_clear(MixerVoice *self) { pyo_CLEAR Py_CLEAR(self->mainMixer); return 0; } static void MixerVoice_dealloc(MixerVoice* self) { pyo_DEALLOC MixerVoice_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * MixerVoice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL; MixerVoice *self; self = (MixerVoice *)type->tp_alloc(type, 0); self->modebuffer[0] = 0; self->modebuffer[1] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, MixerVoice_compute_next_data_frame); self->mode_func_ptr = MixerVoice_setProcMode; static char *kwlist[] = {"mainMixer", "chnl", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp)) Py_RETURN_NONE; Py_XDECREF(self->mainMixer); Py_INCREF(maintmp); self->mainMixer = (Mixer *)maintmp; if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); return (PyObject *)self; } static PyObject * MixerVoice_getServer(MixerVoice* self) { GET_SERVER }; static PyObject * MixerVoice_getStream(MixerVoice* self) { GET_STREAM }; static PyObject * MixerVoice_setMul(MixerVoice *self, PyObject *arg) { SET_MUL }; static PyObject * MixerVoice_setAdd(MixerVoice *self, PyObject *arg) { SET_ADD }; static PyObject * MixerVoice_setSub(MixerVoice *self, PyObject *arg) { SET_SUB }; static PyObject * MixerVoice_setDiv(MixerVoice *self, PyObject *arg) { SET_DIV }; static PyObject * MixerVoice_play(MixerVoice *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * MixerVoice_out(MixerVoice *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * MixerVoice_stop(MixerVoice *self) { STOP }; static PyObject * MixerVoice_multiply(MixerVoice *self, PyObject *arg) { MULTIPLY }; static PyObject * MixerVoice_inplace_multiply(MixerVoice *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * MixerVoice_add(MixerVoice *self, PyObject *arg) { ADD }; static PyObject * MixerVoice_inplace_add(MixerVoice *self, PyObject *arg) { INPLACE_ADD }; static PyObject * MixerVoice_sub(MixerVoice *self, PyObject *arg) { SUB }; static PyObject * MixerVoice_inplace_sub(MixerVoice *self, PyObject *arg) { INPLACE_SUB }; static PyObject * MixerVoice_div(MixerVoice *self, PyObject *arg) { DIV }; static PyObject * MixerVoice_inplace_div(MixerVoice *self, PyObject *arg) { INPLACE_DIV }; static PyMemberDef MixerVoice_members[] = { {"server", T_OBJECT_EX, offsetof(MixerVoice, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(MixerVoice, stream), 0, "Stream object."}, {"mul", T_OBJECT_EX, offsetof(MixerVoice, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(MixerVoice, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef MixerVoice_methods[] = { {"getServer", (PyCFunction)MixerVoice_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)MixerVoice_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)MixerVoice_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)MixerVoice_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)MixerVoice_stop, METH_NOARGS, "Stops computing."}, {"setMul", (PyCFunction)MixerVoice_setMul, METH_O, "Sets MixerVoice mul factor."}, {"setAdd", (PyCFunction)MixerVoice_setAdd, METH_O, "Sets MixerVoice add factor."}, {"setSub", (PyCFunction)MixerVoice_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)MixerVoice_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods MixerVoice_as_number = { (binaryfunc)MixerVoice_add, /*nb_add*/ (binaryfunc)MixerVoice_sub, /*nb_subtract*/ (binaryfunc)MixerVoice_multiply, /*nb_multiply*/ (binaryfunc)MixerVoice_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)MixerVoice_inplace_add, /*inplace_add*/ (binaryfunc)MixerVoice_inplace_sub, /*inplace_subtract*/ (binaryfunc)MixerVoice_inplace_multiply, /*inplace_multiply*/ (binaryfunc)MixerVoice_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject MixerVoiceType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.MixerVoice_base", /*tp_name*/ sizeof(MixerVoice), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)MixerVoice_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &MixerVoice_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "MixerVoice objects. Reads one band from a Mixer.", /* tp_doc */ (traverseproc)MixerVoice_traverse, /* tp_traverse */ (inquiry)MixerVoice_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ MixerVoice_methods, /* tp_methods */ MixerVoice_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ MixerVoice_new, /* tp_new */ }; /****************/ /**** Selector *****/ /****************/ typedef struct { pyo_audio_HEAD PyObject *inputs; PyObject *voice; Stream *voice_stream; int chSize; int modebuffer[3]; // need at least 2 slots for mul & add } Selector; static MYFLT Selector_clip_voice(Selector *self, MYFLT v) { int chSize = self->chSize - 1; if (v < 0.0) return 0.0; else if (v > chSize) return chSize; else return v; } static void Selector_generate_i(Selector *self) { int j1, j, i; MYFLT voice1, voice2; MYFLT voice = Selector_clip_voice(self, PyFloat_AS_DOUBLE(self->voice)); j1 = (int)voice; j = j1 + 1; if (j1 >= (self->chSize-1)) { j1--; j--; } MYFLT *st1 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, j1), "_getStream", NULL)); MYFLT *st2 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, j), "_getStream", NULL)); voice = P_clip(voice - j1); voice1 = MYSQRT(1.0 - voice); voice2 = MYSQRT(voice); for (i=0; ibufsize; i++) { self->data[i] = st1[i] * voice1 + st2[i] * voice2; } } static void Selector_generate_a(Selector *self) { int old_j1, old_j, j1, j, i; MYFLT voice; MYFLT *st1, *st2; MYFLT *vc = Stream_getData((Stream *)self->voice_stream); old_j1 = 0; old_j = 1; st1 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, old_j1), "_getStream", NULL)); st2 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, old_j), "_getStream", NULL)); for (i=0; ibufsize; i++) { voice = Selector_clip_voice(self, vc[i]); j1 = (int)voice; j = j1 + 1; if (j1 >= (self->chSize-1)) { j1--; j--; } if (j1 != old_j1) { st1 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, j1), "_getStream", NULL)); old_j1 = j1; } if (j != old_j) { st2 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, j), "_getStream", NULL)); old_j = j; } voice = P_clip(voice - j1); self->data[i] = st1[i] * MYSQRT(1.0 - voice) + st2[i] * MYSQRT(voice); } } static void Selector_postprocessing_ii(Selector *self) { POST_PROCESSING_II }; static void Selector_postprocessing_ai(Selector *self) { POST_PROCESSING_AI }; static void Selector_postprocessing_ia(Selector *self) { POST_PROCESSING_IA }; static void Selector_postprocessing_aa(Selector *self) { POST_PROCESSING_AA }; static void Selector_postprocessing_ireva(Selector *self) { POST_PROCESSING_IREVA }; static void Selector_postprocessing_areva(Selector *self) { POST_PROCESSING_AREVA }; static void Selector_postprocessing_revai(Selector *self) { POST_PROCESSING_REVAI }; static void Selector_postprocessing_revaa(Selector *self) { POST_PROCESSING_REVAA }; static void Selector_postprocessing_revareva(Selector *self) { POST_PROCESSING_REVAREVA }; static void Selector_setProcMode(Selector *self) { int procmode, muladdmode; procmode = self->modebuffer[2]; muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10; switch (procmode) { case 0: self->proc_func_ptr = Selector_generate_i; break; case 1: self->proc_func_ptr = Selector_generate_a; break; } switch (muladdmode) { case 0: self->muladd_func_ptr = Selector_postprocessing_ii; break; case 1: self->muladd_func_ptr = Selector_postprocessing_ai; break; case 2: self->muladd_func_ptr = Selector_postprocessing_revai; break; case 10: self->muladd_func_ptr = Selector_postprocessing_ia; break; case 11: self->muladd_func_ptr = Selector_postprocessing_aa; break; case 12: self->muladd_func_ptr = Selector_postprocessing_revaa; break; case 20: self->muladd_func_ptr = Selector_postprocessing_ireva; break; case 21: self->muladd_func_ptr = Selector_postprocessing_areva; break; case 22: self->muladd_func_ptr = Selector_postprocessing_revareva; break; } } static void Selector_compute_next_data_frame(Selector *self) { (*self->proc_func_ptr)(self); (*self->muladd_func_ptr)(self); } static int Selector_traverse(Selector *self, visitproc visit, void *arg) { pyo_VISIT Py_VISIT(self->inputs); Py_VISIT(self->voice); Py_VISIT(self->voice_stream); return 0; } static int Selector_clear(Selector *self) { pyo_CLEAR Py_CLEAR(self->inputs); Py_CLEAR(self->voice); Py_CLEAR(self->voice_stream); return 0; } static void Selector_dealloc(Selector* self) { pyo_DEALLOC Selector_clear(self); self->ob_type->tp_free((PyObject*)self); } static PyObject * Selector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { int i; PyObject *inputstmp=NULL, *voicetmp=NULL, *multmp=NULL, *addtmp=NULL; Selector *self; self = (Selector *)type->tp_alloc(type, 0); self->voice = PyFloat_FromDouble(0.); self->modebuffer[0] = 0; self->modebuffer[1] = 0; self->modebuffer[2] = 0; INIT_OBJECT_COMMON Stream_setFunctionPtr(self->stream, Selector_compute_next_data_frame); self->mode_func_ptr = Selector_setProcMode; static char *kwlist[] = {"inputs", "voice", "mul", "add", NULL}; if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputstmp, &voicetmp, &multmp, &addtmp)) Py_RETURN_NONE; if (inputstmp) { PyObject_CallMethod((PyObject *)self, "setInputs", "O", inputstmp); } if (voicetmp) { PyObject_CallMethod((PyObject *)self, "setVoice", "O", voicetmp); } if (multmp) { PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp); } if (addtmp) { PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp); } PyObject_CallMethod(self->server, "addStream", "O", self->stream); (*self->mode_func_ptr)(self); return (PyObject *)self; } static PyObject * Selector_getServer(Selector* self) { GET_SERVER }; static PyObject * Selector_getStream(Selector* self) { GET_STREAM }; static PyObject * Selector_setMul(Selector *self, PyObject *arg) { SET_MUL }; static PyObject * Selector_setAdd(Selector *self, PyObject *arg) { SET_ADD }; static PyObject * Selector_setSub(Selector *self, PyObject *arg) { SET_SUB }; static PyObject * Selector_setDiv(Selector *self, PyObject *arg) { SET_DIV }; static PyObject * Selector_play(Selector *self, PyObject *args, PyObject *kwds) { PLAY }; static PyObject * Selector_out(Selector *self, PyObject *args, PyObject *kwds) { OUT }; static PyObject * Selector_stop(Selector *self) { STOP }; static PyObject * Selector_multiply(Selector *self, PyObject *arg) { MULTIPLY }; static PyObject * Selector_inplace_multiply(Selector *self, PyObject *arg) { INPLACE_MULTIPLY }; static PyObject * Selector_add(Selector *self, PyObject *arg) { ADD }; static PyObject * Selector_inplace_add(Selector *self, PyObject *arg) { INPLACE_ADD }; static PyObject * Selector_sub(Selector *self, PyObject *arg) { SUB }; static PyObject * Selector_inplace_sub(Selector *self, PyObject *arg) { INPLACE_SUB }; static PyObject * Selector_div(Selector *self, PyObject *arg) { DIV }; static PyObject * Selector_inplace_div(Selector *self, PyObject *arg) { INPLACE_DIV }; static PyObject * Selector_setInputs(Selector *self, PyObject *arg) { PyObject *tmp; if (! PyList_Check(arg)) { PyErr_SetString(PyExc_TypeError, "The inputs attribute must be a list."); Py_INCREF(Py_None); return Py_None; } tmp = arg; self->chSize = PyList_Size(tmp); Py_INCREF(tmp); Py_XDECREF(self->inputs); self->inputs = tmp; Py_INCREF(Py_None); return Py_None; } static PyObject * Selector_setVoice(Selector *self, PyObject *arg) { PyObject *tmp, *streamtmp; ASSERT_ARG_NOT_NULL int isNumber = PyNumber_Check(arg); tmp = arg; Py_INCREF(tmp); Py_DECREF(self->voice); if (isNumber == 1) { self->voice = PyNumber_Float(tmp); self->modebuffer[2] = 0; } else { self->voice = tmp; streamtmp = PyObject_CallMethod((PyObject *)self->voice, "_getStream", NULL); Py_INCREF(streamtmp); Py_XDECREF(self->voice_stream); self->voice_stream = (Stream *)streamtmp; self->modebuffer[2] = 1; } (*self->mode_func_ptr)(self); Py_INCREF(Py_None); return Py_None; } static PyMemberDef Selector_members[] = { {"server", T_OBJECT_EX, offsetof(Selector, server), 0, "Pyo server."}, {"stream", T_OBJECT_EX, offsetof(Selector, stream), 0, "Stream object."}, {"inputs", T_OBJECT_EX, offsetof(Selector, inputs), 0, "List of input streams."}, {"voice", T_OBJECT_EX, offsetof(Selector, voice), 0, "Voice position pointer."}, {"mul", T_OBJECT_EX, offsetof(Selector, mul), 0, "Mul factor."}, {"add", T_OBJECT_EX, offsetof(Selector, add), 0, "Add factor."}, {NULL} /* Sentinel */ }; static PyMethodDef Selector_methods[] = { {"getServer", (PyCFunction)Selector_getServer, METH_NOARGS, "Returns server object."}, {"_getStream", (PyCFunction)Selector_getStream, METH_NOARGS, "Returns stream object."}, {"play", (PyCFunction)Selector_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."}, {"out", (PyCFunction)Selector_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."}, {"stop", (PyCFunction)Selector_stop, METH_NOARGS, "Stops computing."}, {"setInputs", (PyCFunction)Selector_setInputs, METH_O, "Sets list of input streams."}, {"setVoice", (PyCFunction)Selector_setVoice, METH_O, "Sets voice position pointer."}, {"setMul", (PyCFunction)Selector_setMul, METH_O, "Sets mul factor."}, {"setAdd", (PyCFunction)Selector_setAdd, METH_O, "Sets add factor."}, {"setSub", (PyCFunction)Selector_setSub, METH_O, "Sets inverse add factor."}, {"setDiv", (PyCFunction)Selector_setDiv, METH_O, "Sets inverse mul factor."}, {NULL} /* Sentinel */ }; static PyNumberMethods Selector_as_number = { (binaryfunc)Selector_add, /*nb_add*/ (binaryfunc)Selector_sub, /*nb_subtract*/ (binaryfunc)Selector_multiply, /*nb_multiply*/ (binaryfunc)Selector_div, /*nb_divide*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ 0, /*nb_power*/ 0, /*nb_neg*/ 0, /*nb_pos*/ 0, /*(unaryfunc)array_abs,*/ 0, /*nb_nonzero*/ 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ 0, /*nb_and*/ 0, /*nb_xor*/ 0, /*nb_or*/ 0, /*nb_coerce*/ 0, /*nb_int*/ 0, /*nb_long*/ 0, /*nb_float*/ 0, /*nb_oct*/ 0, /*nb_hex*/ (binaryfunc)Selector_inplace_add, /*inplace_add*/ (binaryfunc)Selector_inplace_sub, /*inplace_subtract*/ (binaryfunc)Selector_inplace_multiply, /*inplace_multiply*/ (binaryfunc)Selector_inplace_div, /*inplace_divide*/ 0, /*inplace_remainder*/ 0, /*inplace_power*/ 0, /*inplace_lshift*/ 0, /*inplace_rshift*/ 0, /*inplace_and*/ 0, /*inplace_xor*/ 0, /*inplace_or*/ 0, /*nb_floor_divide*/ 0, /*nb_true_divide*/ 0, /*nb_inplace_floor_divide*/ 0, /*nb_inplace_true_divide*/ 0, /* nb_index */ }; PyTypeObject SelectorType = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "_pyo.Selector_base", /*tp_name*/ sizeof(Selector), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)Selector_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ &Selector_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/ "Selector objects. Audio interpolation between multiple inputs.", /* tp_doc */ (traverseproc)Selector_traverse, /* tp_traverse */ (inquiry)Selector_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ Selector_methods, /* tp_methods */ Selector_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ Selector_new, /* tp_new */ }; pyo/setup.py0000644000175000017500000001256112652732202012375 0ustar tiagotiago# -*- coding: utf-8 -*- """ Copyright 2009-2015 Olivier Belanger This file is part of pyo, a python module to help digital signal processing script creation. pyo is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. pyo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyo. If not, see . """ from distutils.core import setup, Extension import os, sys, getopt import time pyo_version = "0.7.8" build_osx_with_jack_support = False compile_externals = False macros = [] extension_names = ['_pyo'] main_modules = ['pyo'] extra_macros_per_extension = [[]] if '--only-double' in sys.argv: sys.argv.remove('--only-double') extension_names = ['_pyo64'] main_modules = ['pyo64'] extra_macros_per_extension = [[('USE_DOUBLE',None)]] if '--use-double' in sys.argv and not '--only-double' in sys.argv: sys.argv.remove('--use-double') extension_names.append('_pyo64') main_modules.append('pyo64') extra_macros_per_extension.append([('USE_DOUBLE',None)]) if '--use-jack' in sys.argv: sys.argv.remove('--use-jack') if sys.platform == "darwin": build_osx_with_jack_support = True macros.append(('USE_JACK',None)) if '--use-coreaudio' in sys.argv: sys.argv.remove('--use-coreaudio') macros.append(('USE_COREAUDIO',None)) if '--no-messages' in sys.argv: sys.argv.remove('--no-messages') macros.append(('NO_MESSAGES',None)) if '--compile-externals' in sys.argv: compile_externals = True sys.argv.remove('--compile-externals') macros.append(('COMPILE_EXTERNALS',None)) if sys.platform == "darwin": macros.append(('_OSX_', None)) path = 'src/engine/' files = ['pyomodule.c', 'listenermodule.c', 'servermodule.c', 'pvstreammodule.c', 'streammodule.c', 'dummymodule.c', 'mixmodule.c', 'inputfadermodule.c', 'interpolation.c', 'fft.c', "wind.c"] source_files = [path + f for f in files] path = 'src/objects/' files = ['exprmodule.c', 'utilsmodule.c', 'granulatormodule.c', 'tablemodule.c', 'wgverbmodule.c', 'oscilmodule.c', 'randommodule.c', 'oscmodule.c','analysismodule.c', 'sfplayermodule.c', 'oscbankmodule.c', 'lfomodule.c', 'matrixmodule.c', 'filtremodule.c', 'noisemodule.c', 'distomodule.c', 'inputmodule.c', 'fadermodule.c', 'midimodule.c', 'delaymodule.c','recordmodule.c', 'metromodule.c', 'trigmodule.c', 'patternmodule.c', 'bandsplitmodule.c', 'hilbertmodule.c', 'panmodule.c', 'selectmodule.c', 'compressmodule.c', 'freeverbmodule.c', 'phasevocmodule.c', 'fftmodule.c', 'convolvemodule.c', 'arithmeticmodule.c', 'sigmodule.c', 'matrixprocessmodule.c', 'harmonizermodule.c', 'chorusmodule.c'] if compile_externals: source_files = source_files + ["externals/externalmodule.c"] + [path + f for f in files] else: source_files = source_files + [path + f for f in files] # Platform-specific build settings for the pyo extension(s). if sys.platform == "win32": include_dirs = ['C:\portaudio\include', 'C:\Program Files (x86)\Mega-Nerd\libsndfile\include', 'C:\portmidi\pm_common', 'C:\liblo', 'C:\pthreads\include', 'include', 'C:\portmidi\porttime'] library_dirs = ['C:\portaudio', 'C:/Program Files (x86)/Mega-Nerd/libsndfile/bin', 'C:\portmidi', 'C:\liblo', 'C:\pthreads\lib'] libraries = ['portaudio', 'portmidi', 'porttime', 'libsndfile-1', 'lo', 'pthreadVC2'] else: tsrt = time.strftime('"%d %b %Y %H:%M:%S"', time.localtime()) macros.append(('TIMESTAMP', tsrt)) include_dirs = ['include', '/usr/local/include'] if sys.platform == "darwin": include_dirs.append('/opt/local/include') library_dirs = [] libraries = ['portaudio', 'portmidi', 'sndfile', 'lo'] if build_osx_with_jack_support: libraries.append('jack') extensions = [] for extension_name, extra_macros in zip(extension_names, extra_macros_per_extension): extensions.append(Extension(extension_name, source_files, include_dirs=include_dirs, library_dirs=library_dirs, libraries=libraries, extra_compile_args=['-Wno-strict-prototypes', '-O3', '-Wno-strict-aliasing'], define_macros=macros + extra_macros)) if compile_externals: include_dirs.append('externals') os.system('cp externals/external.py pyolib') setup( name = "pyo", author = "Olivier Belanger", author_email = "belangeo@gmail.com", version = pyo_version, description = "Python dsp module.", long_description = "pyo is a Python module written in C to help digital signal processing script creation.", url = "https://github.com/belangeo/pyo", license = "LGPLv3+", packages = ['pyolib', 'pyolib.snds'], py_modules = main_modules, package_data = {'pyolib.snds': [f for f in os.listdir('pyolib/snds') if f.endswith('aif') or f.endswith('wav')]}, ext_modules = extensions ) if compile_externals: os.system('rm pyolib/external.py') pyo/utils/0000755000175000017500000000000012652732202012016 5ustar tiagotiagopyo/utils/E-PyoIconDoc.ico0000644000175000017500000011256512652732202014714 0ustar tiagotiago oOV00 h&O  (-v U h PNG  IHDR\rf IDATx]|T> 4`A,!*F]tPAE)"Xx>Sԧ<˳R(6,(術@ |s$7fwd7g~̽ssL!5*@@d|m}kJPr(P(__]%e@%P%P?J@ @ˀJK@ |}u@)@)*Pd /-eU!ߎB%+ w%䛅 Ύڥ&7+jII9d5>EFFF/H%,&j4{ed* ,ƠI@[oenذ4@PʉO>}ѣ4vXk ͚@A@Ob !QQh#F޼y.P=/RT|9s*WչsS;wLb2x=qDBbbbr d!'#oƜm۶}vÇgV^=)akvӧӞ={322"~遽{~SI?'3SyqGo:bccxS[l۩SZjr8I)J&vZZjtyEr-W_}<ҥk 'U(cO)$@2,M6S۠A{h.DQd/"|hq[ɓ'ԬY3Z`~K/Eg@q}D<(X0;5 nY+@AaSH;Cg mʔ)c2֮]?d6m^fҎ߿ JBRpL1`k_<(_BdnpQ69ǎf@%KNoyv曟c-!6I37!E" Z^a˵U$ Ɏ`M p9-Z_lɶm>1ܙ@~$,W;4$`>Vs7o|<$H[o'@"k'9ӆ4I&m%~69?W\y믟 v"4] T; (A9Nʹ?SL3)!IJU@I;zK kQ@KO(HK.cHiw3 48qbW&& &i( C(Pp #6mzLO:CfTMw{ I:H$`#H*ݸq2k֬9ѺuZb $ͫ O`PIͧTp#u. ɨӷUpކ8tX/u5Bl.SM +BB\vfL/Ӊ z SJyZ OzpE8FY||(Jo^_!IG|ᇱ ,NKy9PjqPj_<ѻpr Q*GWaxO, 8\*P*_: k `l$;d㍙:81X*I@ pAoF_~>HСCy @|}\ 8@6vzW3ydܫjEJJ9 !And\- zQ*%`#HE$/glӈe J (J8ΗvE/BV&|ǎ¢ 5XjH@ tbԾ3 `g}6{I?hSAqAP(P(/n'~O`ծ]x0^LfiJ%ԅY"w}G qxzm 8Ll{C#knyXb}i1<(H@ E% ')99oUwFRa]7{ZɎ`ps ]vF|W[=bX P@(F 1g|ހ袋UeR q~~#_C_â/B-{gEͫ#ׯA#{QÆ #8[9{%`HtU`Q S,(.y欳">x V `ވ˕_q8_K.ޤ0#XGΙ3.\&y.|IsW(i_ďHF@st}_ljxbbӣjL5jT S&RuIT@PCKtynb[F A)`|YY PGp~lۡKiu-tf 4""xRWo b9}:ی޽&C5mL;+]P !dddt6| `J<wʔ)CUxaΝ4~jѲ ͛7h(Ry#j̞$I:A|fn ;5kފyߦ'=Ph`,n#yA>l-:dśч 6QϞW(h!5OI@1BCf۶N7\߉EYկ 6)J k[1d$%dr_4L,JGѥ^EO?=˼7"< L@=TJg mW^}ZnKAlv܀c/9>ꣀ~*UD wCzNx$PO e.G?TlGKÆtVh[VY xRyD``@ON kO?]c( M FPDFFMͯ/m&j|AeH"͂ɕ)qjӦ+=6 3C&1"N%PGp>wڛ6~Us'؇Ɗ [Œd"yD\r4i}yƱ| 'p$Bb%@?$ i߻"yI#l8=O5h2_k :KKD0JA(ӏM0?ëJG15 a=ďCqH@ Bt\}eWQZ C_B^ d(555y4`p83~ H@ B?֬tm~L~8?Odu1^{}(C edZ}J@ UY1 57߬<-6Z//|=ʚ@Mzo<9܎A Lqd")`[qJBZgq(O~ڸ{3{PG}*n|YjSGM?+VJ6Vť Hݽf|2ɔ8(0oe2s(} t@*n ={:*VhVZ16E;2N%N'Cq*/jLA,}g7܋\c&qsqim '&&lGl x?kK|!GOtA;~Z`;3Wҳ#nk*Ҝ9Я< 舀oVA^((|(hWRBb9%[Dvckyɖtq-ݵ<Tȑ`bsnt|/LPD`;^a;_F^˵'\?qsw/#x%KK?YaF3 9?Q!3 }⣺s̐_ɹ0n'۟˵xS~/OumLRBǏ+vw_C0BځJ3Q⫢ 0ğ?ʗο "ByJ]p+`_/6^@ep/H'hλ(A; (x'' L0_-OLS'rV6]v[&b۟ۯw7q`8>saIC0L$|/9Tg9`۸^Ea;ݽ \k{zr ~m! 2?ouC <<Ņ 2GZq2EO)-m1^F83{ӬEg7Ojע6o}{wRO}y~Nߚv.^ߞ^{8?:|䨳S `52#bہ Ax0b %>%-|{1'q?оCFK)SP@];7y:x t9~l#ODƞq&@(<]Xw=) { gRŶ7] 9@UFu_6Dp<qHfiXj~4͜1_reiQԡ}cY0iii&fIDpF3;zlZL (!\-c5 !RkݖrEͷ,G8?B휖ďb~/b9jDLO GgO{?K IDATʕ*-?Sמ7QΝFpGgwp"^Y3s 1]$"p_v~ h < ?k~xwgДIxt' a&91)#zRkX.%vc\ %zձ.D a%~w6Җg|:IM=9|(g'UP.=o4=# ӎSU{&#yp?-[V, 6::uW ^5WRqVUVSxYTpS#?'b/iX s0ζ)6)= sm~&TG~بL҈a7?⚿7C0~*_  2X8; (xCѕ*V4gEQ0(,^x&Br/Ŗ0b͟ w;; م;F|XUX_3| 7 F`B k_8sOZ5aBy(/ 5 Co@3wmW|~g4 M'#/b.9٧Ukx Y>)իW _`pyO^dvw{C{{sxiKcwic:t:vC=q?uYc˯A3O#G>OYl"hj"ġ` (,\\]p͛0BvZ\ ]}%,^?ب3hߵkxUWM  ~۶nt*}fZ/jrۚ~_niMMP),# ͚]p n5tɈÆ1꯰ÓqܚU+q:0D|6^Ӧ?ŀ#Ա[_ѭ3M2O?KӯH~_.gqUA|?[X߰{i,+Q[@@<@w%A)W,aT[f },? 4R\Mr0PC0=Spv&u=x'%dBʕ+G]tǍ`n\";Fv73x.&$tG5XN~FGoY?[hc-cdiH[s5Ϊ{ Z꿷d{U}B(0zu2e˛0޶WM@?9BRzk<?8u孻-3mn :0,W3m~Q-#)dc_Zj]w]kBSyGÏP,ܧRK.<`57 T\&?F -C}u7!c_ Kesou~ <`mwea?ߏglFFGp/PB pͧdef9QUk(\?w7$ 6^S,lYƫKv=YGwwF35lpno?;ը?d9FԦ F4O#m[ (͙PI!ʛ]4:|Z"@Xz7&{t3M4ƌd^_} QQ?|X^Qlk{ཬP0BG2 p:- D@A)\ldtIi?p=5-on?д\2~1y߈wT: _Y4ΧL80X S27?%??XS{n,AG]g~]v4zm#+yz ׵f0M?D=p*Q77@H2RẆԃk)IcoaթM_kqfa/Ĥ];P̨ȟI@P]f!A㵠;uQG~ x_xMNEw:q%ڱG_fL xۢoٲd._z{<#hB`/ƚjSO΄q3o (-:+j?jiO/nj6j {- Z)4FW<@ f_FO0weҙܰ[n} [hsߺ6m~ %;vѣAĜ9Lkw_;w%ї4?QA/i' ^ @Ȭ2<3ޗo1v:s_N-zЎ;V?45}>i|<-Fj?6~FM^yoL5h J 2d5?OMEtGp#L:j0$A7a;~m;1V4@m&~󯿨ktimNukצ@X ڊ=>>kcԤIc㏘#-ѾJ\C5%Tl`f 5wkHJ @J |2]4095Ysg 9yS3m  4!KlxTRyݐlŠ<) /$;@2c@q` a= g|iZ5k}zptFKÝp7gqO !HϚG؉c7:\G5j /%0_ R0SMk1 5rqѱ'j~N,]A?0oC]{y9Ļӯ۶Q5Xn*y$%q`f5ohUX\dOz@\FM!4 Yp.]5@=XT$ȤyN-~~jp4]G8d vcwI_6/ټ:r,oj14{ԷOOCXT _y5`P< ާk̼CZQ5}ɫ@FM@67Oqwh(c.^mwL58&@$b~C<)iР@Z{(pxPy ׀ 7Z };p3s"nԨP h}8ߏ5ΝL5@`Ran7+1 TK3"M. v?#JZй$qOS7PnBh#<,*0+@Էw@fA~Y{-?686>@4{wmos*$gI@5 ! װ?]=f,5X[odx@.mJte5k+.}^9&?Tx o䓏ۇ9C}Jؿp F-B:7G=/^BW0p0.LaGM~]7ox*W߮7x?C.*L9$fC )`'0:d^\UJAQkժEͥ_;!iDo~|=^48d^s w_ 2K}y ڝxQch$<0 %i$ JjFPAy+3yk!IA?E͊y׮]ǝ{1Fȝnx޸x}9 4/:1l~)${Q_gj抿ik8$}- 55$p i˳xCjs܃0Ԫ{\U m}hf` 0F=}at!]㹹3q$&6&.?,5?ˣ0 \{]KZc+.N<=N/HrF{BmxHp=26iH yKF)vsh{hu&?AAޑ~uc@%M,[h3.M!-[nI/y}eE877Cgi3ʈjg}z o}:7ij>!4OJEP2w)gp &~?n/5We ejoE 8hvb۟ )0r/~r`ifġ JNFZҤ bA(E%V(!7LԘԔ'5iz!(;9+" -hӒ4.^ ( L]#@BLs]^}kx?,Aa? GV>c?#> $'dܶO0uUyKlBa7V'5?ɯFKJηXiadЪnŠO 55ͬ@D\vNjL-qHX FcϛƓ+QP(Q؁% 1HSш7;ޒ*sgTb (IpoϛP J@ hJ %XP%VJnET/%*Pp+} (77T [@K@ J܊F_J Un%;M=E"^ Ӓ]2%PKQ WDY( )8ڒ9ro tb>B]ZMhK@ ㊊N)Vܥg28˝?u} (71]inF|ҜÇDGGƃ5zz:uԖj<$a 8#%e?16IDAT(G|[E˗ Qzu~ kZ?t$P F-C5A|ƍ˧V;3Gp%aEQOA8766k'3)pQҴZWCM S@ƛ~O~s9^J_1HOHc'S:5CJdr=:~}&9S{'C:UM;xѣП~v#hF$}ZB(Cw<=s_#%XP3رF -뙜J 1!}J+\;@PE12<@xl_OΡӎ;M!4xp| kcڵ/jFᛛp9&5#|@fh >G-dv%.!ģ&PLQ` xo׮?>l5ʛIfă DHeΜG s gLr@I@ @,\4(@{3|;io^N.L_}u|nߞ.p::0Y>c;v%%U!%W?q~Ig@HrhFE:,y[~舳jyA?t^XT< rPJG_LyTVwr{a2!3,]&)3@;ٸIɕ+a@0j 2YEj>*3 ?ёWq&BiVL@Oqp)XtSO⋯M_F){ׂUM;-[; 2.]$/K>o>`!OY4fkbJ)o (/Pл@o#2,ԉ PYsN3B: no2`PKx="B^aA>2ܹIw6n׀ٳͤ1,XHo.jj@iڵkw#W| yȎ>  D^f 5obzG_:ԸiJ[Œ\vEf?q[M $@?*PswԎ@4Y{ bE#˖ͣG}4VԐ޿kvܱ؛eG+K%"QboWrkIAZ,顩s y.nr_W۟Y1ftutKL0!H ].|?G<2x5l؀'+%qOJW1vѳ'/=}[OQpc:,XwX?G:pݶ^H16hPisR;)k%T,j'Qx9J]HM911W iБg67qŝ?+/$' !~g|/S(9J?XV= ,YNO=" m/HEmBxpUH@H@ |K+9z47]@WPFp u 44 2c7nw뢑@9R@J|myJ:xa ~|yAߗ078P\"Vת5G^ > jM`H |"lB;jpw~!RȨSp@ "$ B 2o(~ ː%,k;ʠCLr"CNb#GI3Vs*"P52[u*V{ʕ,LvعgL#,U@1l޼9jժ3*M* ) =zu{_ӠA2z`JP3d%M]ve  "+! 7-,?546,+1'& g`aNFF! %/%$D:9^TSH>=.$#+! e]_ ! $-#">43NDCA76/%$#"_XY}wy  !(/%$3)(0&%)!   !%(&" UON   ?77 !  "g``%$ PIIG??$       # 4,+VON !!  E=</%$    (vppUNMIA@SKJrlk,*&$+ $( @ :^UYXXXXXXXXXXXXXYU_5Ͽ̱ɶ˵˶˶˶ked<43/&%910haa˶zts:11d^` qji˶smm!XPRSLL c\\˶$ ;22G?? ʶPII $ <33MEFF?>˶% "* :0/&?66F=> Ͷ  $:0/SIH?54:11ζ #1'&B870&%(8//]UV Ͷ800#%$ -%$̶~~$$ tonɶ0)($     $ &ʵ)! !ȶked  hbaʱDB? ?ξ=8uʱȢɩɦɧɧɧɧɧɧǨͤ4 (0 ,%81708180818.%$6010&%18 lfg18(  ! &18   )* ,#"18!/%$SIH3)(g`byts18  +!!5+)/%$ )  18     " 08zz"""rml18xrq  sml/8zzjcc~xx18ø88ٸ85ͭ$%%%%%%%$&(  Asgljkjlgs>ߛ~yx`YYjdc/&&YQROHI ڢjfe.$#%PIJ[UUؚߢJDC $9/.!d_`ۢ[VV ,#"'-$#YSRۛޢ   ޖKCB4,+H@?ޛW_\ [ܝO pyo/utils/E-PyoIcon.icns0000644000175000017500000036541312652732202014452 0ustar tiagotiagoicns is32׬?  Btzu }  G  M  )5)IL 5P1! Z )2,e`P !bTT  \OZRƵQ D[ _u  b #dح@ Bu{v }  G  M *6*HK 6Q2" Y *3-e_P "`SU  [N[Q±P CZ ]s  b! #eٰG  J{ {#" " N T &(&  &4@4$!PS  )@[<,a &4=7fW ! $+hZ &[ "bVa YŵW " #Ka"dyi*,ks8mkGTF<8y}v;48C4)#`Z[Uߐil32 ݃ѾމF  I a   i    \   h L  X_m   n   }    "   Y  g- "%'%!   8  !)03/(! eP5*!  %0?H>/%l   '3HZG2&m~V %/>G=/&"m}I  !(/2/)&nK"8 !%&&'oOEk &oOz "nO-  lP9 lQ 4  lR @  xR    OV  g~^   G  B1CJA   GҍX:+"'8\ѾފF  J b   j   ]   h L  Y` n    o   }    #   Y  h- #&(&"   8"*140)" cP5*" &1@I?0&j  (4I[H3' k|U&0?H>0'#l{I ")030*&l}J#8 "&''(mMFl  &m瀼Mz #l災N. j炽O9 j炽P 4  j炽P @ u߆Q   OU  e|\   F  C1BKB   GҎX:+#'9\ߏN' (Qi  p  ! ! d  o T$$`f$%t# "  (t   #  + !#! `  #&()(&# #n6#(-020,'#  @ !&,4;>:3,&!$iW>3+#(0;JSI:0($&q)#)2>SeR=1*)r݂]#(0:IRH:1#-rꁺP $%!&,3:=:4'0 s郿P+@#',011'1 tT) Mr! #&(*#0 tT  !#, sU$6*qV#A !qW# <qW#G|X#"O#\$ lc%  N  K $9J$ SJ OԒ_B4,0Acl8mk*.)Z֢T y OEzsK> teG:~yi1%OA!H<UH?56/X̶Tit32Z6Գvmiihijozۭ~S2  9]h2  =wJ   \Q    f'   9l  $l       ''   C X     ~    4 g    2   Z    /     w   g    a   b   m           '   MJ       (4  h    2O    9  m  4  h A  x   !b     C   H    7   Q      K      P  !!"!   (  !""#$#""!   Z  !"#$$%&&'&%%$#"!    2 !"#$&''))*)('&%$#"!    !"#%&()*+,+*)'&%#"        l !"$%')*,-../..,,*(&%#"   +    R  "#%&)+,./1321/.,*(&%#!  ٺ    6 !#$&)+-/135676431.,*(&$"   QP   m-  "$%(*,/2479;<:8641.,*'%#!#   @  a  9!"$'),.247:>@ABA?=9741-+)&$" #  |  Fb!#%'*-037:>BEGHGDA=962/,*'%#! :  : T "$&)+.158=BGKMNMJFA<840-*(%#! !   4  S "$&),.26;@EKOTUSNID>951.+(%#"   #  3  b "$'*,/37951.+(%#! "+F  5c "$%(+.158=AFILMKHE@<740-*'%#! #,K*   <  d!#%'*,/369=ADFFEC@<952.,*'$"! #-O:  M0  "$&)+.1469<9630-+(&$"  $-TC   e; P "#%'*,.13689;;:97530-,)'%#! %.XK   rZ !"$&(*,.0245625420-,*'%$"! %/\O   r  !#%&(*,-/02110/-,*(&$"! &/^S     "#%&(*+,-./-,+)'&$#!  &0_V    !"#%&')**+,/+**('&$#"  '1aY    "#$%&'(().(''&%$"! '1b\  :1  !"#$%&-%%$$#"! '2 c]  f]  !"#$,##""! (3 d^    !!"!( '4!e_    ''5!f`   &) %'6!ha  Zb  #&7!ib    #&7 jc     %7 ke  GY  %8 le   $9mg '  #9nh  Wy  ":ni    ":pj  2Y  !;pj    <qk   #M  <ql    =rm   !S   >sn      Asn  -p   Dto  !   Htp  N  Kvp  U  Nyq     Q|r  G  Wr  r  /$s  B  v  w     y  M    }  /    'g       e6         ܃  A      K  K        p        `      $   K߷    = 8  F    b g   ܵ2       %״{>    + D   #[.     j      *Z   ~;   Y3  L<   TX  p9   L΂>   N ݢg5  @u ḍfC-  1KoűԳwni jozۮ~S2  9]h3  >wK   \R   f(   ;l   %l      '(   D X         5 h    3   Z    /     w   h    a   c   m            (  MJ       (5  h  2P    9  m 5  h B  y  "b    D  I    8  R     L    !  P  !""#"!!   )  !"##$%$##"!  Z "#$%%&''('&&%$#"!   3  "#$%'((**+*)('&%$#"      "#$&')*+,-,+*('&$#!       m  "#%&(*+-.//0//--+)'&$#!  +    R !#$&'*,-/024320/-+)'&$"   Ӷ   7  "$%'*,.0246787542/-+)'%#!   PO   m. !#%&)+-0358:<=;9752/-+(&$" #  ܦ ?  a 9 "#%(*-/358;?ABCB@>:852.,*'%#!#  ޶z  Gb "$&(+.148;?CFHIHEB>:730-+(&$"   ڼ:  ;T!#%'*,/269>CHLNONKGB=951.+)&$"   !   5S!#%'*-/37BGJMNLIFA=851.+(&$"  #+J*  = d "$&(+-047:>BEGGFDA=:63/-+(%#"  $,N:  M1  !#%'*,/257:=@A4?=:741.,)'%#! $-RB   f; P!#$&(+-/2479:<<;:8641.-*(&$"  %.VJ   rZ  "#%')+-/1356726531.-+(&%#" %.ZN   s !"$&')+-.0131210.-+)'%#"  &/\Q    !#$&')+,-.//.-,*('%$"!'0^T     "#$&'(*++,-/,++)('%$#!'1_X    !#$%&'())*.)(('&%#"! (1`Z  ;2  !"#$%&'-&&%%$#"!(2 a\  f]  !"#$%,$$##"! (3 b\    !""#"(! (4 d^    ! ''5!e_  '* %'5!f`  [c  #'6!ga    #&6 hb    &7 ic  HZ  %8 jd   %8ke ( #9lf  Xz #:mg  ":mh  3Z !;ni    ;oi  #N  ;oj    =pk  !T  =ql    @ql .p  Drm  "  Grn  O  Jtn V  Lwo   Pzo  H  V|p r  /$q  C  s  x !     w  M    z  0    'e~       c5        ׁ   A     J J       n       _     %   Jٳ  > 9  E     c h  ױ2      %Ұy=   + E  #Z.   k     *Z   ~<   Z3  M=   UY   q:    L΃?   Oݣg5 @v ṍgD.  2Lpűն|tpo pvݱZ;# (Bdn;  !  F}R  ! ! )cY  !! (m1 ! Cs  .r!!) !11!!L ` !   "  = n ! ;! a ! " 8  ! }  n"  g# i#  s#  "   0) TQ !!0= n :V ! "A s = n J ~+i  #  L  ! P  !"! ! !""#" !! @! !!"#$%$##""!! Y  !!"##$$%&%$$#""!! !(  !""#$$%&''('&&%%$$#"!!  S !"##$%&&'()((''&%%$#""! &! !"#$$%&'(()**+**)(('&%$#""! X  !"#$%%&'()*+,,-,++*)('&%$#"!!  !2 !"#$%&&()*+,--./.--,+)('&%$#"!!  a !"#$%&()*,-.//0112100/.-,+*((&%$#"!  <  !"#$%&()*,-./12244543210/.-,*('&%$#"!    !!!#$%&')*,-.0134567654210.-+*('&%#"!   s! !"#$&'(*,-/02457899:99775310.-+)(&%$#"! $4%  Y  !#$%&()+-.014679:<=>=<:975310.,*)'&%#"! !׹  !? !"#$&'(*,./1468:<>@ABA?><97531/-+)(&%$#!!"WW !s6 !"#%&()+-/1357:=?BDFGECA?<97520.,*)'&$#"! #%߫G h%9 !#$%&(*,-/2479=?BEIKLMLJHDB?<8641/-+)(&%$"! #&  Ob!"#$%'(*,.0258;>BEIMPRSROLHDA=:7520.,*(&%$#! '#CC:!"#$&')+-/1469<@CHMRVXYXUQLGC?;8530.,*('%$#! ('  =S !"#%&()+-/1479=AFKPVZ_`^YTOID@<9630.-+)'&$#"!**޴  <b !"#%&()+-/257:>BGLRX_ehd]WPKFA=9741/-+)'&$#"!++/O7<b !"#%&()+-/257:>BGMSY`hlf^XQKFA=9741/-+)'&$#"!+-7s<H !"#%&()+-/257:>BGLRX^dfb\VPKEA>9741/-+)'&$#"!+/ ׀Aس<` !"#%&')+-/1479>AEJOUY^_]XSNID@<9630.,*('&$#"! ,1!K ?c!"#$&')+-/0369<@CHLQTWXVSPKGB?;8520.,*('%$#!  ,2"Q3E)d !#$%'(*,.0257:>ADHLOQQPNKGD@=9752/-,*(&%$"!  !-3"UB U: !"$%&(*+-/1469;8631/-+)(&%#"! !.4"YK  !lDP !"#%&')+-.02579<>ACDFFEDB@>;87420.,*('&$#" !".5#]R  !xa !"#$%'(*,-/13579;=?@A2@?=;87520/-,)(&%$#!""/5$aU  !x! !"$%&()+,.013578:;<=1<;:87531/-,*('&%#"##06$cY   ! !"#$%'()+-.01356789/876421/.,+)(&%$"#$07%d\    !"$%&'(*+-.01245567/655321/.-+)('&%##$08&e_  & !"#$%&'(*+-./012334.32210/-,+*('&%#$%18'fb C: !"#$%&((*+,-./01-00//.-,+)('&%$$%19'gc  md  !!"#$%&'()*+,-./,..--,+*)('&%$%%1:'id !! !""#$%&'()**+,,-,(+*)(('&%$$%1;(je   !""#$%&&'())**+*')(('&&%$%%1<)kf 03 !!"#$%%&&'()(%'&&%$#$%1=)lg  bi   !!"##$%%&'&#%%$#$%0=)mh     !!""##$$%&%#$$#"$%0>(ni %  !!""##$# "#$/>(oj  Pa  !""#" !"$/?(pk !  !"!"#.@'ql 0 ! !"-@'rm  ^! ",A'rn   ",B&to ;` !+B%tp ! *B%tp ,T )C$uq !(D$vr *[ (D#vr  'G"ws 6u &J!xt  +&M!xt  V (Q zu \ S}u !%Vv  O \w  x!8-w  J $z !})'}  T  8  1l  %  j>    ڇI    R R    t  %f   ! - #! Rܷ "E A! M  j nڶ; !  !.ֵF 4 M ,a7  ! q     3a   D    a=  ! UF !!\`!! )wB! !  SЈG!!!! #Vߧn>   !  $I| ⼒mL6"  ';Tvȴt8mk@   #&&&&%"   ;`W1   %_P  ?z- 5y" fLg n ]Z7%pF G"yJ q z  Wb/3  \MS3 {MT!Fq(EBU;|@;l2_  $>[# i. J X ^ _ ` ` _ \ U D c)V 5  Va(0 pk2*~C0i2X/m7 m0[i3+n8u 9`. Kd s { x l W  h:  @~R6~V%B&N2F-,u Qߓ< NDž< &\߸N   (LhȮaD      ic08m: jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 lM0<ÑDEt( o>xjWS_C @AՋS3ɅB: ~w*`7ce`jo˿3 <<`J WWw/$ qv e%@(W+'Df[&YŽ6dQ^2Lz=OʯrG[$;nj@ G~g@8}!L >czT#y M/7!_ͣʧ^ 'A-$% G){|}бP25_Y%"ă&;.!ffh#%u,J>_E%]{Xvi Zߖ+ =̗N쟍K|>CPᆉ .~nt";,Ln-Qv ; Dkz'㴕O jE%`v &o̭ttQ'>` Q$0j5SS ǒ%jpU$JQűS,A~f0 7sPNqL Pj8'\?$WM diaBHGaGNA:ŶY`N\hie]Q% %q 2$nf,&G_:r%ȵKLɻ^j_y 4!cδctָ~7-念_]{r}`⁋ʴk%+䔢Qr=޿ u]b,wr1}v;QWcx[jr mv{+jCmjw{T.ɍM+$JWAj.T\4f(e5aSAL'oݫvkP(;5e*oudQRG4so9e෍]'N y?c4& Mƛn ><>' -!ct;}d'; `eGfxl Ur'n=eEӹ#ڀ2Bx'ާ\P^u]{duXL"M˞Xr&»b}K&W/t-J=POס9L !iNSsf&.L/S#ٔN-*2|ʟ :}-3TO^ٶeମ'a(-/,VȰ\zv[ԅ@ĸ|8@jle٨z/KBԓ顚=I詻ڻKr5.#(2_-nSŪ1}UڢpI?xu`h+z6nH|xB* AæsLe.:m6(uYom8oӖUrܨd`&S̒' %M"~;"Y-)+ wUӲ<~C"o>8GFC#Ru mS5Oy+'%̩JMn=#F)"c#dJ kX0[/d1|Mk^"J䘅y6GFk*WQvK42?~@V `ACy7|?Y!lB gP) /ZCfoJq1".l z7B3*}AuyD\x Ф/ 6Z]=K2e\jeŸ*`ŏ~ #H9EО0NHSIg{nZ+BĊ#tP !'ƨ |ǧ;A|q\񌕄yw} ϩf6S5AV2ʦH2tk!,H%MG|M[/дeDsװIy^rZ;lo_b˷ŅՎRi+p'7@k93>0Ha=ǗmKpZ]B;b69{HFE۽ 䌗?A5 I(86ϙS',ϺrU4kْU\i1WVcJ3Zj`g% qr=m{CykO_vavL_Z7nP_i$C Wi=5|L>G@(ܝ47}ӛvܣVlv{dуm8k|>Uy9@~v[n7@xd4I0&6F8XQ*8z%2O݇ <i{K82@j'x 2! Gg+^YlSr#/L)WNJ,4LL$>e_CaT8{e7#8I~6-I%!SaXt#e8А)|BڂJFΏ"I]57q曙St>l o-TZ<8Ԝ- m3{'pM|?!}.*.`8ѽw=6sUx3&*lՓa:OCb˺~R*SpxPuv\"s Q@jZԪ(6=GE4Gi6_tRzS!q=Y ˅2!=9&TIbUO:j+:¿! *ܿb7N{bgPKV颦]6|oPaPޙf"uuc~- jY_˵u?iŰ^rOW\̟#T,m>yEM`Yv ̫SY081l xY389!ȕ(Mbo |#*錐LMU07T񛐅}xbE'򌋃f-jڪ<2Ł=Hns㢷p /Q=_;O=(P*rP[\šbcܚs%4Ϋ 0Qe1pB!\ڥ37o|fpEW/TczߵزRf^ihszQ(Ɂ|#<-ǩ&|f.t(,(!(V-K8ܰA6(Y}w|XîS|_QHt%+7'kalJqatS ]1Җ|fpDՕuja$uxgrI0lj1ڲ>g5~(nzQ:nȻ#IHnSs~dRS$^QXո52,b(N!Zji Fϳ1PQ%AX}!4a ni-zEmJfBl2%+%T6v4t;>=Q/\:/I&5uFCH-B 7w/r'ﮫb~&7^ъcC,ȓX0ح_`[' E-.hdu6K^@r\$ۧz2B8& Rvv*<蜟 _leL ߕ:trOt ú\$Kl&f֨j'K 6?jbG>Nñyglc zc1,`0+0e#UY:'e:duDŽ1ύ$jdp!yX, F/2^Hz:Ld`nɢqِVApWA$:5 [eũ͐2lsO'n\(m .>=?SU%(Ӻ[}祿KfAJyOuOq%݉CۏBe*>Û]0hYW2~23{v ƓCH9CMh=Õoy̚dIK8{IkP4rъ o[?vksK(bj՝x!W}L^: !Q9XOL˳S-s `aWi]j_UU,a,Y=X1UMfYIc_p |7&JV)̝2 ]06_t7Ul2r"Ưg)W:HDˮʙq>`7<%k/gpSK 9nj)xv(kI7-lS38|IcO=ex7i}`H0e'PqRg]&b6\ե@Fb"ihݐr.S}^DZ DSG v= NbgC4PIV}}v~i6sЙA7F^Y\]@+rބ}ET~]"zg@ЧGɊ/P݈<Cw*xj#CG0 87%$F {`JՔ[ອU9 ݔMfJ@ jmfTJ .1Ly 5[&}hQ?XV p-&<޳Mg#tG!"s/<~lR"9}]%9o5Vܕo@lzG)9wyy_Ym=%ۻxI8J﬚ TVBmZm->?Җ l BjV6Ajb{^jz|7|}\&x;.Fބ{YgGd9`aRSAme%l=SU[4/jIɥ;FZρ]8dO/ (@~?t |`^IiS ÿ4j`̯Ezaa+g:JVqF<'u"eO^_Xʴx kΌ/QA(33&]Mdy!׭ Bz^ l݁?f ء"qfztҼFv˅E_zdLʟoV S\6 eXazT,˓_f﵀hɸ/Ÿk>%B,;cl&!{k#l6OT͹"Eߟ/asʭ ڨ,vm|s{ueAVQę9$+gGH#t ӱ NUw10Q9"w@ _~n4`_pQ`0 qM"'ILߤd]>KN<>Z_Ûjt"sJ2H\'Nd&.XLv4BʈUKc`K;#Icg`Jwg_\/R/0=%M:^^x^!u@ׄ^hU`qeƬާ=ħ歁EY~ǖjbf7י=k6д84RlxEgS2I+ɲޞ6Ck!m6/"w'I!pb /2RSf*ˆ.<u/%rKהBL>SA~HS0=jiL-׺71"fm*j$Ht@9G ޖ&NLs}B1!kyZUx#' D!@cw[?^t \_ZY"ts_#d RM鹆4rP֢qA#"ms_4OrVmWH0 Iɝ_O by. z fwS9~,wKHmd+⹭ҼiLS3Az8o٭Ӭ}%7قnm'{̮d[}/Y~!,_r3mZ*Pvjl?WN/kpʠ6Ie=аNr$"rNQͥ ~LTsVHf?n rKwo8qZ5N_9؇kmCDrIn=Uܘɾ{[[| KG,upރ䭶eWTST̼=;;TP i|zuR@D5&!/eG,泄  nwOŬ+C= ʄ@p]O~!5 ?pH T 2L{6S5g^%{*E\j aPp NOvf Â,O4jҗL;r@e[Fv )Sa8m.SMV_aAޙ+;xċRp/w`Ŷ[L~ b|ٞQg7 䅌"ʓlP0]+ҴɄ[)"O6 .c:ZoV\C]]nMZo6& N[4k/=,ٷ\ku($iܠ ɵ#'$k:tf4B%[Kj*#2VJ,yɖӚD.UăpQmF%@и[{ݏ{x5qJ;`Mg7ܼ LJ@lݝF`m1Kؑ}.Z:&bؑ5/ kɽ X ñ86R |Tg"X8X|iG<;o &$AA]\@c6X Cf«zu5AU.J-0Af+W}ُ|,G`[UHh!ɚ~$Y#o'.O%\6}#U[\PkL1Bʻ7N:oS2B#؈,0IĔ"7L_E6ޝPL PKa,3Q: &ʵLv x % [LQ7pgAЫd3j\}^^f?9> %ϡGì.k'eʗ*b3nwEզR$95^I|X͝Bմg3?%O%x3 ]{.w-wICzNVCŪ(`{oڪ;[@ekdx'ial<:A]}`HDfK`1q KĢ[48XᬄCN': dr'8L>р|=o@/ Pc *Xԝ *"%g|P:ݾ5+NyL7xtV6>,mbe|H !?֘]H]u 7™V*N a0nm1I\0ڷ-'3qmp3FRck|M5:ix՘^|j@H׹Yhڑ%qV%7 ZKAZX)3.Zˡ4yFnxH< *,$^NRGu8an-ZQGLsv8bqS!L@YK/cϯֺ=[z2qmkz_E9o^G_&XK:7\"&ñO7Ac(e#N$Ţ꙯[9p~7{ffi`5oWb}ka9t'g[kzV^Д~pXs ԛ?t ?P7&ЏR tHLZZs3N8R0}pqB I>v=kQ`윻5Jꟕj,x7C#?S z.Oj!L/<"&s.gPpof㩰7""YFMx bs%9"r tpRC# y73?|0en1Q,C z owL2 /{HD4 ٔC w~dM-fx{S!=i:UrByP4.\nI\IO$K8u< +P29FOIɎDYbjб;NU)!xoPlB9ZۖW \Hhu]>sQu+/|‚V!6ܡA2"'Z g XVJwQ92?zIXear{ü2ʦ_ڐ`d/Rs Rؔw<ĵ JWZa9@-|8B,zO1-a.vb&۾ Ge!P9zo{c mtd|)TIVY~nRa_cCZJ f#%,/4sPKp;scLb (eKbէF']1O 6-ފĹvE K$+9++t`U!Pd{B X_dg"uZnƸ\FKOϺzt* jYeuG]x39Z3IC$zI5C" 0^nS IUh s 7ޙm3F{+x\XwۨyfqVs253U1oh+),?u- |=}ZrE7t ?mO:uPOä1,%-\ϖL'#E5,-F>{vɊ&SQ*'>PcЉJٵ-XPF)M0拜nL'lnPW, S zHNkcj̈s+ -]o10eY9E>doMٔP @M! }ZǬ%bݸ ݱb`5yKMs]n0EA4b̓7;G20r0k^MB0j،k]ӈ:w2[ ʆ @hZIk=o*j\W&=j׫ԡ;Rw}$vqz~ݸ&ބ?oX;3[.{Uba@_;qHEȬpmH ,;h߀lQ4ea<Lj1Sͪ)YZa(lw]6fMa \Oz`%#Ժ (~j[kb@n_e4DJj^Ke-pؑ-+DTݛqX+SBiG`?3'W>컴Q%C^/[#ua>TϗhWi[9"|n'n^LyD!okV3$t"M .1,g89p.tJ=z"nc3i!2-Y|,Nqv4c)k-qtAdֵ̞zKˇZ fqs4 4ja|7^ Seh--gG|nB]Xl=݅Ӝ@#UQ Ip(Ğ[ ~)93Ak:b029wq)oUU!JF aU_To{ҥ|b꿿(fzćۂm7Zo3H+<]ib-}1!NLql Btn4F#D Oq#xWn &ㇹDO1'_1iPޡi;|amt屲MA,a5_Ԣi==Ix* UmAMP —=L=2BxYzN}0.w1F%fƄSvߋ;2jAzn =wsm7jްy%!wIҐo+wVr :X](dhd)=:o-<.c$O=AG3.ܘ=C.+ϫꯤ1Xщ.M5m-6٨<͠bSzdjafXWofvMzb;zBl9ԇhVal)_Pȥp{⨿­O.cBI鍈Htj]9 W ;8g!E/#Lժ5vE?S g}!GX",QN' ؀h(*5ӆa眛:Jџ| :1|MsDIXAgڷڹ[cuӚs4aZu.@P0uJp3F>V7H3Von}"~[kvzVAzש36ژMSY(Y7vA߷d)t~P [Z{p|d7Bf {BQ}lNՍkC>MUu<%mzGo8(dNK UAn}qeiOK`6 ?&1zUuwiD2گnlf(E~sc=oUϖ6 ^@7 2ɂ>Wf9V6nyu HdB#@-eyxך5375e J*[D=a7S92NP%a/ȕ8&WK a2ۋ;`( l } Mρ" kgS~((EK"@^B{:*z{wjLڱj=#DU<56, ,TI[G@<B6YV%1$4772sSB q1¹A/2?]X=3hK\ 9h*^l yynUdz )WϦQ _Ҁ a@kŴ> LRba ڷ ,M&$*7m3)?ZWaX$jюCd@2y:_q{ DL3iM:4StG[¡:AUք_^hD:MD{+q'xa/2Ie;K VڗvIx|{e1"aI*tBQzw NIf0N2'ZZg v 2V}]ͨ\E#i2a"b o4k /X\(; 09xYnYP qt@N{Pw?_[ƫ5]4k,v;#4k&ǍKܢ4 5S8Dl@fʜ9`c=|?}qCHtFd__Zc*&4p"#ܝnӄ-sqlo0|Z3@cZNn45ܞh͐m<-eķ5Q)* a!9׹.`-}#[r#*.FieJ+dw+)M,Phl.u@݌n2muj2r'/@<5,?I< c,JdgK,.)cI2z)}*A_/c[V \ 2`t gF2p%'b?+q7u .]+ aՑ -=NS3ВH4D#~`j|cs9Z}#S=8)Lɔu°u(r>~Rz{?KdcKP; @נkdq{20-ߊ$ږڿgeƘc MP#k̯+/3W[Oo3.[p pI^]h1ʗI /j|)8!aiKS/kߚ@vPkmG/,b:_5O !]7JVr a$wuG(M#f9b]hwëZN!X C(#b5L4K v~WXHP8;{AT/Ზ-J} MD\PAxWBi$ҲͯEM%k|)p&/_1.nG1m3)*z`S[ alN;MtߏTКJ>XT6X0Mz *7NWR~XY Q'%18Ź~'ϜUOvU"gӂAX)ZIWߔ}(u8~Qj5~S1U'v^y7"BԸ"p8ZavHVR'!1I6̜>wѢѝ!7,n8/ 6 J렡I1RPCZ.m vDZ#yȾ41(pٻ~'.PvusˆIoch$/i(\z`V`mJI?(!W@>u8Ϋhk`EK݋}EduebiS6贂%Դ;k354Uu$N%o) wdB-6~_Hvg`&؝Ec<4Ö,?*P:Nq)=-IRnO/Q0°bf d{̤]!&) Ax".L5ITCHl{_1p4kPmNM/=A5)l + ~dTeK[u*rk=4S>_ZVpd@T`P2[.A@X:$aKa"|g !\WF .;3>Ԥ+f(Qu@1xo#Քj.4@Ri;t(HP+fPdoiZ] L>ATlGDt&N(8gwxTҢ N8N5=tEVs4(NCk`oVkʜD_T*?]u8< gn ӷJ9`eI H$:w%o)N5Yz22Pi)^uSVϋL>?ʖMi8m2kFiE].94Vkt[]Z0&P1lITeJ EHFW%w /twXh>x_g n'J[bK:*Օ E:RZmu/M-nLNKȖ Abn=nN4c;Cr|WCAfx-uȒy^;Yhl?q%,/IBgiCaNf S&T6N}M;&z͇+U/Lrz#B茓Q5Pb k%d->km^OSuq~ujRٲcgaѱOq#F/rT@aȖ34 "q-;_>֮2.N V/2d:iZU2]PsG~_Ut+nK59aCڈp#Z.??WgIe J`gmzmu#Jr[~*(Db!} //346HYgiS7)<ʍW|쫎K4!Fw7J(ٹ[. A.DMR.߻*h' cv&OrYtrs5XGF(#vYVdjpkne"|+VS-?۰|iWŸM x>Ijz'/k$]iKGrpm7=@>.ܼ:5AnG[n I)SAbmZ C$2@lsc=1RE~#*LVa}G@y/t\J[Te 8 P]4LzC+OyJ[iHx4/)\p@CG&]}v:&ŚחꋦX;#P[E(+&xWH:6fR70laCf) 46Y~2ՈHe}lҜ63ٔOv\9*{Iл,Qy*y)|&[tπۮt悆zRxk,4vjo'g<ۈ&#x H$u1}9 l iz?0-:F觟ԋ. -R%U6W?ń9f5,E M$Dȧ.|tWJB?+F2A8]K>)~BQ a(43u`> .6h|@Hsk[d@ܮZsg C?zcwӟI~sӟ.w F![$ԉa_]ch *9 Q!CHkE.χۄU;0gT6A|m@\y)Z`gnwXt.)3:Αt0;܈KD3Sh^a6:JsjM pau^^ mD.v E2g}]9QrNĥq-]-)bM7-noඊCC.T͎70rŝDoasƉoYÊ8vU;WY3d߆x6swNbȣ?v ay v/(5D-qINxu5.?{Y:, 32(d^Yu727;6r T~+"Ba{v/JȽmZZoL#.}E$fe!Lc"QډXtތ64|;al֏Gahrdh5 bw2g5*@̨r'\~8Mg[%lʚ; 2:#U \j0Z50Ul} *Zg"AV[O#`ɞ\nT)d6JD;~Q0Gr,+~vn˚,S:*ٹ(PB "49 BPuRX2ſ磳0$#N~]xeX՚@;{0G{?*4d䣄[wV7jշNH&lͼʟk4?j6 'd&wgD"pR10|jK5wYk)M Vh,e9x%D|`]@ͣ*V46$= &)fȈ핖M;' Xʒl;Shzdw(缱Ot^8`A-],m !yA,&%vl`)SW,@f~*1_NO3=NӖ檓 )~؊wK@4 pQKu FXZۨ@莈yB)s#?C8i>zTx(jHxp|}A :fQy{ZB$rcnҨߥym`䂬Y^_xBl)K0IRjwaNɅHm)}smkQ +I^ )Ny#Lúݫ s=vj`FppWײ9~Ixa.c=vO"R '+xL7^HXnRv}Qyl ,0nR'h-iaU=%3< .B]7)P~+RC=*#=%)檜Bz=һ7/潳kT > I>PvBJEPi^QjjҼ_)EZ0ԗָ}\U6?@StG;=vFh‡[?Q;<ǎ4InTpg׬d6bLJf]`$N00T!o\+k&!w.pD?eJ1m`r`fƠ p .?PADO&32޷ ">m3?׺۱gŽ&Ώ> ȆUWn**sQm#Ӵuo] 6e_;?Ks`Wf4cy\^ :թNa5sQg:\yGn4`SkĢ+.Gv60b"͚sQa_DJIe.J;Ctyv.qGHd溩%~6:O=g6Aac |+_C.`+,!RoI:Z}\w"iFnl(Qc#i|{CHV~&ȓ_?#JV`'oơ bv?ϕu)g6 y0=3gQE1$v.+9pU:uh%&̒*tPwl&C, R9|23&Ӟ%-yEEeqK$S20P+e_8kkTω ۏ9 E]7w5Q0JBuH_*hoQ.e3ф]4B\Va6=4w%8RG;HC{ewb[4:åoN¨_zV ]Ja8x*DJ|RGY6,G U+wϣ\%8r)crL9Elb,iw0(O0bypn6<6D 5sg&d^܃%rVqN#/Zp]RG9 E k:~J=eFU=*~>wıx>o}W3CS#[Y !+[g4\YIg)BBqLj@fƖe%DW Ƃf~v>ykD~fF8ԡ2;7x\ם U CƑ9|58q t?hBrj]8wI<|M$I NBTJ6#Ur(7j34qW4 HYo%6p~kAGX/˩˔Ѝ^By1O -@UbSF{pqM1n7 7} ;| \/ 0%3Ua"S*nDa}p7V[_u0_pe*io/]k'̊a8/I|g2RX噊5 5@STjx^\ ,s5HOFZ%sa4lYA%sAןۤKl|svB#L!5J'U /D z ڀ+~FMTG+|=|f .u@ѲrP0SLxP>18&%-eO.a(oۣ߷Jt_ҿۦ~ EtH3[`,*R+cI譜X' }G:n=M1e U n<M -!bS+B:U' ,1{ű_m>oc`?ЁG/.m"YWId~?yyF1ZiIxBpKf.l GP-R&U%t;Eoc0u홴s/Ǵ*Ǫk`,p),<ni$(CQs8+cAsQh|0#`\*^'[llnC> XF߫v\R_GNRmũ-lB7+)iC Nlq<ι7U h?Ygw[DUv෧\J t¾cRq"~NiGVj%Egn==Mˋkn]zeeOU+4uύP-^Zt9|4fU=thO,Ce&:8r$fhx8킊AA:5/b)ߛ%?5%5-eENuj"%an=cP3Cr )ݻw uTZ?f2J "ʢz-r' o,Ḧ\wCOSٔ47M7hH8 % n\űfܣڑFݩ_6ꩭQH~5iG1݈)0ze{!k'72˦K3F-Qq3 3D@]cxP"QDNwC+7OT;yfYod*[Zʆ3:䌁-oq9G aCtyYWf Xd|geTԲKgƧS·j0և5|0qDBsD jJչ0nQ :!!^ATYjա΁}CpKr~jOͮquz :EYREw:Wu֭ՌgPrN*nfp]#dT^'^r&HZC7Vh)o0M D][Ns`˨ B-Q-ųe•ѳn4l5'l۲tT5e;9}NzDf RiRR Q(\S r[ Ŋ &Y&S<򜫓:k| >_t s'9*~Ĥr-(Zst^rKvMS ¤?qVxTV m}(s S4CS".9p%2X}f;#_vjťOph#4田k't7M~4Εw mja/bS>OU s4}ỉ&<#ި'򺭟Lh9'-t@[p;j L?d9P|^>% M6X@E/S4BT)v]tʇ:zh"6 Ѭ%Y# D hkx >q`tn_@\/Dih-nb|C a.ŒNRuX'$!Ҝr?l<‹1c].7vBuR;x&D1;a}2ZEMr N3=0=$"1<zQlBpi+X3@y2)#o&S6occެ؜5tzRTH.-*Dip+LJ#YCQ4|j(J8&5oUz=.uфiy6B|fezy>Dݮs_m4h[UѴd1urBo-;-C# `{!գf<ʈ 6$9d<^B:bY:w^Z鲋/ol6jhɫl W+-; y-8"V5.7Zj+ð~V2эC N8!o\+1a)OppEh:/,&)"09a|NwZ! 2yhT:h#}7G-<òjB(ؗs7Fvq+gZ|mIU[d%G_ϔ5?&*xߛUP:>UdHubY_ؼYA%g^g}ӗܿ"St/ O2<8- w1?gLثU `a$dexWR*; ôCy]nj}jYd=,ɏBnw-rOEBig?IɊ`LHo:iV{B'漬 r6e\y #SCg"QZ7 7#jTj(A(Ty_=p )F_ٗ#֝(%֒Rw5JQ3pm!DH 7燾@XNKamGx<ÎLOx a5UDKď{F4BUEFъcV+8,ն RG(# ً^+A%v@TkRKP+,ٳţ$>oe:yYZiCE2Pz:17p hp/C FC {B/Kjd22F_Iҡyw%S꘴yqQ:7b%Ld2͢!vx‡ݒo =~48~G4Ԍ~1_N6ȕ3w>9gf.q$AEimč>}0 l7@&nHOT=xt֟pVz9G\yjڷNglHf IJjud!\D;ZmK(ic09Є jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 ϗ:2AGĆ)HTZAwג9N/ *!fr(>vsxǛVRi+52wJM1w<Iޚ5ktʫe,qrXy_//LoT3(hGIȥHφEXHtKoNx=(( jqL$%慆W(,)ɯ]&˫* zZ[8P*uH֛<g"i྆H BKfNj`KE@m1ζarָ~7-烈ci|+9U!G$Sy9]1Ð൚_ "IN Wf ?RgBnNq/d_Gv HH5RvSX:lw!j>s>#~\IV>Ppp|͂qt * xbEX;5e*oD$`| EmXXN/~ŻIn*#ы_e ,CmP1X,OE)jZj%(}kk i&sM#LH[JQ%Hx6r wYVnF1fk0Pz2xb\mlX\`M7Bz^u]{duXL/%>E_K{g*s~^T"FHg=pO֊.Nu5}Ch8k׍EcwtݽT%N_Ϗ$g*%II2r\TY] Mw^\²xZ(U+?/I Giw|H@S񨁌u4qO}$ spP,}I6M|gQޖ#u09T_&}" -e7C$Q~ecxm'O֎8ei\nhǫ21adK{3|[HUVɱC3f\'-IZ,8B=Ģ Y,whvXhxnL1-',0.>8G3} CĹ7{3-XڠrcI0Hi4lZĘnG?8*d-n}H ;4B+1_rWBl5:òf3P~o0@6)4(-e|(pQkkʋ9/!a㙳319o1Yd]&w(`|Ƅ|N"6q>t}Q&ܑ̼?7o0Uϯam:QRCfUF=/TTL92Om,!)WSZ3vrd,Y0Ba )T02S|{lpylvg ;V< |q\񌕄yw}37 ǥ9[DbgNPg\y(/xq5s>Q[5 .kYq$@NBY;Ziurq1k93>8N`lAM;|+USbj4 KLa!%~I뤕'2dsirfQKʕ'Tyz&}s͝se#ѹ$@ݧY{xc;t@1e 潦0:xG6N k\@U4u'a`wϭȰ.5].8 ]s4>\ U\Uڝݗpfv TOdOf#}~Pӟ)V] 鑵;4·t47EӾHuTAtCe Wg\p&_F˻B;ջmi#j˼CH!L@g|CF#qak!?M]bHtӫ?PDY2' ±sƥnH E ?f/#]77K9inQWguBNuy?nLn%4fׂa6-pϷ?~P  +\3sMo"dA(zT[9;N X㤗Zi3G/ sl0; n|pwW}0 KӍW Epi*n ZS>֒FsshjXQ2m JI8C {$GX: 02c"}1*=Ygid%#j?f #k}[?h/R^B".If]P[Qz-(|\b :QdXԚ †z&{xdV 52O8vPB25))MNĚ7G GphVqi"0 {6?+OB7Zn彐'uUN . M7"T=5cvQXd[ jkUaeXZ3ي9麱߉c@G_a ",Js7z5vB~%)9_ɇe+]0#HdW%6< aAvaR bjJ$T= 'GWw˴kTrrrcbZ!ϐ|Ԑ\îSZ GZWf!\\>n^e{⤮jٴx=G0moi;ͼpCaK?1d8{@0,%~/,*{]M턢lk :=(}ObDb+'l:EaKX&wB5UZz'U_ϟ;}7t==]fF@D";Y⋯Կ%U) (x._iSszOA1ČshpMd$U6tCqs #q~E$ 3&‘qDDСƂ@w* ȮBd 9p#i"D8mu9/>F3kXv)gLl@iWR \Y,&} n r&~0,4 X h@R:$ز#\7Dԅ:?h5D- Rȉ}Z.J[ψ6= 9Yoe8b Ff`^މ_8[e7̯.OTb>k %γUsl^a6n{C@!Qִ5ATrbΞ&oSrTޞDgHJ!YC4G‘%U "SEf\ގ |rhM."w^.Qy2}r4RKҴkS!B!"hui[% 8N_b͵ߢ1GM~.f-2vSJ/Vs@cz mLB6N8zr;e`6zr?C~ /[l-2cH]N:vo.~I~H q]Z:T%I}aXIU;&ݟ=C`IR>D pGSFq (ދo#R(ξ?H Aާ b CE8Hc\sXüSDqyDg t4(iQAAfa@|㐏x*6=ģS!DH8o-qGFrp3"^ o} cBTW6Zsg+OJۍ,)[+91.VK +EŌ$OQ 5Ҿ7 m1 W_ܱ'6BCf=NMg$et>Bnϒ8!nWq^Xh\.. BqKƋ=X걬Fڄ,iYTÌ'04B~ -Cf**fd$%G ׽ov:\$Mj+{ rX; CqՔjA2p *W0{x|ȿ~Vc1~Aɗ p9"rAv +c8K9aŒ1:zs~Lz̈!rƀV ^83PIT(Mڳ-+1\C~k(J y,)(6a|okm(HX:LHC#MCO8cvCkv '^֬MfcycfhUJ'#XA>nBf=7(;=cD2&Jnxn"2Dٙ?XN ]67Yʣ T# w `.h p#܁ahZ,A ,"ߠeAv֏\m{;,NxUvG|.X1t"cZ>%$#׿{3kT?pzQމK(Q;ȕ c4d%6WB\㺸|g4W@UfY&P nf&lWFë)*|O< eAa?hy.r/֕b3!tΨ-=G꩙5k&V/ =hr*X3&`#oa*S&(6 =~C5F_9MJڄ P' m̷߻VD''rW9O2NA .T#ruzXMdb-7a\}7NGmg^]Ed-n,=#||"?|~8NmAI%zF³WxG~o*5wf]t'Smف s+r5-6#۞o[zł.N҅}CO Iyϛ&F6EF/y9xCɾ_Vq8s Kw~W–&YDB3;e\6 aE.KŔۮQt?+6CFoλw4aNtޡ ցu& fd[}9^8c_2In F]c\u"ooFuN ?:a 3P]+"${v!?zv3Ex4qO۩0d2+LozA2M2s'5h>OX1H,Y~b6D*%.c-}=|9M]d4c>ȵ@G~tjd3܃TU+&J`6Ai'3 SB hhĦC>')2{.TY猿x"}rCslzvfL`$n.-D FKƉ,20Q<<$͡**A:E_ X]X|ozfqv&6jGrg867H@ptC抡Iv:k\۠c7$} Qf)Jr+J}azҌn{\shxPT>0M-2{{z6As{h{_h-߸6Ƚwz,-ޥoi? L3x#C _^|j3 ]BZ\;+Ŷϥ!VbU##@lr3U3 FkIR~Qc'1VC_5мIv9 J+#$P, Hz;A߮r`QłSP=yQ'u*G8!iPx$<#_;J,XQ)8 Gܜ.bdlj;n*`MOlo"ޜ% 1&0r8/B|X:;,<JIDW! $jW&ئBL۩ISKctLnp6^꣒|oWE(G/<gحl,M>;za~ <*s]q=-1mvS} P6{=jŇrsu IFͅPS'[s( &iJƠqjmUAfdj(bzd LIN@#bۼ8q[xҤ[0Iyq!~-Y.ЊoUsCV3,V&_)b Ux lv3{<}{I8/ڕHr\;;aY&f7Wq%TApD AYTz-?i&߲ͦǮG_Q?)vuM%q7.ҽ}F.3CB1N˗>z=5v=x=q|Sv幛iɹ8oAvqHp奦fا~jPVBr=u~(Dͪ W 8`k.~˵ra<ѭs:zbnv)G;ION8ΙN;I3 1jia(ǭ95 z-2 \6cV_e ^=H7(WH{h?0iky}=Fm 8kņ|l89 yB;IGs:Tj2W0H !Gqْysk`Ѻ6ջl3s02p^QG^er'++%Aw9?-FܾXA_8r>oֳwb@qij%#{nkx㌥B"1x9 0wK`Ąㅁt_lz G-Gr0h&; x$/4u++9Ӄ/ءYnǜ:WtW(' %dzNȯ  մɉ0De氾s}BX0yT>|=6ʨqLfYo֖!T>5jDao;:uZgQ|g,$GϧUAvw\O~Cc.o+e`xQ8d]}Ο3{auK6඄l& h"cҕ;Pk4T sɸ;VL6"޶sց1€tTdEp 0z|kk=B;m/EpbڼKꉜ 6q3=M4ʁÇ]UKL>;tneOVeV"<pb_bpع[jx- sqH X@cN0(w M<~G*7 w JBր\fh=J6#X9uk7^6IBɔNUHX$n*r A滫:-&ĻtSOEw;yYhO7/r*7mȞQ,,;il%ht?(?y~4ɂt 7ހ_OE˂\s|ٮ# fB7M'I cc&_U^D]^ .t1Cԁp`ك"c(V@Pa%߿0٪? %tL ],=lq`JԊE*&h)gH}?.PGm Ӈ"MRNz'ݣA[Ng:'XKsWx͍$8Q=U M„fm?/.F{7*l#0[4dҍ{ܓJI(f*g!EcxT,$Ө[E.ۚ7HTJ H >τR՟tnuR۲Rb4ꕋt kGGbG/ Vγe(F{h3kPΎD}]zZyxwӏ"wS&ˍDV, U;GA#MÜ8h1Ɠl/w\m ^dtA>K}~kj#C/PC'5}]=8"Mxw!FI(j e%sxA1T1ܘ|^z1+ۈ@D̦E^]wӁ4oT9Z_͹ҌE7꿛8&C-Ww\Y=V=w"I> 21114(u2p(aipkҗ|&Pj{zxx -۲ t=TӗSn9fޣQm2r]|)l3J5<}'HGBK_K< gBBz~U-#(BhajYIRk]b^O"$ږdq̶9ya)@x5T2b4VVG XuJqG0oڹPk&}kz&#$fޏ\<˭.s_0}wѓǮQՄ(c*O^ J/9LBn^ㆱ(mdm\rOPP)j4WV(ɼ@bkHYd6ep'Q5VӞ^4r˯Zd՘N/#Os P%B':FD͹ c/!μ#t U&!ٸ:2\x)rlKoGb/'ˏ᳿âaX0wΫ2Rh)sw<`tZ h&{μ0hSNg-7y%efE+cwb'ѩkk8?(H ֣|QJ/Ft˫Db ,hmrÍg].ԅ+5ҍvf!Urȅ>ע{+X <-@̉-3Yoܥ()7trV$0,8Y|n[MG~unz o;wqeq c/kp#z.Ĺk4^~;2Eզɒ UG%O捍%*KiPRA5TTFKoQ }W9BqQ#O$]@ A_{Cj/ث3ni%=7+ v  [_t(N8g5pIՔàqb7L?~5r3vN ΀n7eakDs }p[!! |U"G~Ը0'";,B ڡ\7LgV_}Z =2:p mTp^Cfpϡļ2%w Be+5K|ƥfcR&zYcm%bi3&ӹ=PlDY\l{.=]Soe憸RK⺔a$pQI5cGª8*r;WXWXrϲ.EP&`LR^&K;W!d=n=V97׀rv~'i+`|<*'!)-s JiӣgQ_1zPlX¤2km$O\v?Vr4 %[mvbz Hd %4O2L !Z@MTB*T+=Z"|TyTG[jE0^`Oܾ͘A&Ȍu'{?fs;7ԫC"݋ S'Q$iP&d&.!wrR RApf79:cRm0ӝz(9YRLD1jS5+*f^(A *^56aX~>;G=RG -IU9X>GrYb~uulb}.\2|̾#߶NJ­AqwrA`ց7c1KCmS ~\V\DdTR8&~Fq޳!XtH7,6oYTu}4:3tϧe<,Xq hM\hC*<|d"XvIS ~F9ew1+7ňA@6~3"Y8ƯUЙW5SMpUZ1b)!m΍p˾8\#<)h+1> /fMRbQ/tngMl`[_ %2;=^_\UǷ}Y`*4o\KͿܥ7dmzrE{ֶx2v~CzD}<.soF{gm5l@erWY,V~Eqqǎ MzmnYN/2jXa  쐶=L.C|^M7*BDj@dwemxoanJSun+ @LÌy~ݢrmoR?9Df] ^t$Mt#?){<[DĎL1rR&'az c)W|1"Ð8g"yQ+wzD!N1X"*Q'tPeG7W;F%+F֝[tReȕYXCH^F;ٯc| RnƕMR`pz˖an?t1pi~BHL$Bc fY z!+3s ,#<䨷^dZŖ B8PU;z) !)읶&@TGZ-{9Cqcq,˦,Ojh] U&q;~єZ3Y-N:GF R QCr kHFBLoP( Ol9ׇDg _ a+r^uJIJ9}yi K.K08ߏH B~~Ǝl)E:9uAV֕"v:ۛ}.'p;BDO?jgi +掵0[zWiR3(7jLVT\}oG?}$6^d|x`x 24nȼƒ &?|$_j);91yȏ&_d@#?w&\;41jo,* 5z_8owUP% :Z)2|* i-(gS>֋,MmB(M逜#=CeT#Q/b)x. V/qbǴա&Οw[!uP^oo J7V~1-+ȍHC9Yh%8X6%-x;f1 șTřI&k4L\(%͍߷̤%Q o,hwp<[:q,Ƣ-ٵz<ҀQYѝ9 8Oa62$iyE5!*t"S3[h5{~'ljY=aLe_GbH>|O"W {"ȯM>K7iX: +' N~b䎭Ce8͕7"Cs*_EeWeW=Y'b&_ VNF][mTQq~ hOBԌv'Nrlo8v ynBO5 4?v:" ~\~-AdvnAe] qXy&Op51O+ʴѢb':=PXMB׮X,d>&|Ez/fba>7TqT4,?nHkіKm\b?b88fp8I{j(ch 茣ڛk;RkIJc,>CX/()]b34GUpC )^xY~aͩMGF'[{ȌNqjY0ԖeN5PVyAe<,`ٜӥbCv:.0βZMDBdz?Č|k7*}q%:H=S(\dvG/Lղ'2iyvfFk2aӮƕ^*`q!=z -_-T+};,yq5)| ߼p{NR39D ֻba~ʒ] wQ>rYjz~ SXEX `y l9yOM 7D;˘ݛB'Ij$B2&ET #Rp( s_ߢ/|{+x4V W-o^Ⱦҧ 0}{MDj;#Yf;PIQHbN+M߉UnN{F5S]xQOG=gg}lw6&qi8#yhxeJ{ht#ˢV^̪۹pp)}ݶTX*s$ga[L\/0;DuPo/v&>׷o)4x8 Q`7xff W5Җ܁~ف f  k2V1>(~;"j&3hvذ'E}q76Dr^2T!hWٳc,AV$OBQ8V~POX x:Gu8YѦ`ֽj~I4;hL[| {0ʓ.Ƶ~bO(=kTPp[e ڷ| Ovix͖62x]iٗe ؆|&smKr_'֖V*AXB?PPJɚm Հ :A1>uQiPwgɁQV3c vQm?|?dkkӒzfZA JyZh=_}Vu$ hR;wirWsQ6.3]|FDq0=Br,/V4H&t` MRc{ Cs6@{xO:bƺjV!!+:_9j?^5[!ؓ<-zֵn I,q駋NUR}䯱pi"aS1g:lߞnAj=U O\LXŢ+6e-g_`qɇ M?/ڌx<mȽ *I@5^\Rc~Y$2K`W)>l֫FA8ZbS 蒊j>{WvRC&Hqh G thX[A ˍbvSJT+*T=~9?/S)n{ք/-s]-I\(W>#6H5w#LZ_m>*_e# u_K@>x?q%iJPV=Y|jcDJTz["|(Ě [UP"?kvgƯNfg>AyQua\wpXAF3j^*=:,~&X词XKk&_*ox7'^"Q&w#o$G7ɍщE *y>>LpP(n@&ndV%3f(D*,,3y['N%)tQśƇkdm_̗lNVzZf,]9=2A|Jīw'Ru?~_ w ޻^QD p7HV a3GQ" e {]R6uh? f;u+ڐd~ӈj*6KHAS4B<#ǕG̾8ql\%čcX7B4`u!@uPI Ԁ+覥gq9uDTkVjYC*FJc.1άA,Aڪ#j`XPg_wq_:!hwѷ5 6Tԭ`3-W=$to( YLO%krCpMynn# cddl_&7r=!z ~oL~MO4'ԊVmh_L(SN#"N?`ZH4uTz6l?n~e(#jK~ sӆX-Ս*)XːڛIRXQ4_"VZ-6pöD*ۇh\Ax%|zq$[53B̺JD ysHmjo'/t64oЏ40+)DF%Z )gآ*L-ztJ"&"lsTQy' C)n~q  <eMT_ka^z4#7Aȡ! b0Ek $cD^F.هg\`DG$,i(V+1g$;_GKzDeS4E,Yƾ0re9 @rEOBԓ?`=3|׊*+hO^N"E$Nu\DߐwAb>W!1¦Wff^؛hILO[΍rk4Pl ;N'2 t;c۽Z>$B2 :c"XG&qbܬb ꊜ,YeJ^V b0QڑէFܭ'O1%|-iCA$ J B};ٺ{7 W h ;SKM *u0!@ËV;{fp]n0-n@oÊ㎌E_(& I6XVCDZqw⪼wHhUiXAׄ9ZT.WGؗO#}ExDO#qڦ y  ׍ .FNff O9Ho98.3O2<.|Mdׄ7Ea]ai)p0j Yf6N[kӋ|Cg}etr[ut)kYBpg3Bcxcnz$=lZ¨]luKTJ΂V A5j闽ċցt%WLIFD B  h׃[-eћ:=qE*23Lw';E) k4>܅z5ȼ3hY>,.t 0)뿹~܅֟5Z|.L Vs-0YNvRËÙ7+TW u-QPB~Ox@ȱ7A#zUV7UjHtRs6>fQz1s-&d“ y| I5o(<"c_=jW^}! qI-7<J,_kd.׻;tuukTQ3b0Z3G0Ƕ[m\T!-9u c\,@jDN ]F  Y!ަ[/nNj.W{mS=%; t{6PKYOXB]ehzL[i!g`plZM!"0)s)1))?DwtkKIuKCDPy?%#K:I͵%O)+"_ C[xcl9(l;@ʟKQsAZH^lX7 Hx7\+"w缧?'/ψ>KO =e鳪s'0p ZE2gIT՘o\u9e8k 'mP+[Zx}wG f7nӬ3tf5-]obc*qAYRx DZ :9UNlQxwjk*(/E'{󥕿!O%ԚW$ƨiuDi>= ITP ˭ -=c |sm[ Y& yuA}{1Ur"lRv=/R\D\x6ĵpR9t0e jbhgѯ_E4chx4G_?ADZS/(f=NXo=K9OGN{hj'<;qAfk2 ʯv7מҥ,M|0[ 9+p2Y߯3xa{jhso*xf\)EUXUIutǂޡtYUk4VRkаΙo<+Ù6H^HǷG'nJOt$Bx$DkcPNC w E +''v VwwJrV2 + _e#= 9$wlC5{ _Rb1P`"C+n&3#fL*g;#Z2^0Z<\piOcбCB4Mp-z~Zcdʙ^v5r5c Fj̸oEr ,]4h?wV(ŵ=i';;/$_[V͑LIzU_,pyPgWXq}XP*ptDb H{AST}]C JrQyQ0tl?~צJ$9p-Үsx-{ww7tx/[k~;#=K:J#`,hʎl?&RT^e1$tM}` FЩb'Qm 10SL`} pR0,Xe V$mэX~q0"o{B&h:.Y& 쥒R3on[m6Iռk)+8`jw5.7Hegx.TV]HN*l jX^ZPL:vpȝ_B7 1WjMO <Mg\*yr:+|]mDKĘ4%"2 Whź$ͅ@^MVr*ک/ɛI3 91'Ho0!tlˉ.v8hӾ]b)ш-O(^|Ҭ1CՓcB(d2c tgP*-(۹RT݊Xqg{{S叽ɣoqOwX xEp{Hm zB񩿸(|RbDÅX C&T)YĐlc2k6"h>%n1iG0愣~f n jyD¼[ꏃݾ\3hM#&Ae`h%U/qƑ(RXsg*W+ȉY8R{X Dā"s*BL#@uv[8.K ٠Fׅ"wB">@qI~!4ߙ 1G $G $K 3 ẘ>NC] do?ol4=.$ք ;)wQjUpU9 jS`* wwSIWd6ahMU/@B9 G[IAY{0.ʟpF1.( )ڑ? VI)֔H} WBtJP@P(&^B ;I*!iٵ~ Q=ơ^L fc0INŢdZ}º7=nE9bd篕Z/cAVqAjh$;H~y7n/,Fh&OriA=3*x8=LdT2*4jhp²«m&3dMK2cݎr?QV}:?I(`q΂2VN/XjQ%XL3jE~ͫn%8T #O+,M"8ˠ$eHh(% }`R"#[Ap1mv&5v'#?'"!\J4xD @<۩Ju)yg!xKx͙?QhFЀ_3Yd.?E\fJ׸:O@П5DzVD'~y!r]'.nװK6)N^<+ ix܄- Œ#se,bĸʻZ}^9Kaޔ(JۻΕL:Gp\fPH k#3v28ZDすmYc\BV~kvbJoޯ[ .y^6(#3ΜN OQ?Br(d1/RFI7I_Bg.X0"K]7!sgMan cbX8{eij]El䉦^a]0ʤ?pVfZó̹$ёd7E"QmLmSs:c8_M@X%>jeȈ+v).JA<0* E^^|0[n%\N>b 1hTwu-?_ h"~*L)O&p-t/ E_𬑛:=Y#7S%O4t{ ¶;A/N lap}wGkt@6#R|PrZ.=F(rV9o`j\8 ܲ? AQ?UDO=%yh7  F[>7Ki?bg??K|\?$30W^ xfP]*x}*Ǝ+ur︃#@l!4 d2CѬzOg%0S#<.=JuMr#jޜ7F_/Ug\131̬:n_<|MEmUg.Ȧcct<5`ufzpIf)Wh<#QZBon9W3vl3%e%yx 2U#^()5Ö|f"ш"vSd".'*|gv{3U 81#8#I+]$RŨ8H`e뻮+y'Hgdh!>3dՇ.Lvأu-: V8DM9n+JApofct$ŊȢPh]J'-L {0_yQnyJ<޼MSeYAxe8QUg5xnd>{B>T(h9aj,xG4-ĴMqA۰y~jO Þ}Efel~1($xt i.Z]ɅQOm8wY ǯM y4}ҪNY9('j 25a r矴)y;$$D)+8cd4~h5UEPuua8X;Wc鴤3rc˷6 */ۭ`K\6wQ8uιy>ghiO^xUWVFoh͉ٻ"R kz/b ﰵm* 2t 7}iѸȮVM܃  1g S(,A0Ctj[z&uƋT244wsdǛ_4jՏd()L*KUɹ>~lU?L`l<]-+k_ifwME:ɗb/=&]hϢT6Uhq5(J>xc-0s n"iqjˊ/6{U כVbvKLBB8˩y(vyTsQNۊ3bZa!R|81g1PS!S?Hiu9?heI9VQ#},?$#Qm 1IgtuW hj4Qo dUYgr4eѸAxD_1p-hNjZx()Uz,n53N I"89/Y!k~1b f,# jK(8pg.S,w,dp+s6tZj |OVJ'>(;4 EOZ5dӢف(]HjoӨt½% @ƭv 6ɪ_!@R=xZIDɪ-&[~@Ԝk*@֬eA7.%jIl'=$XMєP.TwOvk\ѕu+˓s88J#nNME5 )1=O@ڲ>|.xCvRGJ֞ݞ\+~K*%RPt0'Bf$tm{y's1|M+k׋i;Yc.$顾6t=$ 1I4څPvaGuڄuw9؛1[i(7T) j%fz(:jmf_ F>=5c)1f4Ri@Ffxg6L\F |4:/X9D8_I K]6YFE%U+Q)j#IVQ;.n'}*jBNŊJNԭzs>2;[[B]8{ \NGh~i-G3bc Y"/V;/& ]I٢e' Rg1 [r;&9Z؊[Ya0BXL&fIv6P:O(mzCZ|nݮήSWWo~!xkUL-Кry y{1GA;'4l!26Ghjz*.:rOcτ%ȹ H*w5-9ؙE2›(p7 fґ [QP+AE4euz(dEX!HSKkQNw%5d @q 5:d%o?J>leN,ۚfR#QM >ei_lna@@}yQ} ~.ӯ^ub&\*M^t?FWӋŠ}^3-yB-[ }K"V zqԒ>'P8L8QH"jY`6V[Lz(@V:Z|B_y{a[  4yn`_ 4F.?H'|Z 8t@=v(·陟/+6r6iZܹ Hȶ3WqX (W? ozF:Bm}Œl)sU,in9ZY^ȳ,bvZ@gY`ïT5%)ĜvIwC1i6om r* [;?2pWn(lY(LX;U7XJhl:(ߪyaAqޯ% >=ʸOX$O 9eʋnyΆ'^*ji}OYG/_ \eiKb(TR 1!7'l-ꦡMٍRSkQ95]eGl(q̒vAaXUEG]?h4,>ɢZ' HdOߕ`&7 AB!ň~ԑО'6$5 OrpCtO,sr*.gȨn/'[$EY wl X܌l1sv*;diZ!O Q{,g EǬqF#ǂ88Vx'd !Q3J:nKbiZbfn']1q&ƣdDz9UNAo7«>f t%re6>J 3%ޕ/v s;!2 77qX ]` ] r[x1ZQۗ,b3'qc oo>l֌o΍*.UIsgOj~lz3qEU%w$n[ >`w}kXcTc+H )y!@ǜ5Iwb֦!}_p܊E ӵ=/l: ?}LaW*g3Xk&pVt`s./Ңh##!Su0mXsiϊ.#b 0_ߎuԽDic>@sZ,&$*_zmy ǖ.g(R%=q$OёJzl9P[Zkm A |it'b,&TYQ1ĩ.ǖ~ jhj2gO05@Y}kkN?Y|0uD+UO\Qg^x[vknw֜, NC -Pŵ`#DNm{Eyػ4 KXdY%rg@u$&yr2xdZ 4R}m5 v`Ê١#޾O7[4F<^lWv|@\A10WOzWv,ӏWzRNP [x.$UǤГm$$XM|4]=<FΉ8+JrW-kg! Z&$2X#V}Kլ"@A]NYz*G?d{ɫ)1o.O{uߺ=&j9/zaNNqLlÊm±**wevU&O &T5Oj*C8xb9VIgFv6yGoAc}/E D)w@+lqn$}ikr:>g3'^޷mђ) If?6 Yю oٰ@%{DM]|%7׺*]6:D(m+s{ۉ8n$Up8췼8?4ɾNňΊLc|bAm| 2$]s] $UTʹϴtw ,x*R3-!*Fb',Ni]S%龸z =rwQہ5t7?2Ʋ Zh`9;8ڔ[9d/gn(`<#0KzAIZFMߣ-]5_fbۙ~Ok, >s(G3_%3gtU];6DW:no}v4+{=-OD<ʪAC=I 70I9K zN|=ݝݶ ia?Y XK-UwSDK \ǘ#LZmW:MuwPu#=?=&|HrH'٫i7~ApcOi{ݛABA#!6^("%;N'GQgn?NӐ5&rR7ל #8@kuMطX{&Uȯoj` c`'"a/"x֦ +B0=d㵤KRZ0D)8z)5-t |on!d]!crϦ^vAJRy!挠d"SfJ|u?1F~7+S܎U@={ P>p jjxzmG[6dY|/R$uA9D9즨 Ėa/Vz{oDUOvdsK. t?bHtDH"%ф&^D3.?!3~9H ڏ;*SKQ)-bKjZN¸5\t tQ:N麤tؾoq4w^1$,{5].՘I(˨?yZچj_#2}|݊WmxzU[PE=kY_]qoӨfNi g樽z.(4[ql3+' ԑݏh}JYSvS`} n5̞. lB =,g{dDogg 'Cd/r[ i,^{RinrO!+\@5 2 GvF,N1B&BD}_S|9qT]._ld҈-bP m3s*U+8m~gf"yx_S e:(*\: *ev00 E:9A-E>GF(Rb8.~tLĮNӞw񹂩>x*vN5~b 3=Mד [=ШtBi۩6\| `ѓn*BtO B]i @R>gEzzl#;nbuFQ%'Pr@XN<]6<C(~e4!̰G쪑g|HQ$y/z u(wmJZYA!82YsQ%t5^N8!"T7eU#|_ڹ vh3h[c~T##@볋;w՞3*I!t}-Nܖŗ@ir6L`Bm'yQ}*S[1X%'QStd_Td[ZJ;p+xqGCD Z%R+4u ~j6F>C#yyEqPRC@I:q(EZB$w?1Ib*SN$Ԋ*<-a#?r"_AJjq R$4z? DPGZ48T*X)pMm 0 ƶrAW֫z7pZ먐" qҸ| DTI45-x1wՌ2.0|LYGpfS>0Ģ5c$Z6i;x?שa[ 4fCl_ӪZѿHxB5J:>Ps"1v}%F!3eY~Z|Sn8 L]7Ѷ1[ d#a떉q ԇ ڦM 3ʎs=+k'M@P.~QhmOH RX^FU&Donn9v9fh|.bG ijPňִbV/U86`z 6ز^jVv S 8'AFN]mJO!3=+*n7~c*cL"{AֹNV2?}7%CYN/֦j88aÄå]~#Gr:׿Uv;v[tø:7~;wuZ~?|:rTC֝Z\^dHie?/Pr%Hm$"vFSR*'4"x*K==3-?1!z'qQڗMAYu_8)H!$p" 6 n$}c1AWKkσSa<{Nyz~[*R$U2 E">^q~lzrU d-SܫlQJ)G&0ƩH]Ge{|5QRD^8bY<\340/.š`IE_mξr` TTUxί "pgv̭>P糹$KFxtGF]֙ʽ-PRdr`ѡ9Y(6uԞz/MhpwEiHck MRz3jU6˿mdU`YA7y̹RE]:'~`REt&OЗ5]ND~ɚBo@^LAߕ%qDJY^Q66ҫIXmTLԝhA.;Jɴǎ'bg;X_a}n0bE( IJPϰ;i:nEŧ((豲Xe kѴXu'fa2.N Z9;)%&iRg5Q OpDg@^6ZW}wR7,ڳ `:蟝KzPbqlɅY1ퟏSG2qYJ :v4*l#}x`kzg]hG<*X|14(sٍ F 'mkCyFxgaD\ kE-FŠncw;Xk4Hy+8Fǯ_# $ejL~TĦdu~&NDUYJ8B;\X ԉ:Ro{=YriUR1Oheѭl̑5rJ{?([|6x[sjvfY!`/;QTVDvι c} |VѤCbd=GaU^!BK? ƮS 9$(ڮ8sϵ=w^8Ic!U(p֔- >OkwBUsSSa^U~w#u@k51ɘH)dNSN Q;|3 (΅Lo)uצ7 ҆ wQb./SL~|qqG`PG?:|EHzP&3@i}&/tgWΦEX07 y/laLXOUIblnBw#CJ9 !:2A GwuuWW=mn-|p4UP @Up8rR3+\ljqF܃2oM \MV~d~Zu&'XqԈe6~,i-agvhȎ$&ӕG|U9`́~6κ QoS-N^I6R0Y(]\%r B]V8+]u7/1OO̩uq5~@2k,悆h.%"3$h#ىQ57JD%^W*, 3ɧ"fEp!:c-8퐇~d󁯖-Y*ɞ1<4%GvsWz̜W~avXοLl)U0A|(Be旪jt8^QwQ@!d)DZޡ|#Vi{v*/'Tn_{6<)SVyW׋ܧ /$x7A T U'e̜L0IщUOMCq עIz1'b?ۏK8ŀ(# ءzCRT;\ʃ"*upi_]aH$FDvi'1huaG\QCWLdF%66;+ #.G _` p>f#0عlhw c®MRp?̋ t:@]'#ߟfuUu?g+88@mę˽ x3HP z.hğIǒQ[5xg0w8'OV/rs?֕>UhN.f}qWގ+%_2ũa}d!pSs䅏}B->}2UcXۖCew$1&/jēThPϰN%GAG"3;23_ƩsS/C%=4F^g7i^XTdx(ϭ ䷉7=!ipg/>q'c_? ^7e!ҸNзW,>2u1SvuDՀ;xT|Ss_Ou{'Z(&wFbɠ@ZKOBDD,xӬj1@e`7{*Zs'έ}<;*7F4mgb;kHѩn1& }/ir(681D"-AD/L]Kf35j{t8d0Q 1¼Jԉme?}og/X q+]N]|ݥ+%-apYO]:@$!b(2H,AP>X҈(?o-iXYjpIU>;%nDOpѣ`ڣegrfoTA@'d5n?LZ_f,;W=7.ĜnmLǴ:^SpkHq`6@I0g8(}uBψ{wN?XKF§9^X؁ #d WZeCqo HN<1=kAaUmqL(k!9OvEA^aZ6crkv(0\kY5R 4]{>*\q8T$9dtvJkGfD?qd%^f؎Q;RDCqҞVsBUݞs ܯ@KQ⣗7a pECe<\4a}F(3ù,WǝA"j(HO\xMٕWGʶ4ѿEndib\\kH|Br5ܾ7+$-~BϟRibiU[ )+op ^ei%N=[E@NJD,<$1hF倔1yYl-Zv[.t?o.T ]_Տñrw{.@_CRlCZ=7߇+w }"ä~|R ,9-h֒>wllu zyEl96k\MsR>kKjJL A< :$ Ik70@?a>b!a5/:=*F`71wGVe(02 ԔLlMx~VD~9TظiU^u7MJNQXg㖭o $cH݊AJW9\M(7Y:}A, ݺ{$/ARQ:ge'GV?Q= pW0&σ xHJ;VYb5SU.^et[b5?#ܲ!݅rp^T!ge!gh-9Mn^rG8Y`hztc &e#૫S(OuyN]K{7=d}+T~/Fjfr9v6&HqHC4r&Wן3{H+_1t|f^$#=o[07~]d ipoK FD^w2p׮i>Jھ yhZ݋JU!9)[)HjQZeD4l3e<^.+L&Ƴ|7HZbBr府ot$嬦fcM-fYx}5E8>!!O&YkBafcZ>LĠv;&U-yk!3䬶b[>vH u{ 1hlw=_7ˠ?>PK#5\OOۏyP oeH&}?Inw =/([żuGxvXFC?jz ՍG7崢[ j7ҿIx0_fq+z95TH.`X$ܤ!.[sJu.Qx}A|x^Ȇp2v{IDSJ-ޤ{f#S3]2J+x޽}4}Te™?+,”j}T\KگT𦯶U OA+?9);;}›ׂ]{[@, p"P'$X{WF *S>!Zd}ur+^9j?66]qPH=9h)C-ۨYw 4\>.bE9U dx"oeZdKs$#|$y%J}c+InH+UsJ y6 1%8bGGU38¾]R_HRSg|+ia"@aĘqP#dWyErp7*6݄!鲋9P: -[^zߺيJ5Ű$C96!}d.,Z`=J#T{tsB$2 }ހcs"JyFCET媉? -O _dw0ތmo+YDG y9{J[7}6]n6.6(}Φ6>9.S-a\_㉥R{"K5蚾-Х͊)oli$Ҧgo}YTGa- .ޖl5b:Q},ߝ5[;9U=Gj8f3eh$ ؿrںBِ 10<5u^qn=LGX' +h?[ CHIW^@]zt|6ih/eNccWR}3*]n }W9w^ 6z1p(fd)#޺r;pCƏp1A[}Y^Ј@껎밌/XE:> Uc'Asĵ_FJ4ỹ#c$ױ TnW^Rʅn*u`Ƕ1yPg~[p,>'GZ3t~t86bMu Vݺ`C|9($d)0@ +OObr7}ϊz99ubzmյZR/<.!\g' āsY|+T%?ƧǍq/$i+0XQHԠFcqPZ4˿RLЛK 1z/pW,Mws`<1c"N'V{`>tQw6Q=%n1yWe3x`E309,b(JӢh8ѧmYckՐ  8) H>2h-tQ]'؞:_xne +ot}TB~5Q1,\VZ>77k?m( 髁:}n%߳5J#Ua 0}!FD^w^G@lKQ@$HuPdllˆx0F"e̩:lEfbJ8`|pjǀqt~?3A^& _L_Rt ZP9VԍȞ,)>w AX> HK8FN0q_l];ǣ$5 ǞNųA'[Ő2YBr5XazKgl#=袐%nHxn淚dt(64Hո1J2ESafh:θGrvKp|m5`L u]CedĽHP>EhHucf΃A؀5)][)Cʵm~ƆCDItf.%P^֒O*մK05Mf@z)h#r8iR%r6'OaSV9MPN ob3)NIةJRc% ;KpN-0t., ٵa$AIj̙K6 `o+ 2*?%E"^3U>n7aK.a-de6he5]7 2;{Ǿ|zf A0 >$Wm\ik0RX&ORt .O A#*nZ+܌Jt_Q) kLXzamu U(c*R?M IwžСfxmxNמuEtGq6d񫓾W4S X7!XS[^&ϵ-$u䱆0OT̢TQ#MM?Ḽ t[H:R\^2M:v\tNTHZ4Dh)+Salr[#D*ݑ3/QiZ)XwWj7#jY>&WbLY\Io is36H{b'4b>@{Ӏ%6N`st`>Hc fKMH~K7yδ]'ZqbeIVۜ8[`~S]d.YGO8Sܙ'Q>sM/j]!x7 5i͋v5Δ߮t^(C~i%EMO)frG,fDvDĀ܊:x=pӷ^0\+nW#'sa.z^rsX2#bFso<_;ֲ?Y{L. 4BT?<Œha;/|f^8ׁFO0chR&T}pU R6ͯvufT_416XwC VX;I[l>DͶlWjۯ׫-bLSxCﻫ|ZD7 R Ǚa8+)#V*jCbd>tch9i0(ؒ7?7nR&*}L81+kݘo=zUaJ!UdMՠ. b}u]c_k :@*\xDwn}\$uud*r29f63v~2,?IoBt2l"y/{ zNۣT=iSIP\:\°9ž)m] a暙= ]S3? l'"]Qt O*6dwk xfΜ5BUv&HicnV Bpyo/utils/E-PyoIcon.ico0000644000175000017500000015077412652732202014272 0ustar tiagotiago V00 h&L  (  hPNG  IHDR\rf IDATx]`UE֞H"E,꺫keW]**JE, v.{[{ {dr_ 9sfܹ9}PHM+|>fRs P P`P5d6߯222Χ69߄%+&K} N֪ nl1++h)$R\Ay K;i`Ʀq)wuXꁅ@!L,e"iWY|Z~ 5k֨E~Pѽ~CR5ZEM!t2$r)P232!TT~Aо*))Q[m}+ Z֭?337@XQPl ¢5'(%= z EBLȚ>6l駟C~,Lr K+^|f֯o_SS#nW_~Q~6ܶ f2 gd@|~ܹSM{^zҥ3~Ԗ[nab +Ȅ: 2Ἐ iT%MUH7YT}nnhPٌ_)p0Xʪ_jW^Vv]{^t9ˮ;7j gϭMD:5Xh22ydꮌI@$vZLw+n쳣q$ Қŋ꛾>$w7~׻ -oO$81±@`-Ҭӻݐ^}}G"UUU-//_/[!4}w?yKuazAj!TPLA a%- 0Ri@JӪMUNN<ȫk~ݢ{㍷CP7[=xQP(ciQxxj^@- a OMZjֽRЀ'\~|&~ݔ9,WPB)&VB"|fcȈ';w`wZ>oÙ hl( ciBH E`  l|UhCO>z;/Y3csrYTTGP]])>0l1H_EwnF@:#%J #/:3s3 a>Ln^ ;e j<ND@^@t`&('Lh? ߻$ |JǖIY >c v"WPnV C%( |x^U#qelS\ &@~`eh5\P[StNN;uGqh1Gӧw dFMJ`3hf*ZYh^Cf|kS~QOnWXxP~~f>U# D%M`$;JqJPC`pd-~6ȏBӛT>\XTО{'Gv>LA_k& $MyZ#@Br>[gesE/ p}wݫ~> Nh׮]o=Z*?­drLKj%ϩ# Y%f3Gy_,@=^<?D ZH& 2{1RZxPCWUKnjgywC/Zt?#sHX+*g_^״U{"%<" mA3W?;39LjjB)I --b9gϪgtKǟj岓 ߆'AhVRIi)(O&+֮]4Һa]Ιg =c2;th1 iV=J>|n͵z{(jT,`D5C^/ernҠ7 #IgX@rQD- \v{UWٶӃ 0FN3lqN |5vL8onW^z'def` l5‚8>]#0г*Ux.侉/+ˮغGT5hЩ; ,۲ h>?kǟ̘qu' Y%K zNeeX^MW){@E7Ҳo0N0G=g~; ]8AakuB[sٌ+pʊKJNw_}-Dx+[)ӭ:72I - DA醲7L~OL2EPf1f9YJ46r7ڔpC?:ZN)kfϞ[j %GC VVF~Fz٘J_=|ӳ{צ_p}Bm+G"=Uی Ϲe|x .Z۷/EEExi෌fjlMkVyᜓO:۩ӦdufI*-V/o)>?BlS‹k >>4@xܽzБ6-D)Â38ثXrU;w|ʔ #GA5eg Zhv?}Byee3g^S}ճ:W_ֱc #q5= ߖlJfbƏ׭?y啗eߩjmoR,B}3>a5(Gl|дߒku }uu `Ðƌdڴ)(@ڀxK iu懂Ub 4S]\=kMYRfu0rH dÂDX5֬^jR~nᆫgj sU*_AaaH:lL`ةX׾ z yJIDG5afu'Naw9]e5V#>5@W\[}E3|prpzg{]ZÇLC%B@8^r=}g_CIߣFxUkgyI+yCK:vnxՐ2nK6ý`Wͨ8,wgbxPKZ[Ueerp!eV\کSDoMً飚Yg `0ᛵkV 8}Ѐou5(9/欒VZwsʊp#$$Di~/f9N}$bw?;nʸ>B{ rpX5Mޜw۝/-RE-wgҼAW<w=Ĺ\NaЏote\WUx7 󎹵84rY68 @OKf!ctbᰈ'diނ䔕U⾆xcE_^@6Q88H)Т^Ei~H]3_~ '+-+J~(i/n[Tulը2QI^ + kVSN=n1GUazVZz}?;Ӽ\~[}]b?)*)JN1s0Ʀ}np|Q+W#zPS)z~% cT6/4hX?\>P~a[&2m:a K/w+j!VdnDgp%f01;t[ne.]7{S|<Noh/5L;]]kiC=}?j+Q`\M~]z{I+zvӃA \e9o-jl pU)g*>-GP<;cZ4.@Yň+wk `KU81%%Ǟ &<6;`o|}atn]y䑇 `ly"|XAj?2 ,ߜx:o1J@-6| UWUq&6pUN ad?3FVz<€bWŨif["*21DpK/>u׿16zYzѦZ,F"Ӧ]߶?K /V$vK*=;@L l:cb`? 89vn ?Dn;v W)=ג{:J !ˡn(; {gs PDӍF7j^ 'vjWzjK.XW^%?_- trͮt_ma&~U?}PoAs &DaOߟ3\XX$_gIKEmM?$]^#կXf͚9s jYZPėT\ӧOO>v1)0yՒ%f}};R_fiu%sykUl_B_x~9Жk@761Z^|ްacjK0_m #5=v-`#1+۩}[= UH~{o 5p3cseWV<Աd,n $4sZQ \ T@Gk_lc4 )[T]zJ:v[^Q%_+WItW0@?h%Snj@cM6V$U[ 8'sI *u 2\=;m%K@Z1nܹjkСhLs@l4 K䟭f8f5KRH/DhWXx-V/+e0SXG?xAԵCqNj0 ?Ww5:K ޜSAZڤ Y̢&7Bp3+D > 1h_ d8`LQI%c%ґJ TJ:utoeh] @۲sϞ7Ҿ; L@ @z'Hk @3Hw4De\p*//`N8ehL@\?SNB͸*^ ~+ eU"m- fg^*8?>VW9D4JWXi՟im61q_€]7_~塹6H,M;ib뢾y흋w8 3 +=gtnJ--c ?9 X zߖ2ʫ`Y>Jޒzl}K|̾+Ԫ+-!=h*PHxX%Oq1m&+15gϾMQ;n?d">U=KJWV?=GM%$-ӎ# q;QSVǴ Vagm ׏9SOIoiܩLaV0R8 V2Ҧa Kb7|JSٴkRFcЌBB%K=ؓۼֻUX2Ԁ`@Z剙VՓO>]II@(rG:˲dJޘ.F2'N*&i6#>f2 W]u=L@Wg^{ fޱ^w#_' ' G>s֬9 cxt_W@ڕ(x)QVRt/m% c%%C;U:Z>C0!- n ?8ǟS\\|"&0ȃ>c!$Xq&p5J#Ѽ"YH&N"0^ @[UY9|M2A^'n YsܦJBdIQnYHŴOX; sbX|f8㤍 nNeUɧ_Ub N. n- .*-dI檿?jf:~ቧ &;xҖ8OZfq[[1_ar_/6H5n/`ߊVqޟMVX '^~Ce;eQcgmݰQ^g@I>Dɒ%TM,p<ʕz豜ӹ@ߣMc?&P ™V, m3v`SH!ϟ1 l@&V%$_4h„-];_fhn;^$#a6] fbKxl开|邽^zZ [cjQh&$~w?dd_/_pҽ"͊-Lo x4mfJg;R~L3E_tIOH%ٺ17vOx"w=["8/V[p(~RE!+̦~6~&~f5uK:mA7if/dj鯿C 7Gs%۪x*S$x^|t/n3a^6? =7mh keȱsԋ/ H" &OO>;.imWŴ=4nM3[!4bLh/n?m]h^&v2< ݴͰV`ip}QnŮm5 G^@ԩA}.z;+أ*KJEi1ittK~l%g뎔f6f-qL$Z4. 3uk 3g~p7n@w`ZdnmNOeӲ,w-|N[~ mW¼lINj_$^<~/^g>Ch䷍Mڼml:dQp.2$e|cI0s+rxzxlz<~Gܴg~my f7-◴oXd%mɋI3ݱMvltBWs3#4na?JK?3-戒\JzJeWf~m /43[i30-[؉Kxl3x[(?@a|`ο/:՗ ZTTR\G,_ܴ/'nnGL&̢T`|\ݢFwh.jq|%r") nY|fat~; 'p-If\3Hiİی+hfx[p;r5torFՙwKyffeM3ی'Dm8y^@atI'፱0;mP Mv $~z_XL;=8 U+No6+ASI۶'7mӖpI~15i+4g4c{n#űyl4=׏/ }.zh2@a)pˤg+,F]L ;/ÅǴ%^:m ^$=3\ҲiHp6xIx*mC*l&iV{xq(HU^Y0O -=XZZZ_srs @1n':Ä׌-AҖ촄h$L^I6v>$ܤf ~Wq9,@~'O{cqo A|V;bƏfa_^I^~/~G"?'q//nMɯ vdlI+(ΞQ woP6l(m-Y[SLC+az鯿nX6T&%[>\c+ 7!~#t/یO7A+|v:my+4Rʹ%i&qMē03Ŷae'_hLZV^ooueBWUW9Pru{Uǎ%yz{\t֡0@z5T 7;~|*z!˗]be7H<p%EX0ґ0yN&n~ 7y&iFH?ŊHKHB<43v4yMh 7yuUV~q wZ MzPe_V˖-G9 b _EK̴v_ԶVeeͷU׬U)B`~ޫ.+֯o y` D 5GIH<0M[ǤIm Wl0hnfri?EK^Q9AIfmF r ،/n7/dlOAlO$[pI5LwG !-;Z: ;ԕ3.} ?PFjS_eWாLwQee0f7Fuhu%j?;n Z~\d Zy/']8̈́KYv;r״qK —8bG*L<&Mc H 7Kn&=7LO5b.t<½x"$xl;Ʃ UVSN:A]~@5\(UUeCB25i4b*—Q(YWTƎT5Zf:8V^^μ;^W?&=U- ֽ{?;oIrjz3#10喛q(Z P$^̏/ 3-cYɚ5kj10_v3i͝|A. hvJ1fėp &8#M-noH0L_lM ibK^oڶhF%Ŏ/a|iS@=_`fj$)]^|ͺeW~oVoBd*>i'fG)P2ݧ`=۳{@ڢUбcno5M>/@|I5my.++mikVLіJkfr45zΟ*>߉?_3MRcO?m'8nn*ZC)su_3#egBwү+WMFzRԅv* YP( JP?i\ шh*f @V\{jij7KW\v:#+YT9oƲ_E4'gBt!t`M׏Y&*0 4$}Gws2 (ΖzLrTbl]F \~9,KВjIl%Bd>k~GWB>|}!]UO2ҝ_tM|@ҘI+x2$q5ߌkG?)M~V:IS{#mZI6{-??n0gS'Wq_Cդ*ȴX^̿% c}ÏjqzO&r;Xqs[03+Vr0yFYQZYB`jOmr]b%bL&RBfeVC9/ f)j:X  ]c M#e=ʟ/a?D 2Jhn-t+ԡ8 y(3=yϾa6I )*\{MAnJ@AAʒ~N+ȏoW<6|&?'vr %-?i4 4_l4FCus$&~5f9hN>Ƌ sDhD#ߛ ݷtj O@_:`0e5.&`S<{Ez_$XL|k,L쪜l|z];0vf$-!4I&`Y1k-%  b|lxHΊͬ0,[mS-x?COUիWq, hSxΠ#>^E`ά?? /,ogDpG{l0|o TH(`9 f̒- h2QK@@( # Cc7+ fE_ % [O7㒟4q-ϒ4/4DM^-}oȯG?ܩg_=l}/ϙgnU;8du\oF oÈ~9np5u#_ۏƥ J}YH=SIa~⟴iX6prOJ/ML[FɊ")nV". 7L?iF~6Ё3\Y,1OlF0 @05wt-X^T W% ~ [~i16hש==ύ>/ _!v:z ӣP1/f1p 0O " ?N+^IVnB} {U Yʪ~ k6-GfL7/& 1M> wmô~1]3~ɗؤј~kGr׏Q磂LqI;}wkwI7E/qH'Xr1nG ^n3KgW]+ȇc@annNP ,fT׬ԩc5T*>H7Ըq[T$ncG?i^0 IDATK\YYθtWa"0ai3^v328d5?z.sc/,X|!4Vrd(\c5ђ^?6v 6b`2bs<44׃i4vF:4J(1@ktiA2`Ff\mGa4b#Bwv9 ʹm3̤1]O ̟CW}},/FwL?Zo^Dz*uCˢ}/͛{]2~'_Pg~Z`w@$k0`- eaӺ`|h݇0#ݱK#0l_L5ݬ)0tmFi M^ 8~ m3tG3y̩ƆHj?K:_|UPyT ȡg8-g9s=˔a 'j3v/;j;jn og@`FgA#KiŦa1Di6O~ Z4-f*mxK3QЖ.a&xlIϥ`a۶64xIcm&yb-,GyO,$ J.=k5pO-?uM.6jzÏtq;o %ϛ|iY:-?=M ~}v& OYۼzU9oX/JKیlMF -n :mk;DW4ė4t$&Ϡ_h^B@hb [c^^43/XۦLV$s\|`o>}/a4~u-(2!ǡ>+If$f^Q~j-E7 ȐΩ$z1 YQ4"xg2v/n#<6!Op}N4pG^n&itm!q&O$#a+?׼؈3Yo)~[!|;e elFMIꖟwF]gsy r1Б'}pO@_3 sFskҿ៴.V@P6Wp0hM$?y"% gnn_x&qfOl۶%rL-?o]xa8'X"Eϑ}|o?ӧA ?qBgO0VɆ aMaoߊ.]:'4mW2?mc{īP_&G)?u~F>)kl3[w_1, @@㠸 +BJ.iD.kT~xAwH?{{eleKM?RyH~ךG1fz75ǿ~}zZ͖M҇p}9<DM| p; x3P:tYGaPxPրV Y2aE8Be39/ҙ.M[xMxNWh^#M∛~nK%m>ƌcx6 ܠÃ9~[~PG[n: DTT\2a?[ _{o& tM3}F oJ<9Ld/իSFWh}(gަϸAL5 m!3WMWғ8pFY-t/ᤉ[l4#n3tK>.nWo%\Ha?WoK-.ZO7P\~8<;?Ae^ϖ?\^|% ~vOj_͵u+=!+wߺwfтs >7hF*Y6 M-4I-~ [H? Hv$ZhtPo>~?_ORqvڟD/ j?Ҙ{>D81n4#WYV߲GLN@cz 30T:w,lU2 j%fDyHi =1-iGh0#cOнl i-~. 8Dg~ 'w䂙18ݫn Tys~ mlKj[6UϞ[k[,n !z pmzea6~ _V O8fqS^٦Hn+ciF㑖]̸[Lͼ.$Ӄko|'߻gx晧Q=+K;nC9.d0?oh,$RͤlZ"~`JVm#{g~'ͅ29^ۏ~>6%XT^\ô1s3Y HǙ$yϯ<`I܋6 3% aO خ t9u ::Cx¦FnL6KbG Ӧ[+~~VJf?Kgc?Z~$[G~~cG NgN9)ǏYy'x*0&0g5!ש3շ /Ovw  ᙀzc|!WB) ~pI]n|4&)-iɫ4iH>" n-oҼBgv;<5jXS<?oMHw<ϣ) 5{^k|o8lNoWjz5Uva !w_2a >$ɠSZemm7L۶M>;~&~&it?n>LˡԽ i#"a~n P՞~ZF&5U=s ~= OO8<-4~|CNȻ&,ónmUmM #GڄK-3O0 |G$ϚPlc#hhs γOz򉉍jg- zc79? pK.H?{MaQ;ݎ"̴ 3#qa!>^m]bK?ҘƸԼ360?j$Hk ~W'zhtsny_ijqh ~gk5WMbinת=[vN;``-{aߣ`{h:w Dc ", ;\b-44|n$7%nӘcM/b3Mq9lpTe-A}t5<#]},F?i'~pv?7챵l/X{MtuͨϦK /;hf}0I@>sם~^bRIҌidzv"Nt Imџʟ7yi /Mso#xgn9ӰԓNڏclF{yyգ?@eEo5 iO:|OogKzȣG66:j<2h3Ƭ^/+\|;ZGf\D#=ޟS)0qӦ~,E>' >n b$L@= '9):BG7Ö-@X S޽@gWIQjBpV9qhQې8oXxm>Ӷݑ̓5m[0͸69׿sTgȧ9(]_S}NSȺ[~ܻw C<Apg{z'[_>k;eܹSNUU5zpЊ!4uםvyOq{Ct`X gLoM[336W6ĘtiLׁni0L+9H/YC99W7i !887TO(P Ճ?S񀟂bЗ4Ö,jv0W0@A>s߿~{TX",9dOnHEE7it~-67f<+E,|^iشH~ ~y.rsV1T_8 9uZ"޵~}3bCj~~Ճ<Ĥo8O[OX46<# {jh2s6R7ݦyMZ$7s0 p3 }v3&&~9Ɠtah+ ԂϿ~v~l"Λ~G-u?gCX.Axs=l?okx*V]<Ѷp݀v݀>ƺw*4+3;BC.\{f>o-VeߵuVoe" JR|dlA i9{ǷX^/cD7J^ 614nH|&]b{LKx ħ-3F_1qHφ6PTW _Eeҧr?xI>Z:sK?,4o rnt~y2̼$, FPD`2;c2xgE/:W_t[y뭻[6\nw˂.0^ Qչ߇Ƹ&'`iwܾ_ջ0KD"-(E; }ñKa1!:i|Ȑ`?OcEIHaB[z4[xŶy.6* ~,U\x4\}@5?LqExfܯ+E~cy[c0K]Z!b?STW?f,p?pDd*"hBs0%XZ^V qk@D[e)̋NyxMDuZ~YÖmogT'?~X;0b/,,ԣ=X'u67 ]>7-ls箏1ûhǬ1SqkO=$ *_E[ dDFWX$CM[cѭ @D0Wlqߙrk cDh{7j~S}gƀ;_t~؃+ ?g?cO2j)yޝaݺ'9{_Թ.,8|D =`}bmm0,0L;"G zxfLdfztN+WRgʭƸ-݅|=[ gOxK>*!/!?xnMx: wu_K EYY7Kvuyqݒ/š$P[{:~Lui'VV_N z:j>-`<_yJT ؟9{8ܻɴdO ~,8NX_FPq*;oPFG^n~*p73T~,󷂖c\3p)U]tfZ~#c?nݺd< ץNQb#SmX~ΣsK/Ru룃Ѣcm:7x>?oؽu|ϏuϽQm-D%wbūs[㞁O%+y_"LB?#$,X1 .>,`Əx< 8w)0%/J/]7"*l-?[퐟\u#jU1K ~-wBLg#>}s/Fcol;)\ ` :5kߋ9ط!I;ZUp\`w}~ܩ86[~ɿ΅ꇟcY~$2:kϽN ~Vp;lGwAze ˯RsnWt>|F~6eyfe ,֟i'%כ:tӹ. Ҧ~ SISeS"5jZi8Ƭx_/;kRM?5ؔsWo7?oe~itwkS_:~[Àmeޟks0AO8Z)7NV} >>rgϗp8D"| qɒqG48[vVZ🤯?cZ氕k pFIsp݋~.UL˖/l',2snρܠ6=z,"nKQ}|*̕+W=C?Ŋ\ ?%rqu _O<իV] S3t5̂K[tb3gˊʥN;|h'//w}ı?Zkk3F4vw??[~VV~~hsQ/o׮MzM̉kx(U\pܥUUU?hKMpß,O}\gA_~ހQG ~wy~, oU1=-?ڟl4nٕf]jƐ!esp?W$F3J)!. uU Mf 'yR HooyS SB G0@D<2SqjZpmgEIb:u[c>nQجҲ7{zi?g?N‹~޴=?fz̘9#Kz@Ы㠉 oŖ;{' F?@ s>F}~ &F ?Jy A<49uۜՎZwy/ECW7V~/~!?4Ot9]R"TPGkg\zȜ1U ~ABRމxkq9g}Գ#?ל3~nj Klf1Oi6v;S=/.V3^0nNB_d3p`UO̫ gI`B >`ȑC~]jչ[8m:D@D}l|pZ}S`Zeyޯ~ZAq_ 0 @nTfq݌_W7nu7ý~_u3/fYO?2)+ :uJv݌㘲)/^[(~#p|F3^A>Q dqw}ŗ:|ܨaj3;Q. ~_;X:N~F/AkOaMs[s*5 ֎6mJi3)!R2gb% L\57KwHn~kٗw}|磊O qp.~> u]|Qը 8i^s Pgln6nޥOR?V :}~S}skgAyg\j8L/-u/g츑^bB s%PrT.LG+OeF@mꃏ>0#Ql5sUmKQͺ;u uz_4K X{umx U̦}حk zL4RaqmQiSrv}'vH2 pP+RX%\y<㑿2!#LTj!j4~< yϥzujx_yU+9gij8N߲!3g^TV[9]*bO*IsJXA4=Z_AAqxɅx!F2-Q >X}W[C5fw”LPo;Ǣ߿|燆#6R(_w ׅmzOC_{MmexK%WX1y>\]&Q3AfehC`nso:dX)*1π)ɦ#|uGUe;4HDZ(E,T]WA*kٵ,+ K"E&T,HHdZ}g&Lɼoڛs[nIɴZ4_; eԼSgiC8Qp͞zwTC^Z3_}Q]־~3C_zUMzժ~>,oZݴiMh&stW_BҌ̈́;ﺯpxY +H@vtWt/zIi z6W 'm}#0 7wR6!`~^1iid-n=会 ߱C{Y6s'c[\G?Of]/{=W["S(eS^ҵ<~g 0tDL0H|Ϟ}v=;0,pH /~VHj7_/m[Ro>]$2yMP0']_;zS^T`Q0g?Y/59ާӏC D$1-o1k֔w}R|U׿D|7⃦)CF#hf$x4?*;݆-ژs d^~Q[_@o-dJ5 mħEP..2m18s3{ ~>"pd"0djӦiƌ(c`F+P Ϛ|&dFN +&=E $O* nЁVzzϠ.XVʤ >:c섗dOu%gݥp93M B2+_}5^<.@axL"y1B@2!TuӍ5rќ[am2& f&'q€ϕ>xGvZLmD=(.2Q]H  c*/.5]$&c]֠A͟;aBbGW Λ``|v9vmk23Gg+"+Ufά&Sd<\-0(93eV#ū^Qr0{y)ds^/x0X+~0!"%{7_Ȩxq O.oғ:j&?@ϣؽ'}G1?p% `nzR;UzSw L"(Sw,S#xZ‚i I4#p?\V!Cy7^crBfL!XO̫W xK2b7@CG66*|25*5>I6ؾczot >Dt<-\6@!g=F="8֫ݵXAyw?dkdHAa Y3G-};DZ/b?4g@etrM9O?{ d/4/*H5 L. <<L$qG dj<ZC˺&,~YW2xD5?3Y ozB?''gd]ƮX(9002TהzuZϛu` 0ݕ>~DOߍ}G͛#̹ǽ6i6Mu{X?`Ȱg0b߇e(a8_u"dp}>Op__=]x Oȁ,DfxBǠk?Zzɓ'{`V1 g~܎ݻMgxMI ]f _dN?gw:?teL>2(@0@m$С4^=Ooӣ>x^x.3+ Y|E @m v0;Ob\WrX:`@+W.'Cb C7$&*."ٸAo;mW0tͣ6ytƜo8+ ȱW<bē-$  mW7_ff:C) ~"pB ږUsLg |f16$-828,+!*72 8ep~^T 0ϗ$ 2t/ޘxYwuU'!ӥsaj{^ع[ g(#ܱv՚i̞U͔!j8 0<;vplX*uV9:")lr؄j PZw9OZ)3]n!Du^_w^ύCxo&siE1G ppZ ٺN0IqC t5~.!/P2 S\ƍm~B7CFCseM)τ6޴Es^RG]ezw,C )z:x:t5GA𣻈Js8lj%v{g? w~ 9`Ch*a+\zpiv֑n`V\?@ĩ BT\OkZ^g^p__ۯoAπ/wI'+Wx7h"&_=rqZJZ6 ff2Ubg̜n/ fήA8Sx| o_իWCR/$L 6Z3%Tv"BegsYRk P̱jg&:{N5D?shnCk=|yvCb8nRYY9%ƒy};|Zvcى8Ot|ܙ_N2 alܡL7Pdn o/Nsi%Nv,=z^!.>v66V`,]f7__8}g/D`)bnK8 ?BO);N OO>D\L剠`!•H&}IE,]9YknY.} NrN|dRh>ľ;Feꪮ ?|ԴQXц.;Wjk 0:zвe3_zoz.x 9G0Eb"Kο>Lau$3KC0z SWC:l ߒ[|Iv6l1{}5a pZO Zs[ 0=Hp2Fan[X(\ [s { @wLK!kN/xsvl޿|ĈQ_yͰxw|T8&k$'I@CG䧉!ވ=o_'AC/5"]|91Jr3E,4{i1p E?oXJ&b ı{@8.]5)9yh*!+Ɣu!]H5T3/m*'N zKpҟh)0h=G -]pZV籜/)8h@ Q3B$-A5e޼QFeddwaw`N R3/\˕2IޠMU=@Xb -pno3YkzzS 4VQDi}C+AZL=JsLO?s` ڗ`Hx)z̜d-h0A z}}?# X񼏞8~fgg78)@6L~DBE OA@ܲfzדlbI5bg0K5 IDAT@j`5| aA@гl7M*!5 ~ր4u,Ǹq/&fds5G`LUmn (4BVW2t§Os#>en׮ u&d?=#~#%FpW4oljgkf֞*M֐\g8,ܹۅ(B%+!5k WTetTe3* BT‡XeZc0%:T_ ﹖-/^_b׃(H'GP^|Py@_ DnMʒ;vR\l;_P歐vsc$V@=>SP } .dQ1ѳ lc4I_s֔fpɳuThC*-3pJ` ';'L|ɳjS.H &CjNrH5䀏9usBMWWUޜGm8ہًl7[r߽ws>߂/3%\|! CXS 79ЯA`lʔ{ܓ'a.Ć7;\S|[T?4T=trQL~'tlɭ[^{ϰ;ClU8Z9x4U(U ǰa{3gxIC&ޛT##fbh`(' R>Ȝu3yYGrO,zWnG^7X>w429DQ([Шqn mق|'@=.s0H*7K(;/g5#$UP0 ^l \Z >J"n36k lE6hi.WdC۫={qH6iN?xH 'G)' jLt"Wݽknsc;rOvKH־zĆ('̏ `fZiqaܿ4J:B{:6% #1);3"l}޴Y:uMWuׯXYLRJ iJ/ҿ}gF83:[A Jr$LVr`/þΏ>dZf3 %:&V~)6쬏F)?Yځ@1 \?v(^PO ʻssk(ͤ>xWnnd܃+8m{;thׯjҘڵ$?wњ.w)] 94SB0WQpȮ9Ddv~>4mgϷٿG^2\<@%j좵g$ wr0ѷH;_!-x쁺pR@q0UൺzRmZY޽kj߮yttѪ'D.Pm$FQPAXf?} K2=Nedq8pгuWjO;=5/i_+ԁ$RwVޜl>d X*_Z%R x)aF) }ׇqM6އm~A"﹨aղE su3+<(D`hӲQpn6?Y,Hp2,Np,?s=z{wnj:zϡC<ĉD|kZU5V ZX(ixrV Y#OqMݟX-f{Fƍ4Mo}b t&L:}Z1懷̃6L` HVyN橓'N]ğHj/f^\RP`%  ٍ9׽JIVi:ۮ/  yȱԴZv,U)ɪAUKT 8`mŰ@ mTL0a<%d1.5~~H D@ER4u{1k@w H0)(h6ɓF8deCK2o(ChC( g5k[r):dkx~ls)΅P^@ 2H?V;D Y%`Зir˟g |%G.X8IENDB`(0` 8}}Zkedu^WW]VU^WVlfesW5(e^^z/&%  2)(kdcs"M/%$   "&&#  "!  3*)D;%           +"!3H?? !   JABohj:11!    ! SKJ&!   >550''    ! ˽>    d]_A99      解0A     ngi  7..  𥠠20!  ibcxqt7..    굲$   &/&%rkmx{2))   7//  ztv2((  F>>|vvZ!   KBCzsu3**  !H  LDExqs0''  !iccp  #MEFwqs0''   xss_%MDExrt1((    #Q!  !!#' PHHwpr.%%   ??76  !#$$%& ) QIJvoq.$$    NGF   "$&'()()"+!  PHHvoq.%%  ;!  "%'* ,"!.$#.$#.$#,"!+! #+!  RJKsln,""    *pjjk! !$'+! .$#2('4*)5+*4*)1'&.$#,"!#+!  QJJ|~rkm*!! "~~WOGF   #&* .$#3)(8.-<21=32<218.-3)(.$#+! ") NFG|qkl)   `YX~:10 !$(,"!2('8.-?54F<;I?>F<;?548.-1'&,"!) 'PGH{}kdf$  IAA-$#  !%).$#4*)<21G=43KA@\RQh^]ZPOJ@?=325+*.$#)%##KCD}vy~\UV|~800 6.-+"!  !%).$#4*)=32G=43<218.-3)(.$#* &#   F>??66"! TLL_XX  !$'+! /%$2('4*)5+*4*)2('.$#+! '$!  qkjkR!  "%'* -#".$#/%$.$#,"!* '%"    !?!   "$&()))(&$"     (   !#$%%%$#!  4,+c]\y   !!"!!  uooe$   >76   KDC3    &D=<   TMM   O"  ">WQP "  #f`_o>65 "  #LEE<43 #    #JCBRKJ     _XWy~xwW  !    !錆I6.-            >55?.$# !    !! 4*)65KDC   QJI/RHGH>=:0/1'&#-#"rlm{}PII $  #)2('>43SIHe[ZRHG=321'&* )rkm|~]UV  #(0&%;10J@?SIHI?>:0/0&%($&qjl)    !&,"!4*);10>43:0/3)(,"!&! $iceWPP>553**+"!6-- #(-#"0&%2('0&%,"!'#    @88`YY   #&()(&#  #nhg~G  !###!   :#  +#"tont   }}e   ( K#  ">f`_$ %tnmsTLL$    $`YXd]\        ohhzO !     ! ᡝEiba   pjiy ZNFF'    (QJIT *.¿)(0 RXQP.%$0'&XQPNY&  *!    )ܘV KCB $ # $ PHG 2** #  ^WXA99H@A  80/ F?> #  F>?¾#  ! JCB~~k#  mfh"  c  jcd"  $ g   )kdf!$_C<;  $(&.$# kdf HA@   $+! 2('5+*.$#1'& leg$'" !(2('@65J@?@65/$#.$#kde' + !) 5+*KA@bXWJ@?5+*&' hab=55 % !(2('A76KA@@652('(# g`b#$+! 2('5+*2('+! $ )  911  $(* ($     @98vqp{  !!!  ~yxr"    ga`   !nih (     ,$#&  !      ! "%%       )! ! bZZ e^] 'jcc/&%   0'&mff$9A8(  ibb*!  ,##ked[ d]_ysu  U`  #KCDaZ["Z) YQRWPQ "#[UT  " b[\VNOa[Z!  $+"!h`bZST &4  &4*)=327-,f_`WPP C  )@65[QP<21,"! aYZ8  &4*)@654*)$!PHISKL   &(&  NGG  TMM; "     4{vu}#     "}}v{ut  {zy Info.plist_tmp && mv Info.plist_tmp Info.plist #cd ../.. rm -rf E-Pyo_OSX rm -rf Resources pyo/utils/Tutorial_03_TriTable.py0000644000175000017500000000367612652732202016277 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 from pyo import * class TriTable(PyoTableObject): """ Square waveform generator. Generates square waveforms made up of fixed number of harmonics. :Parent: :py:class:`PyoTableObject` :Args: order : int, optional Number of harmonics square waveform is made of. The waveform will contains `order` odd harmonics. Defaults to 10. size : int, optional Table size in samples. Defaults to 8192. >>> s = Server().boot() >>> s.start() >>> t = TriTable(order=15).normalize() >>> a = Osc(table=t, freq=[199,200], mul=.2).out() """ def __init__(self, order=10, size=8192): PyoTableObject.__init__(self, size) self._order = order self._tri_table = HarmTable(self._create_list(order), size) self._base_objs = self._tri_table.getBaseObjects() self.normalize() def _create_list(self, order): # internal method used to compute the harmonics's weight l = [] ph = 1.0 for i in range(1,order*2): if i % 2 == 0: l.append(0) else: l.append(ph / (i*i)) ph *= -1 return l def setOrder(self, x): """ Change the `order` attribute and redraw the waveform. :Args: x : int New number of harmonics """ self._order = x self._tri_table.replace(self._create_list(x)) self.normalize() self.refreshView() @property def order(self): """int. Number of harmonics triangular waveform is made of.""" return self._order @order.setter def order(self, x): self.setOrder(x) # Run the script to test the TriTable object. if __name__ == "__main__": s = Server().boot() t = TriTable(10, 8192) t.view() a = Osc(t, 500, mul=.3).out() s.gui(locals()) pyo/utils/styles/0000755000175000017500000000000012652732202013341 5ustar tiagotiagopyo/utils/styles/Smooth0000644000175000017500000000241112652732202014533 0ustar tiagotiagostyle = {'background': {'colour': '#222222'}, 'bracebad': {'colour': '#DD0000'}, 'bracelight': {'colour': '#AABBDD'}, 'caret': {'colour': '#EEEEEE'}, 'class': {'bold': 1, 'colour': '#00FFA2', 'italic': 0, 'underline': 0}, 'comment': {'bold': 0, 'colour': '#DD0000', 'italic': 1, 'underline': 0}, 'commentblock': {'bold': 0, 'colour': '#AF0000', 'italic': 1, 'underline': 0}, 'default': {'bold': 0, 'colour': '#FFFFFF', 'italic': 0, 'underline': 0}, 'foldmarginback': {'colour': u'#1C1C1C'}, 'function': {'bold': 1, 'colour': '#00FFD5', 'italic': 0, 'underline': 0}, 'keyword': {'bold': 1, 'colour': '#9999FF', 'italic': 0, 'underline': 0}, 'lineedge': {'colour': '#333333'}, 'linenumber': {'bold': 1, 'colour': '#EEEEEE', 'italic': 1, 'underline': 0}, 'marginback': {'colour': u'#121212'}, 'markerbg': {'colour': u'#DDDDDD'}, 'markerfg': {'colour': u'#1C1C1C'}, 'number': {'bold': 1, 'colour': '#FFFFFF', 'italic': 0, 'underline': 0}, 'operator': {'bold': 1, 'colour': '#FFFFFF', 'italic': 0, 'underline': 0}, 'pyokeyword': {'bold': 1, 'colour': u'#64BEFF', 'italic': 0, 'underline': 0}, 'selback': {'colour': '#555555'}, 'string': {'bold': 0, 'colour': '#00EE00', 'italic': 0, 'underline': 0}, 'triple': {'bold': 0, 'colour': '#00AA00', 'italic': 0, 'underline': 0}} pyo/utils/styles/Soft0000644000175000017500000000241312652732202014177 0ustar tiagotiagostyle = {'background': {'colour': '#EFEFEF'}, 'bracebad': {'colour': '#DD0000'}, 'bracelight': {'colour': '#AABBDD'}, 'caret': {'colour': '#222222'}, 'class': {'bold': 1, 'colour': u'#3F3F3F', 'italic': 0, 'underline': 1}, 'comment': {'bold': 0, 'colour': '#444444', 'italic': 1, 'underline': 0}, 'commentblock': {'bold': 0, 'colour': '#7F7F7F', 'italic': 1, 'underline': 0}, 'default': {'bold': 0, 'colour': '#000000', 'italic': 0, 'underline': 0}, 'foldmarginback': {'colour': u'#D0D0D0'}, 'function': {'bold': 1, 'colour': u'#3F3F3F', 'italic': 0, 'underline': 0}, 'keyword': {'bold': 1, 'colour': u'#000000', 'italic': 0, 'underline': 0}, 'lineedge': {'colour': '#CDCDCD'}, 'linenumber': {'bold': 0, 'colour': '#111111', 'italic': 0, 'underline': 0}, 'marginback': {'colour': '#AFAFAF'}, 'markerbg': {'colour': '#404040'}, 'markerfg': {'colour': u'#D0D0D0'}, 'number': {'bold': 1, 'colour': '#222222', 'italic': 0, 'underline': 0}, 'operator': {'bold': 1, 'colour': '#000000', 'italic': 0, 'underline': 0}, 'pyokeyword': {'bold': 1, 'colour': u'#000000', 'italic': 0, 'underline': 0}, 'selback': {'colour': '#CBCBCB'}, 'string': {'bold': 0, 'colour': u'#272727', 'italic': 1, 'underline': 0}, 'triple': {'bold': 0, 'colour': '#333333', 'italic': 1, 'underline': 0}} pyo/utils/styles/Espresso0000644000175000017500000000241312652732202015067 0ustar tiagotiagostyle = {'background': {'colour': u'#2A211C'}, 'bracebad': {'colour': '#DD0000'}, 'bracelight': {'colour': u'#463F3B'}, 'caret': {'colour': '#999999'}, 'class': {'bold': 1, 'colour': '#E5757B', 'italic': 0, 'underline': 0}, 'comment': {'bold': 0, 'colour': '#00AAFF', 'italic': 1, 'underline': 0}, 'commentblock': {'bold': 0, 'colour': '#0080DD', 'italic': 1, 'underline': 0}, 'default': {'bold': 0, 'colour': u'#DECBB8', 'italic': 0, 'underline': 0}, 'foldmarginback': {'colour': u'#211915'}, 'function': {'bold': 1, 'colour': '#FF9358', 'italic': 0, 'underline': 0}, 'keyword': {'bold': 1, 'colour': '#43A8ED', 'italic': 0, 'underline': 0}, 'lineedge': {'colour': '#3B322D'}, 'linenumber': {'bold': 1, 'colour': u'#DECBB8', 'italic': 1, 'underline': 0}, 'marginback': {'colour': '#2A211C'}, 'markerbg': {'colour': u'#BDAE9C'}, 'markerfg': {'colour': u'#211915'}, 'number': {'bold': 1, 'colour': '#44AA43', 'italic': 0, 'underline': 0}, 'operator': {'bold': 1, 'colour': '#BDAE9C', 'italic': 0, 'underline': 0}, 'pyokeyword': {'bold': 1, 'colour': '#43A8ED', 'italic': 0, 'underline': 0}, 'selback': {'colour': '#5D544F'}, 'string': {'bold': 0, 'colour': '#2FE420', 'italic': 0, 'underline': 0}, 'triple': {'bold': 0, 'colour': '#049B0A', 'italic': 0, 'underline': 0}} pyo/utils/styles/Custom0000644000175000017500000000241212652732202014535 0ustar tiagotiagostyle = {'background': {'colour': '#000000'}, 'bracebad': {'colour': '#DD0000'}, 'bracelight': {'colour': '#AABBDD'}, 'caret': {'colour': '#DDDDDD'}, 'class': {'bold': 1, 'colour': '#4AF3FF', 'italic': 0, 'underline': 0}, 'comment': {'bold': 0, 'colour': '#9FFF9F', 'italic': 1, 'underline': 0}, 'commentblock': {'bold': 0, 'colour': u'#8BA979', 'italic': 1, 'underline': 0}, 'default': {'bold': 0, 'colour': '#FFFFFF', 'italic': 0, 'underline': 0}, 'foldmarginback': {'colour': u'#1D1D1D'}, 'function': {'bold': 1, 'colour': '#00E0B6', 'italic': 0, 'underline': 0}, 'keyword': {'bold': 1, 'colour': '#4A94FF', 'italic': 0, 'underline': 0}, 'lineedge': {'colour': '#222222'}, 'linenumber': {'bold': 1, 'colour': '#FFFFFF', 'italic': 1, 'underline': 0}, 'marginback': {'colour': '#000000'}, 'markerbg': {'colour': u'#FFFFFF'}, 'markerfg': {'colour': u'#000000'}, 'number': {'bold': 1, 'colour': '#90CB43', 'italic': 0, 'underline': 0}, 'operator': {'bold': 1, 'colour': '#FFFFFF', 'italic': 0, 'underline': 0}, 'pyokeyword': {'bold': 1, 'colour': '#4A94FF', 'italic': 0, 'underline': 0}, 'selback': {'colour': '#333333'}, 'string': {'bold': 0, 'colour': u'#FF46D7', 'italic': 0, 'underline': 0}, 'triple': {'bold': 0, 'colour': u'#FF1070', 'italic': 0, 'underline': 0}} pyo/utils/styles/Default0000644000175000017500000000240512652732202014651 0ustar tiagotiagostyle = {'background': {'colour': '#FFFFFF'}, 'bracebad': {'colour': '#DD0000'}, 'bracelight': {'colour': '#AABBDD'}, 'caret': {'colour': '#000000'}, 'class': {'bold': 1, 'colour': '#000097', 'italic': 0, 'underline': 0}, 'comment': {'bold': 0, 'colour': '#0066FF', 'italic': 1, 'underline': 0}, 'commentblock': {'bold': 0, 'colour': u'#468EFF', 'italic': 1, 'underline': 0}, 'default': {'bold': 0, 'colour': '#000000', 'italic': 0, 'underline': 0}, 'foldmarginback': {'colour': '#D0D0D0'}, 'function': {'bold': 1, 'colour': '#0000A2', 'italic': 0, 'underline': 0}, 'keyword': {'bold': 1, 'colour': '#0000FF', 'italic': 0, 'underline': 0}, 'lineedge': {'colour': '#DDDDDD'}, 'linenumber': {'bold': 0, 'colour': '#000000', 'italic': 0, 'underline': 0}, 'marginback': {'colour': '#B0B0B0'}, 'markerbg': {'colour': '#000000'}, 'markerfg': {'colour': '#CCCCCC'}, 'number': {'bold': 1, 'colour': '#0000CD', 'italic': 0, 'underline': 0}, 'operator': {'bold': 1, 'colour': '#000000', 'italic': 0, 'underline': 0}, 'pyokeyword': {'bold': 1, 'colour': '#5555FF', 'italic': 0, 'underline': 0}, 'selback': {'colour': '#C0DFFF'}, 'string': {'bold': 0, 'colour': '#036A07', 'italic': 0, 'underline': 0}, 'triple': {'bold': 0, 'colour': '#03BA07', 'italic': 0, 'underline': 0}} pyo/utils/E-PyoIconDoc.icns0000644000175000017500000024422612652732202015076 0ustar tiagotiagoicnsHis32 B+?V"#RC.`e#JU^&RI xYcC,@ V#$SD/_f$IU^&QH yYdK4H  [ ,'-YJ $9!dj.%P[^/YO~`js8mk[O \ _WAsgljkjlgs>il32 ȅ͹    涥ٱda ( ~n0 $ &7%/V   /H41 /6> I  3F>2?mRL \s1` id3%0aƐֳʀȅ͹    涥ٱeb!)  ~o0 %'8&/U 0I51  06=I 3E? 2?mPL \t1^ je4&1aƐֳʀȅ͹    繩ٱk  h)!0$$&$$ t8#%$ -#1B0(8]$:S?:%"*:&?FP$<60*%!  >k ==!  -!%,35-'" 7@==  -"&-6AO\SD8/(# Af5"==  -"&-5@NXQC7/(#Fp^"==' -!%+2:CHE<4-&"I{^m==5 -#(-38;95/)$ Kbx ==L +!%),010-*&"Mf}  ==i  !$')'%" Of 3== + "#$#" Qg  e==  Sh  ==1  Th   ==~ (Sh  F==  %Ti  ==O Th   !== Th  }==K Tg  ==  Wg  ==|  \g  F==>   {Ug    ==   =h   ==     xl   ==   %&   ==   #J   ==2  YZ ==(j  sL  C==&2     ==,   }== Q  @==q? 4e== Ķ============================%;9';.8==!$| ==1 ۧ_x== ( ٔ dBlW==*@2>1P& SR==(*,77.?6}0&==(+I(==1!;4e==(42!w]/6== ÿ!ݑ==,r==Q)z=:<@> ':&f[`_``^_^]!ƘZa^_`]hWE LR/ rt@ a_; kh= ge= hf=hf=hg=hi=hj=hl=hm=ho=h r=h s=h u=h v=h y=h z=h |=h ~=h =h =h=f=k=e:TKNMNOOPQRTVXZ^c]z"= ;=@=벆cA+#!"):Z} <=N  @==t X=={   Y== %   == v    K== P   '== >    ===    ==P   #==r  ===  w==$  ==s  >== ==n  8== ==    `==F  ==    ==   !    y==x  "$&%#   @==U * #&)+,,*'$!  %==< $#&+/3430,'# rB ==, - %*06i ==" -"&-4=GMI?6.(#6?== -#'.7BP]TE90)$@d5#==! -#'.6AOYRD80)$En]" ==( -"&,3;DIF=5.'#Hy]k ==6 - $).49<:60*%!K~`v ==M +"&*-121.+'# L߁d{  ==j  "%(*(&#!Nނe} 4== +!#$%$#!! Pރe  f==   Rބf  ==1  Rކf  == &Rކg  G== %Sއg  ==O Sވg  "== Sވf  }==K Sމe  ==  Vމe ==}   [݋e F==>  xT܎e ==   1P& SR==(*,77.?6}0&==(+I(==1!;4e==(42!w]/6== ÿ!ݑ==,r==Q)z=:<@> ':&f[`_``^_^]!ƘZa^_`]hWE LR/ rt@ a_; kh= ge= hf=hf=hg=hi=hj=hl=hm=ho=h r=h s=h u=h v=h y=h z=h |=h ~=h =h =h=f=k=e:TKNMNOOPQRTVXZ^c]z"= ;=@=춋iI4,*+1Ba <=U&   H==z%  !! !! _== ! a== .!  == | ! S== W! " /== F#  !==E " ==W",==x# D== "}==,==x E== ==s @==# ==   !  e==N  !"##$$#"! $==   "$%&' &%$"!  ==   "$&(*+*)'%#!!==}!  "$'),.0/-*(%# ! H==\ *!$&*-0356541.+'$" .==D$ #%)-059=>=:61-*&#!x J==4-!$&*/4:@FIGA;50,'$! Fp ==+-!$(,07>GQWSI@82-)%"!?G ==*-!%(-18ALZg^OC:3.)%"!#Hk=, ==*-!%(-18@KYc\NB:3.)%$ $Mud+ ==1-!$',06=ENSPG?81-(&"%Pdr==>-!#&*.38>CFD@:4/+(!#&Rh}==T + "%(,047;<;851-*#%'Tk)==p! !#&),/2420-+$&)Vl=== + "$&(+-./.-++$' )Xl l==  "$&')*))$& *Yl ==9  !#$%&'"%)Zm==!& !"##$ #(Zn N==% !"'Zn!==V  %Zn*==$Zm ==R $[m'== ]l ==!bl M==F \ߔl == 'Cm  == *&|q !==  ., == "!-')R ==; _`  ! ==(q ! xT!L==&<   %==6 !!!! %== Y" I==wH% =l==ǀ============================%*HF5)H.*ݬj== 6.ۙ)mLv#b-==*L@J)@Z3/^]==(79CC:KB-<,3== 9+&U*5==>/G Bm==(A>/%&~$g=A== þ/ߗ==9x==\6=:<@> ':&f[`_``_^]!Ƙt8mk@(%&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'%)*   +  3  X d  >  4 5 7  :  b  d  Z  H  K  N  S  W  Z  ]  a  d h F `  ] `  _  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  `  _  `  ^_  J߆ic08< jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 ; ǀ&|JCSVqmtD5WT!bC# Fճ^1`|$UECm`. x +3?~H|=0 vNO jA8e>锶rCQi0#?h~@T(hvh 8T8ėyo p|== a`|aX3<(aKv-Koc mGɨhLғb-_:Y"ظ?4",F? Zu_YOr|M6qK 9w2_"| >Bp¨F$M]ACԒS(MI I6=6Jׅ|kn=0Df_/ 8hPn1)؂0[Hn06!V$z4Z mHs ­ME։!42%xEXO+,GV(ȿs0絼+0PGIC{BM-QL;Ly_ n39$i}(,Jgv6G!Q~SG˻/^P?=FCbp>>xSWօ~erPZlF$r2s} z"U~Z`oܥ=1Z &~Xr#*.>|9jីxJv? Ʉӆ42yJTou6s!w\dV7mRty9wGOk.\ކDYǝuP9x&}5M.SK_4vɷjxKu,.FgCsǙwgpum|=&Xmcb]j2βh$rp)ke-P(8x 2$%g6 |  4VLjF5·֛.)h檊/^Q`Q7ul$<*"VXFz𙚖Ls|W #(рd*17j>.F\-× n+؉s> xV1+֟gm[f1_HkF`OYFexfgB ?`Rf:7ugt81z*!>-rk^f÷4[l2U5k.mh&é "K:gP#no)XwGB(F'~l+"srMHqDHzu/5;2gmQj~zNz'N=^|MwnMwjz(X:ljL#z2=ɦ#3roztCO]HS>8ۗO5l@,jGczaܫ+eq]%w ˆJluڽTiQ"<=v2" pz>A*I藽b](mn~iMq?9UD !%3`%f|3l6,GBxCM}R즰f2\VKft7VחXrW_dy`OgP3ڰ8+(1;0];?M<5;D SNIJ钍Z;&LѤe3Qh.} An;N<t%F9x# Crqɻ}N TfR,*5K\z:^6v]NF0-V޼$v &ExM̹z"Wsr:ux\|Ծ,GA!p┺Ny'D7YvuX?£%|b"0q #/(fU#[%0 BOl-^SX ]:vXe:yoMqΎnm2ipɥDgo7Uc%oh yy)rjgMȕ' M];3G!G2rwVSL*XHħ mQiޓ4Y}*[g? ^V͐M+@ |, B.Yvtfciʀ7*~%/Pۻ \/2VEEw30,I]5cs]p&FpHX@ߘP.gLSRح/c?\ռ۽^"_34Q61Auh ԉGNinJRМh}F#P1 Gz Dfɸ<_+oUQYJ9R&>5!PehXSzOLF *&h}\SǑ>  ɌtҨhDTϿM6V˖0Q 6$ɆK_gC?L47΂A=.g6?@/&<΄Bo.=Ac\U5Q?b^2:s3 +.q0f:n=Xc؟֓Bzv+hdwF~D^9ǂl4r&;YYa"TA{(i ?X]I#gڥͺ"!i1#ɑ+xŠ0!c 0z͈p`7yd^PnmtN?`+&_yؤLϳy?>;A= Wyv tǻelnU5%Fod& SF;91G]#zR\W-;eo=HsSi~gR8bT+L~Ź#Es ;}agO0ˏg<sO43O19'SҒ9;pv\!ّ}1KU{U&x zՎsolo)m*;Qno_59| GV\#'Ieˋ~o!iypЦ3({g!^S ?;-$˴b yta,~4Wkt0;HI En% mЫoa@ux+'qՑiH4DP+h.ELbhzb͘ 4;Hb)+k› YJqT\c%Pߞ(i#^S=m|5EB52 ~)0"^!jLSimUi}AGjm[ HiGY S3c:>1x2K&R#T 6s>m?(ƱYęhx57rH/ba]?O[X`:l1;Hb:_Omb^30fPj0|w]gbZb,qo,}(Rpt8(mDGsDOMߤV=);o&Fv"b}҈^=҇'LF'WX fm[* 4e91bb!Bz#EX&Nq~mkgʶɖctNR1A2Z&9}|p+˓g]ŋ7R&Co3T[BBw3AXie24Pv!LK\c-SJM,*̓yۢN9 X[n,L:݌cl")oZ`>P\a'[`iUP8- !AV?[Jyp4 GpyA] H?P<20sZ[ 85htTh%9:4 RVpӨcR؟n_vH<, [eJ,"X,?SɓB8* $t;[uȪCd> toIr{R6-O$MA=U4 n La. MgH= _uv …tEqOؙ-܉kel{LJ$S:COc؎"6?zxKKSL"O{. 2}䁂Ԇtva-")LpƛivhxǡͤZuLY! |(x72g_vvݭuYç +یHDsxhp)v\F'Q2>NCARJH;]ҪIBtmxJE꘶A+O &D61 ,iV`0<?h6~q foG;\ szMiRAEC0pTHH)hZe%#_XNT.+:䵺BϧCЕ؀O@a< Ih"ɫ#?~2cjU4 IJoVϯC wH)E3Ex(Ze8 "7N1V0<np[U$\$ ֯!|q8F 6''&?eEU*c ^{RT`!^i;kQ,Pd=RHN/ς:߅[d/{)A,ᒛ3Wdx| 0 2jʓ<-U{_LdgHΛWlxlCA#G7X(ߩHяw[;U 1; bG!aJ+RyB\Ks;}ueX@SqlހUzl#m~$8 3,u.'`@|Psp@eF<zhbmFH$ԚzӜ8Rnj稪 K3S9ۚ,m7gՏqAa/1H*  %_zYH)t5 03$ecfUP0̆է.hkiw;1) *6*;HUYz,(57" 5zC‹wGOm퓦7./{LCBܒɧKSk7nEurMEwJ -a#Z5f4>fVH\US$KlIgHYL~.ڎj9Sk=dFζ./m2eĤ%)Ɔt6( rZ MtQ} d] # WܣdOgV:|7q"rBr@..ľ6!ǩ H5RKp%GO:;eveUKȊ.!cZJ ;Ag@tMg R<?"f t4{Ȫ[lq. [+g׮\` '>%pϳ>(ܠ}©oj0΢+&+ySr*+x6V* nq}_|9pK0h `P[ Q܄kurcp9 5qXȴ9c{9/vpT0`0tC&s՚: ME5t (؉q<5\,ラ1P$M{wڔ8G ˥b/zP`3_ VxFN)f6->ETM|BՔKT+:ë#e &l|vO&# _Fj?֪"^6 I5J)`_L'04C'O5^" },(^8~`qCʜ`DDa'O@t5Ǣ _G?BdRmHғs}5n\5,I<(:B!#{#PuTWP![aĤG8\ ,/QM5Gr#Aku|9./qV+WUM6} ]o.$˯KNPIcgTĴИ77 t8DdP̗ucym*zfe{4KPGb⯤7gd̟7SĽYYu-@ /YR;PNaV}%h|מAX bi]Vב6 W 6Kg'%pyԀiP 7|$P>sNDz>r ڲ:nv6;FDX:Fx9{)A~*&踑͊(N˰G#*)ɣ7d)$֝OBy}>LlӴ9,Pf{՗V?q6\[7dOVpFxH0+KXf[R[pK vXRtd ].հ9 &Q9E&2tԔ$<Ư-6v98WekF62 1y*Rll4#1uIժ*?Ϣ3614ߧecJ7ZJ*R8Mo~=Ȧ+ӕ%q,'H)N 'E HA2Ib6 ╀\j !r_ͥ]f֏< }WN`go Rs0fDx}ڷ<lK@Vo\RP&iC%oî>7Sxxrܣ|dt\;g562* ԖOL%H5*C9݅)  ׫iM'17 p>/t8j& H&}O&]ÝvY95:WیW4_yZ<0 QO^ Dz|7JJL>HܿX҈_:SL>Z&l/p*JJ;<ި"|.kՆwiLb䜓)s^Uܝ {&g]a7"5>q8x"hO3Ƥ*ޒM>#iRS~ 85:G/K/Pl8"]tBsgw5tg+ sem!gojmoNy='"h][MvSBbv6;S%fxD:Ƿgu-yP( S*LxT-e3[3@_9>I`d^L0D|p?f@Š'#a!) ܏W̮K6]tϪpY*WUQBE|͵Km|G ȲBYl']ָ)7e7߼]D yv woje#5 $Sr<2g-V Q}U봥UUUUSZC룅$3sLt.IgsxGKs DygwhޝÂ驺Z}`;4!+u$J@c9 YŢ LSNB%znqȕj=Fh˸ 9cG  ۤ fQPQbNJML2 %БϼE 1?uj)"cOi&[)ItSe$,%k ºH]OSy%yu FUp桎%p:)\^=i BphUS3wzCʺXm\j1 5#vveP0/e09+]3xA@ g.tnȵ"c9/#ʥQir߆+%C#Pߛ%F1kvyK^z| a.TAw)J)G!˔9(#w-! +NiL(7?$.oZТ%ɅPtFsz$5meHf}T Bç03~C39 GeN ߃04oS nbONN~ha!&N5h.t(lðϗT&:1S[jU3&Ux`:wڔ 9CXx^%rj4;B}7#IƝL$OF:`ė[>w;Xdʮ\E  v$2WB,Y,2HK-o|5hJ83HK|'V.|,V6?Ls:B.yYko`6OuMp1 US0\)G;7uJR)J'> aYMNd]Ce jA-92Mt7-=h wp4hZKhh2̀:KdQdBiIlqS6rn5k̅[KҐmu%BhD"3= %~cJb. w$<츯<.&ސDDn' noeH5qf= wE[p8(P}*HؘBʼsuy&QHb`iƙ.'ׇk.}R_*Jfؔx f\Zd̹@`e9*&ޒARJ5fA&?2D!S<|nJ5.|&oC;,(c%iL MI{fരigHwh j?jgMqb#<44#<+vg-##h4 y`&`WV.B7`YPj.*lP 5SFq9ڣjt7ϮNI.+#f NkG~f#NC%Ӣ>uMv&͸\!ZϹۛScAy G@2vd]s,>C&C0ɫA2r8KETHd>gƣu]*]6WU xnC:`Zֺ"-[W˶f6CM"9sjP Հ;w3[p<ǩhfJ;.,b=Oh"_3+[RLo_ ?7.-n`O)r]V}ȆU?17^.'?zGeօYzV?K_&`@i@К Lj~g}*~'9C5)Ԉ7#|?Ək Tߋ+vqvKax-qF@I헰.sO͂( gj0^RRn:q;@ 7B f$[О. \瀅#KrߓشR@_\1Q^ @5hfA"hV 5xri)}TO'hҔXNSAgz|E TI&J+FhT,(+Į1#5l_k:I l}E ([R%w ?.] I;XJȸ@[ F`VxJO@K;FLxb"=6U%7r/9ëv=m pR8usV)O6lFc`wy T= Uq4T!{i`q!,p]t(CR& iȶj/,rwBS 9Р>ar#n:KnN3.35摴EH.nȯ@).M Acς lt뺱 PM9яPb^$$ycߝQȇ;aP`vjO`>=qYІ޺R?Ҭq2˜Q]{D慢"pa4 ׈)2NRoM= sWhaD*~gwG?3sեTDRgzwT'}H470qrŸ6?x,kEpnSĦw MlORCR]d܇?"^T!Ml { 0P$HEZE01?.v'0^_uùh ڟ@zOE=`JaSCLhdn@e7TpWҵz\1[t{j/@E-O_#8Đq긠. G>khj"`#8:INX}'Z(~'n .;_-?l(e UvnD<?tRs(OS&𥟬0"e&$;8iAA9*fc"MD& #V2,LڢCF]P4*U/o% 5DDI y:;QUd:dnhZ|#a1!=1Y)Dh [u|7|6AEA|̴T/}>*&./)yK^R򗔼/lZ3AqY@~ro@Jn}uAft:[Kium.մV][KiqCX9ȨʞGtr@ kD']kE:qe&X.UT|O`uq'+[ox.(\dYWѦŇ7EɂȫNS\h esf$"D Mp&]F\+159?ZL! }L*3kHjv?=]-wU>ܯuΓ5[3XYyc@;ĕU%=Ia^YpyrVvcsũ,EY*'1W`%3nʦI}\QmGIrT5q&:xɑ ٘4yM-UbʄRу| pT1{ot6Zg?cHJ3-A1ޗX??pRf:7ug 䛤XCb%QqԠݕ?%(`Y"ĉ)&é "K;Gћs" n MD Ԕֻ.P!#QvĂ{DHzu/J1f?mu^r/<Ֆ8T}HsXxtavkWUN D+}B']cTԕĽr/62#)0K9L;:&A/ ӗDuikqkS>pU>JRPwmd)ZK(7$iW|8!w7˶BPZ.*ærz>jA@*x0Xi$ɍ\mO)/6aUע)Eaۦd:b8޿ >,ˢ-(zfTme!6$b%Myos)PCDԖ|u* ?@D0I9Pp-i(w֮Oe7A)۸Kٽr)E謋 VEQYi;FZҲ]p!ÆV̵!~pIp?{O"(5#D]V &`(qtF_㬫jI7BlT~+X[8֡Lfa6g@ 0'O,&(:: IDΓw2]ރ0)"jt* к'|UM'3vwbNrBEK_*A+ f鉆ӽL~y|Xp ƏHE|8a[ACEL?/[pB=RRc97eZ랅!z$evb]2Fݫ%Gf3|?E7tu̠GEA|niN9}s۩l M* 3K'SZ%k% P(ݎޫ&a|Z'n{{ dCiEו9fD9bڰ}<ʯaW9@Y0$-yuze>y.l!- g.3_BWܫxEUB]3fnZ_vy%/e|ȷU(h+7R>r(nբ@xXʩi5#| N=5HM1ipLdcD7嶡[O:M\p+ ,Wm5C_ nJtZC47UXTx >3"FzT`S}EV)\Q_3k^>DɌt詇$j-эП={gsH#1\rMu*SQAC̞IhhvRͰnE0'G} ~f/&<΄Bo.=Ac\U5Pʻ|'ׇkxkMNN_Yc#fȰ% AsIUj _r܅!)ơ^f!Lu]{)yKk*,SY׹1h'U1)Drτ7"GuT_SgybƳϳQ๷,@0q T=|)<Mdm7mg\8ʔ ISXFj6Z +u)W_<9$C}>O󷱫Ҭ':@f *"(ض* aGV s<ka%wjR5]ڋ1k[bbeWsOHUxmwވXq˞kk9-tVpZ0s#=\}6q N1uOardj.˳u \oOgjLxgNbTV3 ;ꀾP)/]nQg  [/7p]uּZp(ÄRG/c_*0ϳE@E3AݔسUs Ȗ )QM 2aCQͷAwz`Bo,3 esͻ #J\#HNOuԱy[m|m}w_8y֐߈k7軸VUFjU4 @ 8J!+Z788<37}49uDi@phzz7;r;7L87YWvE ̱$ի f% L~"izFP *MWY [&D`G$t*M| B} 2^+'0!`|S^@2&0Ldyy{+96lFF̸fBMC#= -?w:)<_=,Gyg]Q`)ت0{>`zhD acC}%Ns/!SC>AN>?b[_TLr'cLE (ZXv*%kGn43,+n+vX9[mT F+awS;_:}cF> @N%\>_n`UYђ>}jY?|d 4k$þ=2nQW x3<GwWہtb<-69Ƨ^ml)RIݨVx]BȡU x)L|P#|Tr:{Ll5=kw"zb|*9}D!Bal/_7vjFs{Sh9F 001X k2<'FC<+ >2c0Jo˹I ϼ|x 4x8͍v P /mkQ0m^md瞩Lx2AY/ .?Dѹ ¸X!E BD~C`܃S*#Eҹ@NX!ڷDKoEZmFw:xc.Eu.FdOc^bk2a&1n0c0Y㥁v@٭vM"%Aj!J9J!qDX?jܻxp-H'xМcAlJ+d!J@2?[~Hk@z99HR(eopӭW6=`;jJRnUDI{47,U 8\HFPE  k_&]ƺɀx,i$|r aWJ?nGmYSOEh$鐤h@Dk b:DHPgbP nXV#Yvuͣ|X7є9K8:Q+">EtIHʷf?o@㨲-VAIL/]ʶI PV[B<YGA!_=-w~lQo*ܖU]fcL0F&( 돭xj2'o ZS =&Ԥ_ ^\֮*IJN3SjgFΔB[8]6iLJ]O|tj*Æu#X-uƹ> Mҳ-yUܽ╅?`nB%bSMYkN#&LeBh*9BRn~ᆜvZ +(订o:r b ّ/oyUN~OL7X Jk #i"؈;Ybz& AFiɕl DdHgm_:,VŽuLqhd߲&-`\"I={UnhidNm禠y+r_~"|le y2A5RfL^=YU?Fi,/MO?ϩU @"Q @@UuZ0EEkz{ye>A>+1ÅQBI/kܱ 8MPzuiNx1lOtyIfKxRW"2vGBR ;/7%3B1ur8ν|*3GЛ|ˤMpUm2+պGXF. ghJSچ$(Fr_-il[^V]cNyՉ!8{D6dC`WKd\0j~$?h[Og}ClޚPD%sHgYM Y9)X& ʐYA]C ڝ%eH7/UCCn1{J(4 4S/+r 1І7Rj̩gz *)53١*W- Լ'S8LXȴӇVz1oe9v疐б1=r-bܜLJL)erg,vC5y啎ьY2onY>fLʊE$s|/t?g MÀ?%'U{_Pkoƿ̲{| .ˏ݌s'9.L Bѯ#[C2L,y-0jQ y)fZьhO¾g>̱_imk?q_㑻DL?gnӂGf[`'F6:kt $ZEq(hBy 8S˱<JC5A+ah=$:K6ro3 )?\e>T<ȣp9ӕy nRˢΩ 6͡e[9lmkfEhb2qe?ka gy`i`ΔU;N]O am1bjvWXfdH=b;dbO ^/1K@3c<&_6RRdI"DeT0Kd| iK. #I߇Eӛ>LapcX,ǻ_U_= \hCv9Ô̽ďvZFu} V?3S6_7'PwQREӹW^|zZzY;9cSA7p`-oX8!Wd.9rc2WWf="ӣJ "eQTIPb vqau ݐ\M*h&og| gHKb]Ќ+F>!Iͮ08pטDQU}PU׷Z3`Xyr }F;&Bx-V`4_ó`S4ó`4_ÿE9[Qr TNhb1 t1*8]}+֖ p)"B{ YŃgSn0|lbPBG-XS%-XYtp:q_i Q<ɿ^/cb>

5+noooooowɮ5iRlDqU/[˧P [{FA8K訒qUokzDEU*@Dxwܸ y 1x 9#-`d=t)̣'&KN} t,6q*KQ5ẀHx4wP큡Oͧ΀{&)D!HhJcn' ~_7|7|H6 al6 yyyyyyyyyyw'&{$6yRRoP1A-[EY?3@Hא2IL/æj 0C߀ƙC)57%טWrϷQ/az8GUs <@(@1 731ˇ P%M8 NVzC fgfNVz(t4MBD}1U*=M`2RWEST-ͤ"d> fH&窨W%hZ/.& @dJkd ɟYdS`/p2Ĥ~S(gmH1O1> =5 ; bʘ27ͽ%Hr@m2EDa dK>97f/B#MI"YGA,胾#E6tRQO.Q{ӫ[9nzj<i{ zk';:Q{l}o>gO^V}?LiB~u;~ɟ~k`WdIhIk7SWT d%⥓>f䃔skq೛6 al6"g1U^^^^^^^^^KZ|h'ך/'хְT% ?K|)?(bPkfZL7h2Eܷ-ڸ E_Jka؃Uq{ [vPtGt C\;3.\`>U{d7ea8DN?,,SK6PQߠ+pJqY = 2Z@z08z^UXQ8raEI-VǦ(NRU.JRIUxEJ>#"s)a/{4# EMaxg"?Gys_-#&\|";R^*849 t`h= /Jw?׏;hO*.RcD_%CqR *O"xONԃ|qۙ6ۏk@#,1ku|7|7|ooopY PE:8~/qB=%4qr9w ]%)JlX_)ʄS[N2h}cj6gz Gbq0W # U S~P!e1=uڀxd'\ #nj>晽 ?X)UPoAsK?.%eJAU J}8Aߧ[s-Bk\1f ƒ; R;k'Oh٥-mp5> tqIf8bb73 T= LgA\zue>_\Q: ,$%52)--0) yeൺooooRGYyyyyyyyyyyyxZfb;&dr}56ۏk@#,1ku|7|7|oooSuH]4zem%}4!^aO%Y3i4Hd$T0V *HukO# ԖZ.ߙ=`ͫ-EsvMMLB6FOu(@O۫, z'?ױQqñ#~pdD䈲& MMP葹\wSm0c5))ck,]p,1e6v4I֫,VSJ%%1ƌKh fZ޷Y tK5GEhI[1KK/y"j9!ѐ{@5?pNF 0)ey}k"2䭡Ktڇ1AH(`ĺ?\C{,&L g88дݲ5|cQ)orlhkLiwq)猛>Wۇ>af7F9>SRζ2oɽj1WdT]l_  XB0Sn1Vga$=Wz7trǏQsd㢘cۓLx3S?|aa~N;b΍Xs{K*Zcs}f1MnO'`uFZgGſݾ!x1ΖT.9ņaaI(U*r ,ybVQv) UV} xKt&)1J0,2xl1Pݟ'pFTrM:< ܪb&u245- K%W216%mM vzI0Z:U.O W2AL7yi57WL2ΰ諓#iJא#as=owƕ ڳQ7 ltQCǬa``Jk5x9ET$Ac Zn*B҂oQȝ()37X'Q/yZ~?Wᵙx^CAZ0`b3.F z/bc-yh[9Anu͓s_)||9N8.U!`q74~R^ {Ǧ'ܸ-nH65ohN7nELG〓!3dă<_}@#,1ku|7|7|ooo6ۏ2\<邟/ E uHq#'0;& qp t oo!^^^^^^^Pj~(}V\#CuRCw7T"+z'cE?tqY]iOF4e } :]E;Y̊׷8ҷ$B3cJ,Қ+ YTuMunk=*ߚ0W+Kc9ҟTQdOv R,$%J`A c:=KL BEx|}Vɶx¨e2OMqE9]BqΏקxdZ/+% 7ƱRnN,:\-Z<1Ҝto6=!+Qfh+c)U*^&d}dMC}#)%\)4 ́"QebGcaxq'hG3&OP,` M_[DKdJuea/ek,|C,@\W{{E,)FO*\hPː|JFZ-nܫgƻ,gn3 @JwH8h9 >łȚD[Q dă<_5{}B0l?Oo B0* bÍHH(ˠ3oĽ@}T>EO 򉝧|7:.TQ-U'Mu~Ҏ40&$tbX"xZ >l i{{l,E d&Xd1IQK&54Fx'Agb0Fx(-+IM4Gtj{aQzE ԈtΞr{kx7Av%]*8Fأ&SN6TֶMΞGJhaGcV+%x-6`k&[j+m֍O"5.t̜_IJ&z`Qf˂XhXO}ջ8SyN^qZqʃ틉-b ШrFs]Ѝb2$QW[9`m(I1G2+ԟ=kzw$rº~|-:nhhp[3U& &n+E|j.&ySwOa"IV6j/cqrɇD.Tȝ."\F\5'1"WKt&q/ 4NbΊp!\-rYV`zasUS?eywg k6h9IF7I>u,ѨWctO_8`};( R},Aϭ"J٨,k 34eϽ{uOid88雝1MYWunڮJE^@0l-slw;g~ubUV—UZFE2crAؼJ&?v9hw` J碌n P_@6ST&]$e~ lf lC{g%ơD+ub\sMH:7ab?_m ~]]q%ʇ Q|b*Dhgwkix3w;/LIёq|Lzqx(@2v k$)R⵨I8a7a;" i$V78(W{;}zQ@ۃS Vk=lx6uRHCJ&ILK0.[?wޞIt22+,T` lT:)H"߫;%Nmx?s=ѿhm'AvHgk6u%_ҝg ebӳv0`xq&87 1` if-Ϻ9i&_$ɱHH5kNktsucP|aKa,GG+%գF-@IY Z7-njF4qR2zcD fKDwaXୢԏWy@û%ɏ<ƺʁ'2"' ɸe43p6'Ώ :m]WB㥂~?GsJaK? LR+E‰gס.UxOQurS[Yd}1( FY变J5f(ͧ$f;- 1U=.LFWl9*'&ʍb_xm?$Ca+͖Ra7Õ*֯'Ք έ ;$"5 Tѯt\|f2wa\PXxtzsx3o?rI 9gBL A-O2"0-="۸)@Do>{SAƖyjG<wH5Jd)zs'6 {?#DZV701KEWI-Q@dc?JG/s/3%XiF m;3Ɵ7(pnsGCwS|d}Eu?ݮV0?&Zo(F%qTyChQ]pdcŧFg)}qTTpl ۥ?+h=ZHqd^77((~)p p3sx8 mj~ONrfx=lé[v4 agq{pe;Z+ogzHsо}G}I-:S8=R q"ZrAOLm|" ;<Jrg~fAwFtFrgD` QzwY5Z 3gPXoĉh1vxAaXچN";H%5#N!9t.l]cL[OB0Hqwf$IP'P;rjjRȁhi rǔ4Xh%̃>Eȸd`Eid׺,GI5h H5MVS9Dm5z&a_c㪷Ei>{I o:NٵAeՎW.VBUZB{Qv2 ,AP5\~Ml9*Ÿ?/-rfkgmsBg:RC֍-Y6Wt"TZUcµ{=EX,& an5 z?lXq[ivx\BR JYдN=Qz(TGm޷ei!AgM l `;md#h_/B)Mj>Wj_f @.{N+jXGǫov5Qz3^L3Tu܀y@iC<"Ds%Zc#kB}Sbu;8`]CM]ޡY6߸])djK*R8++.;4RXXn,'iv|+'. ٚ@x,0@~oh6ݑ:uwžEH~>;ҿ?ɪ@pڪ̢ֈ?sbV}Q=ڔOQ^0ցJ(R[fd*[ 孙#aRV*= |VH2~Df F-+ܝ`ɔ p'iۯaBCj{_ҬΔ͊w}0cd'{;yW3oLJl-̥$iN`$ky FLiɞ=<Lhk$+3a}G,IKSGnSK(LjISN{'̻; ~`n̅VLY͎dS XZ_D/t< Pa7[ Es^cPHDl`ZsW{.#v2&xzI3u) SYt^.O?=Lrqkbo:<6I;.k(Ɔ-|]eE{\#_9 L4b~DL=$ Y_ko[Fm$LC)Ei ,9<0… B42s+e 0 rD^0gq[ecPېI-)WOH8a'+NHj;WAtΠ?RDgUWo ts%aۍ! HI0X@'=, s:0,Oq5aRp ^F#tik˥ߞ kB69Ջ@*Ťj!c7Uv@\f q̷e8_+TʛS P UL_f+[^ҭ!@aј퓳wXנ ҨI:զ5λ{U#Rտ{8kqGLvbT `ɦmI?&ӽɅYl.e&"ydcbIװ V ږIZIЧc'~c?\\6j{ȸ ' 4xS[O?$L]n n񒩬xy[$Z^ľ@ 89F}b^vBx8CO-;<6$;p!&`ݫdnl0%w/34#M& }>sՊ_$23]~˜Ji-$m1uPN׃NfQ5)ZgD$ <tW\$%o=έP[">;h%:&t@w'tLn=vS7t5&`mv%KgғgX?9#C58$\0ٔLx6J[(T+ c@/bDL!@KSI)ш cewޜM:%B`EqԬ9ahbV택6 fyNl ]iC\Vhݟa{3},RJ"kofNW>5!mCXf\ŷpRhtŘ k,4yan’jjλv;C3|l5~lTi/S\܀?OMxZ#h! _g:+ͧj`/Ӡ` ?5qR;dI9 :8|lxq l?7MX|MYҸ )*0[9ɼ!m)(?> JJ,sc+)`p7j{G-(&ZGAvsb8_(r%c+fzXok-̪6liZ]JnԀ<;;XywwAvS?KG{# "Nce-p({9V +p^2"mU63kln-uW`-:bd/|)DFs[Q7N"D?#9j>Z<9?Cw+, U^ŖI)AZEl+ +Dﺛx\hCMBƍp,v٥UV$]Qj0xoa#ؤ@ء_W; wTk脈HJ۩1ahA?l\퉙mw|>ل 3"I@UM?dag\۸U":yh1Z:aTsKI>e\B\mj>ۆֿ[:hX6nu*Ԃӡ)e2&w \ 6) 0XenJXbNT!?v6Q-(š7NzU\1\Ȩlvaj&J"e I"8zR%T@T%dC[(5.fI, 'yՓp}RSW_mcՐ"mig?]A j `+Q,ctP]AEzGHTr3y']`DžRR{p#w~őub:ig9voA6f=a^x2`)!|[sBҪE$ B虲I(th%y(A#eORg ȟ5 I'_v+\Gj_D[P*)X~&|ڑ7a?6:QW #IQ(I[F @,(6Qb6bQ0tKqۣts53m1Ov/)-yh ) N2C'1Ovi起ZIQ`z"tIם%<&H@܍ O·  > kAcXEe ;g@e_Mb+J^q iY.~+?<}<dl "ۙԜ$T\0 y ~X' Fʙ”v^G*"?Zy~E @Z>Cg,řY%F:abAG{v{*~ככJ$SPŤjkod_X쿎mue9ukV?!0ͧ=ǩg {od? t C0 q> ,jFV:b4 etZ.3oe )RJe| 9w| ~A&5a+`LxZo\v| ǫ2BcөKǗZrs*k:noA^)tt$j}P_KQmicnV Bpyo/utils/info.plist0000644000175000017500000000510112652732202014023 0ustar tiagotiago CFBundleDevelopmentRegion English CFBundleDisplayName E-Pyo CFBundleDocumentTypes CFBundleTypeOSTypes TEXT CFBundleTypeExtensions py CFBundleTypeRole Editor CFBundleTypeIconFile E-PyoIconDoc.icns LSIsAppleDefaultForType CFBundleExecutable E-Pyo CFBundleIconFile E-PyoIcon.icns CFBundleIdentifier org.pythonmac.unspecified.E-Pyo CFBundleInfoDictionaryVersion 0.7.8 CFBundleName E-Pyo CFBundlePackageType APPL CFBundleShortVersionString 0.7.8 CFBundleSignature ???? CFBundleVersion 0.7.8 LSHasLocalizedDisplayName NSAppleScriptEnabled NSHumanReadableCopyright Copyright not specified NSMainNibFile MainMenu NSPrincipalClass NSApplication PyMainFileNames __boot__ PyOptions alias argv_emulation no_chdir optimize 0 prefer_ppc site_packages use_pythonpath PyResourcePackages PyRuntimeLocations @executable_path/../Frameworks/Python.framework/Versions/2.7/Python PythonInfoDict PythonExecutable @executable_path/../Frameworks/Python.framework/Versions/2.7/Python PythonLongVersion 2.7.8 (v2.7.8:ee879c0ffa11, Jun 29 2014, 21:07:35) \n[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] PythonShortVersion 2.7 py2app alias template app version 0.9 pyo/utils/Tutorial_01_RingMod.py0000644000175000017500000001761712652732202016126 0ustar tiagotiago""" Tutorial on creating a custom PyoObject. There are few steps we need to take care of in order to create a class with all of the PyoObject behaviors. Things to consider: - The parent class must be PyoObject, that means the PyoObject's __init__ method must be called inside the object's __init__ method to properly initialize PyoObject's basic attributes. - When a PyoObject receives another PyoObject, it looks for a list of objects called "self._base_objs". This list must contain the C implementation of the audio objects generating the output sound of the process. - Adding "mul" and "add" arguments (they act on objects in self._base_objs). - All PyoObjects support "list expansion". - All PyoObjects with sound in input support cross-fading between old and new sources. - We will probably want to override the play(), out() and stop() methods. - There is an attribute for any function that modify a parameter. - We should override the ctrl() method to allow a GUI to control parameters. In this tutorial, we will define a RingMod object with this definition: RingMod(input, freq=100, mul=1, add=0) """ from pyo import * # Step 1 - Declaring the class # We will create a new class called RingMod with PyoObject as its parent class. # Another good habit is to put a __doc__ string at the beginning of our classes. # Doing so will allow other users to retrieve the object's documentation with the # standard python help() function. class RingMod(PyoObject): """ Ring modulator. Ring modulation is a signal-processing effect in electronics performed by multiplying two signals, where one is typically a sine-wave or another simple waveform. :Parent: :py:class:`PyoObject` :Args: input : PyoObject Input signal to process. freq : float or PyoObject, optional Frequency, in cycles per second, of the modulator. Defaults to 100. >>> s = Server().boot() >>> s.start() >>> src = SfPlayer(SNDS_PATH+"/transparent.aif", loop=True, mul=.3) >>> lfo = Sine(.25, phase=[0,.5], mul=.5, add=.5) >>> ring = RingMod(src, freq=[800,1000], mul=lfo).out() """ # Step 2 - The __init__ method # This is the place where we have to take care of some of pyo's generic behaviours. # The most important thing to remember is that when a PyoObject receives another # PyoObject in input, it looks for an attribute called self._base_objs. This attribute # is a list of the object's base classes and is considered the audio output signal # of the object (the Sine object uses internally an object called Sine_base). The # getBaseObjects() method returns the list of base classes for a given PyoObject. We # will call the getBaseObjects() method on the objects generating the output signal of # our process. .play(), .out(), .stop() and .mix() methods act on this list. # We also need to add two arguments to the definition of the object: "mul" and "add". # The attributes "self._mul" and "self._add" are handled by the parent class and are # automatically applied to the objects stored in the list "self._base_objs". # Finally, we have to consider the "multi-channel expansion" feature, allowing lists given as # arguments to create multiple instances of our object and managing multiple audio streams. # Two functions help us to accomplish this: # convertArgsToLists(*args) : Return arguments converted to lists and the maximum list size. # wrap(list,i) : Return value at position "i" in "list" with wrap around len(list). def __init__(self, input, freq=100, mul=1, add=0): # Properly initialize PyoObject's basic attributes PyoObject.__init__(self, mul, add) # Keep references of all raw arguments self._input = input self._freq = freq # Using InputFader to manage input sound allows cross-fade when changing sources self._in_fader = InputFader(input) # Convert all arguments to lists for "multi-channel expansion" in_fader, freq, mul, add, lmax = convertArgsToLists(self._in_fader, freq, mul, add) # Apply processing self._mod = Sine(freq=freq, mul=in_fader) # Use a Sig object as a through to prevent modifying the "mul" attribute of self._mod self._ring = Sig(self._mod, mul=mul, add=add) # self._base_objs is the audio output seen by the outside world! self._base_objs = self._ring.getBaseObjects() # Step 3 - setXXX methods and attributes # Now, we will add methods and attributes getter and setter for all controllable # parameters. It should be noted that we use the setInput() method of the # InputFader object to change an input source. This object implements a cross-fade # between the old source and the new one with a cross-fade duration argument. # Here, we need to keep references of raw argument in order to get the # real current state when we call the dump() method. def setInput(self, x, fadetime=0.05): """ Replace the `input` attribute. :Args: x : PyoObject New signal to process. fadetime : float, optional Crossfade time between old and new input. Defaults to 0.05. """ self._input = x self._in_fader.setInput(x, fadetime) def setFreq(self, x): """ Replace the `freq` attribute. :Args: x : float or PyoObject New `freq` attribute. """ self._freq = x self._mod.freq = x @property # getter def input(self): """PyoObject. Input signal to process.""" return self._input @input.setter # setter def input(self, x): self.setInput(x) @property def freq(self): """float or PyoObject. Frequency of the modulator.""" return self._freq @freq.setter def freq(self, x): self.setFreq(x) # Step 4 - The ctrl() method # The ctrl() method of a PyoObject is used to pop-up a GUI to control the parameters # of the object. The initialization of sliders is done with a list of SLMap objects # where we can set the range of the slider, the type of scaling, the name of the # attribute linked to the slider and the initial value. We will define a default # "self._map_list" that will be used if the user doesn't provide one to the parameter # "map_list". If the object doesn't have any parameter to control with a GUI, this # method can be undefined. def ctrl(self, map_list=None, title=None, wxnoserver=False): self._map_list = [SLMap(10, 2000, "log", "freq", self._freq), SLMapMul(self._mul)] PyoObject.ctrl(self, map_list, title, wxnoserver) # Step 5 - Overriding the .play(), .stop() and .out() methods # Finally, we might want to override .play(), .stop() and .out() methods to be sure all # our internal PyoObjects are consequently managed instead of only objects in self._base_obj, # as it is in built-in objects. To handle properly the process for self._base_objs, we still # need to call the method that belongs to PyoObject. We return the returned value (self) of # these methods in order to possibly append the method to the object's creation. See the # definition of these methods in the PyoObject man page to understand the meaning of arguments. def play(self, dur=0, delay=0): self._mod.play(dur, delay) return PyoObject.play(self, dur, delay) def stop(self): self._mod.stop() return PyoObject.stop(self) def out(self, chnl=0, inc=1, dur=0, delay=0): self._mod.play(dur, delay) return PyoObject.out(self, chnl, inc, dur, delay) # Run the script to test the RingMod object. if __name__ == "__main__": s = Server().boot() src = SfPlayer(SNDS_PATH+"/transparent.aif", loop=True, mul=.3) src2 = SfPlayer(SNDS_PATH+"/accord.aif", loop=True, mul=.3) lfo = Sine(.25, phase=[0,.5], mul=.5, add=.5) ring = RingMod(src, freq=[800,1000], mul=lfo).out() s.gui(locals()) pyo/utils/E-Pyo.py0000755000175000017500000102050212652732202013324 0ustar tiagotiago#! /usr/bin/env python # encoding: utf-8 """ E-Pyo is a simple text editor especially configured to edit pyo audio programs. You can do absolutely everything you want with this piece of software. Olivier Belanger - 2012 TODO: - Fix printing to pdf - Output panel close button on OSX (display only) """ from __future__ import with_statement import sys import __builtin__ __builtin__.EPYO_APP_OPENED = True if sys.platform == "linux2": import wxversion if wxversion.checkInstalled("3.0"): wxversion.select("3.0") elif wxversion.checkInstalled("2.8"): wxversion.select("2.8") import os, string, inspect, keyword, wx, codecs, subprocess, unicodedata import contextlib, StringIO, shutil, copy, pprint, random, time, threading from types import UnicodeType, MethodType, ListType from wx.lib.wordwrap import wordwrap from wx.lib.embeddedimage import PyEmbeddedImage import wx.lib.colourselect as csel import wx.lib.scrolledpanel as scrolled import wx.lib.dialogs import wx.combo import wx.stc as stc import wx.lib.agw.flatnotebook as FNB from pyo import * from PyoDoc import ManualFrame reload(sys) sys.setdefaultencoding("utf-8") ################## SETUP ################## PLATFORM = sys.platform DEFAULT_ENCODING = sys.getdefaultencoding() ENCODING = sys.getfilesystemencoding() ENCODING_LIST = ["utf_8", "latin_1", "mac_roman", "cp1252", "cp1250", "utf_16"] ENCODING_DICT = {'cp-1250': 'cp1250', 'cp-1251': 'cp1251', 'cp-1252': 'cp1252', 'latin-1': 'latin_1', 'mac-roman': 'mac_roman', 'utf-8': 'utf_8', 'utf-16': 'utf_16', 'utf-16 (Big Endian)': 'utf_16_be', 'utf-16 (Little Endian)': 'utf_16_le', 'utf-32': 'utf_32', 'utf-32 (Big Endian)': 'utf_32_be', 'utf-32 (Little Endian)': 'utf_32_le'} APP_NAME = 'E-Pyo' APP_VERSION = PYO_VERSION OSX_APP_BUNDLED = False WIN_APP_BUNDLED = False ################## Utility Functions ################## @contextlib.contextmanager def stdoutIO(stdout=None): old = sys.stdout if stdout is None: stdout = StringIO.StringIO() sys.stdout = stdout yield stdout sys.stdout = old def convert_line_endings(temp, mode): #modes: 0 - Unix, 1 - Mac, 2 - DOS if mode == 0: temp = string.replace(temp, '\r\n', '\n') temp = string.replace(temp, '\r', '\n') elif mode == 1: temp = string.replace(temp, '\r\n', '\r') temp = string.replace(temp, '\n', '\r') elif mode == 2: import re temp = re.sub("\r(?!\n)|(?` `0`: `i -= 1` `print i` """ ASSERT_COMP = ''' `expression` `>` `0`, "`expression should be positive`" ''' BUILTINS_DICT = {"from": FROM_COMP, "try": TRY_COMP, "if": IF_COMP, "def": DEF_COMP, "class": CLASS_COMP, "for": FOR_COMP, "while": WHILE_COMP, "exec": EXEC_COMP, "raise": RAISE_COMP, "assert": ASSERT_COMP} ################## Interface Bitmaps ################## catalog = {} close_panel_icon_png = PyEmbeddedImage( "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAA29JREFU" "eJzcVclrE1EcfvPem8zQRRNrumQS6lYRFYLUgxZBccWToODeoIKiCC4HL/UfKPTgxVBsD1Lc" "ULSYUlxA8KaiVDGut5auMdWkaTozmeW98TdxoTRNerEXB14mZN77vt/3/b7fhDqOg+bzovOK" "/n8SCIKQv3swDofKygLjudzTSdvmRc7LtbK8GztOT8IwmLtpZk+LKfA2+v29B1esCD7v7488" "Gh29Yc4CXuXxvGpuaAgzTbt7Z3DwyJhlsTkVQOXrALznUmNjsJZztHTJklZu25ln37/3apz/" "USLXyHL05KpV4Z2Vlcik9ICkKInrIyMXXRElCZZVVKw5unJlHtzUNOTDOBAJhWLwKPIkmXSV" "5Ct3wbeUlSEhm0UY9m5dsGDTkK5j2MdKEiR1/e6LgYG65fX1LRVgFYHD1YSgE4rSijiffK9p" "e1xbdpWXIwTgonvIceLfLOvsF1Wd26KUZVkPhofbEGPp/YrS6YOm27aNFglCoLm29uEOStFq" "SULCxASyGHNDEe9nrCk6Nqa+nZqaCTd7k3OQhFgi0QWJ8B2tq2up4NxLLQst1nVUA3c7l0PO" "b/ABjE9FVVXtAztneycUnYMpzq3uRCKvZK/H01mZySAbwCEEiMPChHwYIKSpPZtVX7uERXBK" "DhookV9OTjZt8PvRWlCFAVgGixyXgNLFfZxv+2QYvQBebE5KEsiLRPHVgVAovAzkMyBwK3d+" "L5GQuh2SFBtiLPIok5ltTkoSyDWSFD0B4FsAHKVSSIIkcUI+UlEMUoy9rpJ6+O1CVVUrISTz" "eGJi+pyUJMhXfhzAN6oqctJpxN0kQUMHwfPPnB/aDj2pAQIBlkJp4Hx1dQzsi8R+/LgxJ0FA" "kvYdVpTwZogch8rFX02Nj1B6ql3T1K+m2ZXwen1nfL4Wvyh6yz0e1ABKLodC56Bnt9CMfhQQ" "wOB0k0ymz8hmGwVQbBMSH4LKO3RdffMrLda9dLqNYJw+4/d3loMKLIpooSBEKymd26Jhw9Bv" "M7ZZkqRr6xlbM0LI6Q7DUN8axt8ounNyP5XqAu99l4LBYxLGbVdHR2/2jI8X+F1A4M76kG2r" "1x2neVCWadw0rXemWZDzLMzJzWSyTXOcK1QQ7G4AnyrscSHBtPe5+8UqOFF42e5HV5GH/+Ff" "5r++fgIAAP//AwDHcZZetNGOQQAAAABJRU5ErkJggg==") catalog['close_panel_icon.png'] = close_panel_icon_png file_add_icon_png = PyEmbeddedImage( "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAABDBJREFU" "eJyMVV1IHFcU/mZ29ifZXbNutMbUxgSaJooiURT1IVQKUvpSpNifvEiwr6GB5kEoNIVSDAmS" "UmglkFCaH2xIU6k15MG0EmkwQpq4lfiTmG5rR+Ouu2bH/d/Zmem9E2c7M7trc4bD3pl77vfd" "891zz3L4z5hNfzGzw4q96EEHerkGrsFqszLpRHpa9skXMIZvsQQRCsDpltRUVFR86vF41BdF" "UcAwTMExNb6Eb5Helva1HWpD+yvt8Ng8CCQCLeO7x1t8Fb6PpJ+lLszgkZ5g28cnTrzX3d2t" "gqkPy+SAn397bpOrkzg2fQwddR1oq2zGNtGOStvLKLHZUdV0BGXestpb3lvD8lX5kJ4ANqsN" "drtDBWM3wc0upAWcenQKZdVlqCh1YT07j+rMa3hjTye+njuJDfcG9lfuwez+3bX8Yb7XQEA3" "y7JsUXBqd1bvwJf1ocF5EOHMHGxEsnjMRbVDPO5H3LGKsAg4PXaQM/rQRGDcOasBb46p/lOh" "uxAdIpJ/J7BrZwvcHINy16skhEW5WAss78CujIiNZ7OAF/UGAnp8rA6QIdlo2tOxLEkIZ8Nq" "adRbGnHy8FdqHMtYwLEcjrb2EQwFyUwSt3+6j6f2MPIyyIHqMtBcIV7KlarFPJEaw/s321Fu" "A5pcb6K39TN88UsPlpQFrKYV/Mk9pnFPjAQaSSEnxBYy3+hsgjVqRcgVwfz2CDJOIrVco+48" "6FjAPw4fnsSAWJIEhzCqJ1C0emdMEuXOwmJBW3krGoINuCfew0oEkAnQwR0SUlKK7FxWwQNp" "QLJgGb/hUr5EOkCzRNSrXqrCcf44+mJ94DM8lgjJtcgYJoOvYzH+GAJJU3IigFl8gh+MF009" "3KISbbrD4UBnbSfS99M4J5/DjHcGK8kIVrIRMG4GLocb7AT7ufCN8CM2kDIS6CQqdg+o0XbS" "1dKFAwsHMMVPYS41h7gSR2m2FPXkufHwxu+jwmiUxhaU6P8I6LikpATNjc2oq6lDNBqFKIqk" "C9jhdrvx4OYDUYs1ZrC52CyVYU73y3GcSkRBtSZoKGvyLe+iaT1bD7yVZbNZSOQCyrKc67qS" "rOQIX0gi/Zw2pgBUllQqRXpQHMlkUiUCa5ngl5dXCkrE6Ii2MgpOd06BA8EggoEg0pkMnM7t" "fwwPD39we/zXpwUJtLTM38yEVA6687W1EHh+Gfv2VoP8o4W/HxrquXD+/ArNpnAGuu5ZSB7t" "nUqRSCQQXFtTL6PX6/3rypXL7549++W0IAiGzeRVkV4qDdyckZZBLBZD2U7v/MWL3711+vQZ" "f5DIZVYhTyLNi5k2LxESq9W6ODIy8s7g4KB/fX294Do9QTIUCl31+/158uizoSAZUj2hZxHh" "2vXrZ4YuX1qkF62Y6Qnm+/v7jwwMDBQNNmdBKkfOiuKWsf8CAAD//wMAHNbcbWLj1ggAAAAA" "SUVORK5CYII=") catalog['file_add_icon.png'] = file_add_icon_png folder_add_icon_png = PyEmbeddedImage( "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAABShJREFU" "eJykVW1sU1UYfu5H721vv7t1DFbXDZmb2UR0QNAYJTELkR9AJBKJ8SMx0R8mZiRojAkJMUSj" "EBMkasSEH2ZO8IcIGWYh8ZuJgwg4gS3LFCcg+7Dt7bp1be+X7zltZ8cIkHhvT07v7Tnv8z7P" "+7ynMm7z8njc0VDA11RT7W9sbY7fWV8XXtbWeldj/dKWZZo/WiuJib2PPvZyZzKZnrdPrnwQ" "BKGuKhLsiIS0hrracCy2OHRHdViJN8Qi9N7nC4cjCEaWIBCJQwvGoHoCkOVZ+DwzSOo5jyA4" "CxKbB7CmvXn/h29uWr84qsCluuEIXphSFFDqIHuWQNWqILs0ONYszNxlyNIkFDcgCoCetm/I" "fB5AbJEWamr0wkAQqHocbi0CSXKV2fHZLMwilz6FYFiCQ7dAt0OJO45F4xYMwDbwQDLRDxN9" "BYVCgf9iWxZ0XUc2k0Q0lKU3GnhkCKWtdvnbzQAWXuPj43xjIBjkQ3QIkLKFbRYBSsz4860A" "OMXip7RXQCQchk0PhmHwwWRhwRw2KgDmnm8GwALywe5SYvl8HpZtcVQGJAgiZyDYBs9CqGAg" "3ECjm0rEMpJdVGSKJcsyCsSAgcNgDKR5DODcpkR8wJmja9tF+5lUZEmSkJ3JwSWSY4jB/5RI" "4BIY5CKRAovlQCU5LEsm6SRuAEk0ixLdisGCqxS0QHVgEjG5XIoHutGCgWQel6dTIGg0eGvg" "t/0dTc0t7cn+M79UMlkoUWlm0pQlYAy4TJTl96kL+Pj8UVyZnkQ5DANpi8QbO9/Z8W3vgS/X" "dXV1nTRNcyEAaSwXpRFgmhZE0toi7Zk9XaqCT//oxYHBHgRUD5qiteiofxCp/DSOj/6Ekezf" "2PX7Z/7tL2w5lkql1hw5cmS4EkBraarvfmLjAyt5/FJRBRrsuyy7cDYzhO6RHtQHPfDKApYG" "fXhx+WaM6FdxdqIPllvCVEHAB5cOh7e/9Oye/v6fN4yNjRcB3KqyeveOzRs7Hq6D4BTdYVBw" "ZkfLIquqIo6OHkXcryCsUjbk3KhHZKcQH1EPs4UNv0vAWHYWw+ro+kfWrg0dOnhI5wCiKKiR" "oMxmckOxsBZJRDyQJxfNSHkE5RHUVscQ8y+DKskIKiFI1HR+RcPKRfdCof6bKuQxmh5A2rog" "ta9qbyWAvrJE9vVtaHB5mP4mZpUpBFx5rKqNo6Oxs9jNKB5z9f7FJFUnZ53ITWH/uW3IFHS4" "varG6imX3FM8hkr2YjMrskPdaZGb3JJKXheQzo3iwuTXBCDD66pCPNiGGTOHS/qvJG0WGSNL" "fspAk9y0XpqYKzIh2eUmKx+/DMB2RH48RBAgWcIYSXyH4X++4etqvC14bkU3Lmeuoft8J3xS" "motgOwpqtA0Tl0b+vMiPmjmJrutD5iKR7GqQnzOpHFqr1uHU1d9olcmTsJ1CRf+YPITD1jsa" "GoT7d79/bKdRYVNhhvuhqFPJRSYvOntlEPzd/kcxERrAqN7LA5p2HmPTI0jOTpIsVvFfTdCw" "onrryXM9w3sHBwf/a7SCYZ4ZGEq+3tYced6jYikB5omBWySJPF6fQV19+toV/fh9gWfWh9Tq" "1UOJHui5a+gaeJr3iSab8CqN1M1bvvqrz3pqz+5dRvmQlIt6m9YrOz9560T/msNbN92TSmSD" "7zattKMz04lDw0ODX5w53Z/qO/EDFJfyxvZXtz257qG3X0vYF5fruavE0lUIKw196nTso96D" "P36+7719TjKZnJPvXwAAAP//AwDmNHbvm7mEowAAAABJRU5ErkJggg==") catalog['folder_add_icon.png'] = folder_add_icon_png refresh_tree_icon_png = PyEmbeddedImage( "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA" "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wIHETgo92WyxQAABKJJREFUSMfdlVtsVFUY" "hb9zmTNnZtoOLRel3ATkASiYQMI1YkTxQVMaxMQbCGJCAiY8KAY0aIQYb5CoJEo0RlEgaUwD" "clOUWwABBZFIgVKQi3RaZnqdmXbOOXPO2Wf7gFTRQcFH19NO9v7X+ve/VvLDP+C56qP/dM3U" "dfX8GxRuAh/Xtox3jGhFxqNnxlXcDtu9KOpPH/hk3qR2gNtX15FcNJzZH+1n3fwpACzdepI3" "KysKEy7bcwGAlYcb7n73XL72pTqRmfeT8KoO+fKefV4wZqdnD9/htg6qblv1zsSrTQ5+eccf" "9VtrhxX8weI9F1k1dTAvbj0e0vv0W5qP9VhxNguXuyBpSbI5sC0QdgCuABmgOdaRUGvrDOe9" "iibK3jImfDpvX7mae3tj5R2bCo5o+f7LPbqKSjekstaDZxqa6xoz+UxrVkbcrDZM2mYUoYMS" "BTUGgQAEqmefCucS89yS0hfkbUWPxPymys4VE7cB6NeI+wwZw1MffmEmUsnX6r6srj935MBb" "ttQbLMu2AmGEVE/cpvSf9ozoMWqBVDXQwlDcDzSTgNBIO9J/F64fI2HjZdqUgiPqXzE5nk6c" "G9CVbq4DRKFQGKPnTveGzfxM6uE4KlBUDpEykBIUAYog3Fhbla+ZvgVA/XN14uTBTFe6+eQN" "yAGke2LtZr1p3yxFc9JENJApIAU9NCg1oWcUQlp34yr/Ad7hVdvMY2umKyUh6F0MPRUozkJf" "A8ojEOue/B8e3Az6DRlJ44VT9L5nTrh93KxXZWkcYhEwQxDSIepDvARKQ9f/4KHH59yUQOOF" "U5RULYt33FVVE8SLpyphUMij+A6K70C+k7iaJQjcgiarQPgBwAYMIPS7GT7QXoSWGzreuZhs" "N2WvgZNkJKqg6QI9JAgZgpAhZMgQpWUxmbnYWh8c/Cx9ncAr247NzI8bU7MrKchmBOm0oLMj" "T77NQqa7UFsbftXPfTPJ/XZl062MtduDEyk3+LEZMi0BVspDpFxosSDroLZdOqEdWT3XPb+9" "6VYD0S1Q36XK9mawExqyKYCOALpAcXzM0xsWWue3H/8vieuOacLWpNXgI68EkDHAVsGXSFTs" "0YtqYlWfDwKIzFhfkCg+4dnu84BR9/1dwGsLIOVChwOWA0KA9EFYyEDcbkf6fxWdsX6UvWnW" "VcKqDwDoe+8iADLfv8/AKQuifcfNDjfU7v67AHYg6XAgZ6PkLfByELigKBDkCQJvhKWXHQo/" "XL0EILN5IQBX9q4GwJy8+Mlkp7eqvbHOLLhwzPnfVTrGgC1qrvOwmdz/ut1nYrUUfowgfzWs" "0gPhgCJRpe+o0tmJyDfj5gYGrjVN5tqv6Gc3VXotZ44VNFn6gaH57bVm8uijua8XNpgPvHe/" "WzJ0XRCIO8EHLQRGFIwwgaabAVSiBODbaIkfdoZ+2fR8vuVM7V+90a4dSkY8KGTnlTXW1qeT" "AP75HQkjHN2oGGaRDPJjCRxQFTAMMIuguAxN11v1hsNLOL52uZequ3TDndzrsXW0Vs8GoOfw" "qbTV7bnuUUnvQeX5itlPiOLysUTiUUXTknrq573O7jd2SEjzv8ZvVwomHyvQ89AAAAAASUVO" "RK5CYII=") catalog['refresh_tree_icon.png'] = refresh_tree_icon_png file_delete_icon_png = PyEmbeddedImage( "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAABEZJREFU" "eJyMVG1MW1UYfm57b1vogNLSdbotdJNkyAp+TOrYogZd4uJ+6GaYyg81auLHj7lEEpdFjfqH" "ZQTHDxP2g5m5jbC5MJQxZthgmWEMo5IOEBCJMNPC1hbsJy29H/Wcjou3X7i3edNzz8fzvO9z" "3vOy+M+YZb8v0wLcZuDN54G3trDsIxqWZRZjMcctSWq5Apz8G+DjZB+rOPOwxWL5zGAwJD7i" "8TgYhsk4plbgdD75oihaH62qwsadO6El58J37tgf7OuzW4aHP7wointHgD+VBDkf1dW9UlNT" "kwBL/FTMCvC9uXs2NzCAWwcOwPZsNdZtr4RazSIuxZFrtaKwthbGoqKtxt7ejnOS9LiSABpO" "A61WlwBTLYOn+pLPh8kjR1BsMaGgYjM463oEfr0GVpAQFbQwVFXDcPs2SsbGtj7tcr2dRECD" "ValUWcET0ff3QxoZxppntkAw58G8aw8i8QhcV87ioVfrYCp/AjO9PcjXamEF3kkhSI5cJQMv" "j6n+84ODyJV4aKJ/IHS1AaM6DmUvvQtDRRVyjGvxc9NhxG+0At4wjIAtiYBen0oByJBsZO3p" "WBJFCPPz0KjpFh4GjRdj3V/hAfsemDeVYOJ6D4K/nMRGUxjhBVJpATBpGayAKjKQPU6cKyyE" "IABLQcAfMsH2fhMK11kwN9yLku1Pgd//CULtX4DJiVLIv5IJZJJMTohJ4NBv24agioXHJWD9" "6++h2P4cpr77GJHJVojVn6Ns7wcYGh+Eb/AH+IGLSoK4XO9MikQrd6FWw7xjBzzlFRAcQ3B+" "cwL8jAOC60esKRTh/f5TBB0D8PVcRdSD2RvA6XSJFICpElFfu2EDnAcPInzoEJZ+n8WM8xI0" "ZsBXQM6Taop1XQAzC/e4iMPngckkAmSTR+E6nQ5lu3djKBYDd/w4dKOjiExFESbHOSKyLleP" "fr3qy68DgQsBIJpMoJAo2zugRtuJfd8+TJaWwnnzJqLj45DCYfBGUpjl5Rjp7v7N39UVpHsz" "SvR/BHScn5+PxyorUWqzIRgMgud50gW0yMvLw2WHg5f3JmewfDhVqqQ1xT/LsgkiCio3waSy" "JnNpD03u2Urg1Uwgj0IkD1CSpJWuK5LGJxPel0TKNXlMAags0Si5YKJ/JBJJEEGl/snpcs1m" "lIhREK1mFJxGToHvut1w33VjiVSVXp873NHR8dr1a31zGQnktFLnUgmpHDRyj8cLp9OFTdZi" "cBpu/mxb2xsnWlpmaTaZM1B0z0zyyN9UisXFRbg9nsRjNBqNM62tZ/YfO9bk8Pv9ScGkVZFS" "Khk8NSM5g1AohCKTceLUqW9fOHq0YdpN5EpVIU0i2bOZvC4SEo7jpjo7O19ubm6eXlhYyHhO" "SRDxer3npqen0+RRZkNBYqR6vP/4/Ofb2xvazpyeog8tmykJJurr62sbGxuzbk7NglSOJPD8" "qnv/BQAA//8DAPE93uTkTcJiAAAAAElFTkSuQmCC") catalog['file_delete_icon.png'] = file_delete_icon_png left_arrow_png = PyEmbeddedImage( "iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAppJREFU" "eJzsVFtLVFEUXnvObS5NTSRqFzANDHNC6sGXCKdA6qEL0T+I3opepJeCegjDl8goKLqAQb2n" "JVpBvoR0I6zUQLSxcsYZnWluOueyz967dc6MkYSV5GMbPtY++6zz7W/t9e0jwwoP+T/hb4fH" "4wkKIQqIlSFsaN7V2bQ7YvTdvXU2M5PI/jMhCQTVluOnjoVbDx55dP1y+5v+7juWXjQWEVZv" "aTxfsaEuQiQPwA9IQCTi1IhzjKSE6vpww7TJgKzbtL61rf1afeRw27Pbl058HXnbJzgrEdbs" "iDRubzkaIZoK4NWAIIRPxSiD0BQADckVCQRuRBiHmG4DmDYQg4NS11S79/SV3k/PH/cO9XSd" "ySc+f5BzRQti6Xn8EBP9uHtAgLAFEJu7EZgCRBMlQmcNFYJBkZCC0C0gpkQC2/Yc2FmxdX90" "sOecPJEowJfhaQCfBhD0A6wOIDCu8iJwzY/KfahUxvIpkukUoIiYMxE6QL7oRplLslKzLyxT" "tADlqITjAThucCyx4IoFe4gynByGE1S6ALQSaASmzJncTWO+2CWrlaGMEt4cdxrhNgQThIcA" "0U0QBqr4VgCCbAI35YoUMipDfrfjMgFVApMkM/dZKn+VW8YYS08UZVtRLnCft9NVgIdOLIZn" "h6W54OXI3HJJUOuAqrWHVI+gUjzdzydnb3DDfMHyiSyLDmDHXmLps/EpPv6+VBpHArd8h8Au" "zXETsLi7pm6syvmTa0bYx3gHy+tPxXwuxSYHGR9/go3Klo396gHA6+6/Mraobb7HrZMXha5H" "eWzYZKMPQWSi+IL/dFOch6Wv5uJBzQGeitr0XbcQ8SFUT39JWdbVo9OjFJJjaOy5JXOW9/ui" "xh9TVvx/+B0AAP//AwDd4UcxPpGF3gAAAABJRU5ErkJggg==") catalog['left_arrow.png'] = left_arrow_png left_arrow_png = PyEmbeddedImage( "iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAppJREFU" "eJzsVFtLVFEUXnvObS5NTSRqFzANDHNC6sGXCKdA6qEL0T+I3opepJeCegjDl8goKLqAQb2n" "JVpBvoR0I6zUQLSxcsYZnWluOueyz967dc6MkYSV5GMbPtY++6zz7W/t9e0jwwoP+T/hb4fH" "4wkKIQqIlSFsaN7V2bQ7YvTdvXU2M5PI/jMhCQTVluOnjoVbDx55dP1y+5v+7juWXjQWEVZv" "aTxfsaEuQiQPwA9IQCTi1IhzjKSE6vpww7TJgKzbtL61rf1afeRw27Pbl058HXnbJzgrEdbs" "iDRubzkaIZoK4NWAIIRPxSiD0BQADckVCQRuRBiHmG4DmDYQg4NS11S79/SV3k/PH/cO9XSd" "ySc+f5BzRQti6Xn8EBP9uHtAgLAFEJu7EZgCRBMlQmcNFYJBkZCC0C0gpkQC2/Yc2FmxdX90" "sOecPJEowJfhaQCfBhD0A6wOIDCu8iJwzY/KfahUxvIpkukUoIiYMxE6QL7oRplLslKzLyxT" "tADlqITjAThucCyx4IoFe4gynByGE1S6ALQSaASmzJncTWO+2CWrlaGMEt4cdxrhNgQThIcA" "0U0QBqr4VgCCbAI35YoUMipDfrfjMgFVApMkM/dZKn+VW8YYS08UZVtRLnCft9NVgIdOLIZn" "h6W54OXI3HJJUOuAqrWHVI+gUjzdzydnb3DDfMHyiSyLDmDHXmLps/EpPv6+VBpHArd8h8Au" "zXETsLi7pm6syvmTa0bYx3gHy+tPxXwuxSYHGR9/go3Klo396gHA6+6/Mraobb7HrZMXha5H" "eWzYZKMPQWSi+IL/dFOch6Wv5uJBzQGeitr0XbcQ8SFUT39JWdbVo9OjFJJjaOy5JXOW9/ui" "xh9TVvx/+B0AAP//AwDd4UcxPpGF3gAAAABJRU5ErkJggg==") catalog['left_arrow.png'] = left_arrow_png delete_all_markers_png = PyEmbeddedImage( "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAABUVJREFU" "eJykVWlsVFUYPW+Z5b2ZznSmnUI7pQt0KKZojCUNmIgVUgmNEYIaFxJXMP4SQlwaImokYhSj" "gagoQWOFCG2oplE0khDUQKAsDSFCC0hYytJ1OoXZ3+Z378zUliKQ+N7cvGXu/c53zne++2Tc" "4aEozkC+xx0qKsyrrKkun1YW9FXNrJleWTZ1RpWaF5gsiUMb5i98dWU4PDJunTz2QRCEYIHf" "2+DPVyuCk32lpcX5Uwp99vKKUj+9d7t9Pj+8/hJ4/OVQvaVwKB7IcgJuJYZwJKkIgjUhsXEA" "s2urN29at7ixOGCHzeGEJbigSwHAHoSslMChFkC2qbCMBPRkD2RpAHYnIApAZMS8KfNxAMFJ" "an6o0gUNXqBgCZyqH5Jky7HjVz2dQHLkELw+CRadAp0WJW5ZBo3bMBDYAh5IJvo+om9HOp3m" "/5mGgUgkgvj1MAL5cXqjgkdGBhiWmbv7b4CbHX19fXyhx+vlQ7QIkLKFqWcAssz48+0AOMXM" "L7tWgN/ng0kPmqbxwWRhwSw2xgCMPt9SIprMBzuziaVSKRimwVEZkCCInIFgajwLYQwD4SYa" "3VIilpFsoyJTLFmWkSYGDBwaYyCNYwDrDiXiA9YoXdPM2E+nIkuShHgsCZtIjiEG/1MigUug" "kYtECizmAmXlMAyZpJN4fEnQMxLdjsGEIxs0TXVgEjG5bHYFyVg1ot0xJHoHKboIR3EREnZ3" "Q2j6jNrwoc6jY5lMlCh7ZdLkJGAMMolrSB05gkst25Hs683yoSREEa6qUOXGN5r2bvpp14Kt" "27Yd0HV9IgBpLGekEaDrBq0zSAqD29NJ2Ufa23BlZysceXnw0BCyCZi0RO+5iNjmL/JWvLBs" "V3h4eHZ7e/vpsQDqjFDZ908smjOLx88WVaDB7mXZBuOv4xhoa4WvvAzBZ57F0K8/I3X2bwi0" "EXnmPgS5uASXW7cjuq3Zt/L55R93dBx8tLe3LwPgdNjr1q95bFHD3CBllXGHRsGZHQ3DgpN0" "HmjbAVVRMGn+wyiY1wD3XTXo+3Q9HGVlCCx7Bcxrw0cPI3GsE94zpxrrH6zP39HSEuEAoig4" "/F6ZXcH50mGQRMQDKXKRMxWH7dJ52mEVxCnzaOkUuCnrktVvQ1JUmFSD81u+BE53w6M6YZ48" "LtXV1tYQwP6cROaNbahxeZj+VKyRCGSyoU2xoF8+i4G1r0He8A2cNffyuVe2N0P79nOo/kLI" "Pi+S1yJw2x0qq6ecdU9mG8rai11ZkS3qToPcJNC3gcGb1wcgyINwzVsCe8U0ai6T90vR/Q9A" "2FMF7cwJWHERolJA86T+0SLTJDPXZLntlwGYlsi3B93rIyno43P1EtyNj6BwxVqYkh0Xt25E" "QSiEvDmNKHrnM1xtWg791HlI9ff1n7lw4STfakYluqEPmYtEsqtGfh5MpjB5/gJc+7oLRiQB" "7XoUPTubYf62CcOuPNLThBGoQHSE7AzaTmrr1u9a96E2xqZCzOJfJq5T1kU6Lzp7lSZ4a+Fi" "OI8dRPz3PYidexJGuAc2MoFBeg+ua0LCcsHR3w/H40sPtJ27uKGrq+vfRktreufx7vDqmdX+" "lxQHphJgihg4RZJIcbk16urD5yLR3YGXVzW62rbUxf/Yy2ZQP7IEWONcg+Kx4HjuxV92K4Gl" "H721RsttknJGb914/d3vPtjXMfvHpxffPTwU934SmmUGYtGhltPdXT90Hu4Y3r/vT9ht9vfe" "XLXiqfp5jU22E4fu0a/0UDFtaaG8an+4YuZXWw8ea934/horHA6PSv0PAAAA//8DAO+NgvJ9" "Mnw5AAAAAElFTkSuQmCC") catalog['delete_all_markers.png'] = delete_all_markers_png ############## Editor Key Commands Dict ############## KEY_COMMANDS = { "01. DOWN ARROW": "Move caret down one line", "02. Shift + DOWN ARROW": "Move caret down one line extending selection to new caret position", "03. UP ARROW": "Move caret up one line", "04. Shift + UP ARROW": "Move caret up one line extending selection to new caret position", "05. LEFT ARROW": "Move caret left one character", "06. Shift + LEFT ARROW": "Move caret left one character extending selection to new caret position", "07. RIGHT ARROW": "Move caret right one character", "08. Shift + RIGHT ARROW": "Move caret right one character extending selection to new caret position", "09. Alt + LEFT ARROW": "Move caret left one word", "10. Alt + Shift + LEFT ARROW": "Move caret left one word extending selection to new caret position", "11. Alt + RIGHT ARROW": "Move caret right one word", "12. Alt + Shift + RIGHT ARROW": "Move caret right one word extending selection to new caret position", "13. Ctrl/Cmd + LEFT ARROW": "Move caret to first position on display line", "14. Ctrl/Cmd + Shift + LEFT ARROW": "Move caret to first position on display line extending selection to new caret position", "15. Ctrl/Cmd + RIGHT ARROW": "Move caret to last position on line", "16. Ctrl/Cmd + Shift + RIGHT ARROW": "Move caret to last position on line extending selection to new caret position", "17. PRIOR": "Move caret one page up", "18. Shift + PRIOR": "Move caret one page up extending selection to new caret position", "19. NEXT": "Move caret one page down", "20. Shift + NEXT": "Move caret one page down extending selection to new caret position", "21. ESCAPE": "Cancel any modes such as call tip or auto-completion list display", "22. Alt + BACK": "Delete the word to the left of the caret", "23. Alt + Shift + BACK": "Delete the word to the right of the caret", "24. Ctrl/Cmd + BACK": "Delete back from the current position to the start of the line", "25. Ctrl/Cmd + Shift + BACK": "Delete forwards from the current position to the end of the line", "26. TAB": "If selection is empty or all on one line replace the selection with a tab character. If more than one line selected, indent the lines. In the middle of a word, trig the AutoCompletion of pyo keywords. Just after an open brace following a pyo keyword, insert its default arguments. Just after a complete python builtin keyword, insert a default structure snippet. Just after a variable name, representing a pyo object, followed by a dot, trig the AutoCompletion of the object's attributes.", "27. Shift + TAB": "Dedent the selected lines", "28. Alt + 'C'": "Line Copy", "29. Alt + 'D'": "Line Duplicate", "30. Alt + 'X'": "Line Cut", "31. Alt + 'V'": "Line Paste", "32. Alt + CLICK + DRAG": "Rectangular selection", "33. Shit + Return": "Show the init line of a pyo object in a tooltip", "34. Ctrl/Cmd + Return": "Show the __doc__ string of a python object, module or function", "35. CLICK in the most left margin": "Add a marker to the corresponding line", "36. Shift + CLICK on a marker": "Delete the marker" } ############## Allowed Extensions ############## ALLOWED_EXT = PREFERENCES.get("allowed_ext", ["py", "c5", "txt", "", "c", "h", "cpp", "hpp", "zy", "sh", "rst", "iss", "sg", "md", "jsfx-inc", "lua", "css"]) ############## Pyo keywords ############## tree = OBJECTS_TREE PYO_WORDLIST = [] for k1 in tree.keys(): if type(tree[k1]) == type({}): for k2 in tree[k1].keys(): if type(tree[k1][k2]) == type({}): for k3 in tree[k1][k2].keys(): for val in tree[k1][k2][k3]: PYO_WORDLIST.append(val) else: for val in tree[k1][k2]: PYO_WORDLIST.append(val) else: for val in tree[k1]: PYO_WORDLIST.append(val) PYO_WORDLIST.append("PyoObject") PYO_WORDLIST.append("PyoTableObject") PYO_WORDLIST.append("PyoMatrixObject") PYO_WORDLIST.append("PyoPVObject") PYO_WORDLIST.append("Server") ############## Styles Constants ############## if wx.Platform == '__WXMSW__': FONT_SIZE = 8 FONT_SIZE2 = 6 DEFAULT_FONT_FACE = 'Verdana' elif wx.Platform == '__WXMAC__': FONT_SIZE = 12 FONT_SIZE2 = 9 DEFAULT_FONT_FACE = 'Monaco' else: FONT_SIZE = 8 FONT_SIZE2 = 7 DEFAULT_FONT_FACE = 'Monospace' STYLES_GENERALS = ['default', 'background', 'selback', 'caret'] STYLES_TEXT_COMP = ['comment', 'commentblock', 'number', 'operator', 'string', 'triple', 'keyword', 'pyokeyword', 'class', 'function', 'linenumber'] STYLES_INTER_COMP = ['marginback', 'foldmarginback', 'markerfg', 'markerbg', 'bracelight', 'bracebad', 'lineedge'] STYLES_LABELS = {'default': 'Foreground', 'background': 'Background', 'selback': 'Selection', 'caret': 'Caret', 'comment': 'Comment', 'commentblock': 'Comment Block', 'number': 'Number', 'string': 'String', 'triple': 'Triple String', 'keyword': 'Python Keyword', 'pyokeyword': 'Pyo Keyword', 'class': 'Class Name', 'function': 'Function Name', 'linenumber': 'Line Number', 'operator': 'Operator', 'foldmarginback': 'Folding Margin Background', 'marginback': 'Number Margin Background', 'markerfg': 'Marker Foreground', 'markerbg': 'Marker Background', 'bracelight': 'Brace Match', 'bracebad': 'Brace Mismatch', 'lineedge': 'Line Edge'} with open(PREF_STYLE) as f: text = f.read() exec text in locals() try: STYLES = copy.deepcopy(style) except: STYLES = {'background': {'colour': '#FFFFFF'}, 'bracebad': {'colour': '#DD0000'}, 'bracelight': {'colour': '#AABBDD'}, 'caret': {'colour': '#000000'}, 'class': {'bold': 1, 'colour': '#000097', 'italic': 0, 'underline': 0}, 'comment': {'bold': 0, 'colour': '#0066FF', 'italic': 1, 'underline': 0}, 'commentblock': {'bold': 0, 'colour': u'#468EFF', 'italic': 1, 'underline': 0}, 'default': {'bold': 0, 'colour': '#000000', 'italic': 0, 'underline': 0}, 'foldmarginback': {'colour': '#D0D0D0'}, 'function': {'bold': 1, 'colour': '#0000A2', 'italic': 0, 'underline': 0}, 'keyword': {'bold': 1, 'colour': '#0000FF', 'italic': 0, 'underline': 0}, 'lineedge': {'colour': '#DDDDDD'}, 'linenumber': {'bold': 0, 'colour': '#000000', 'italic': 0, 'underline': 0}, 'marginback': {'colour': '#B0B0B0'}, 'markerbg': {'colour': '#000000'}, 'markerfg': {'colour': '#CCCCCC'}, 'number': {'bold': 1, 'colour': '#0000CD', 'italic': 0, 'underline': 0}, 'operator': {'bold': 1, 'colour': '#000000', 'italic': 0, 'underline': 0}, 'pyokeyword': {'bold': 1, 'colour': '#5555FF', 'italic': 0, 'underline': 0}, 'selback': {'colour': '#C0DFFF'}, 'string': {'bold': 0, 'colour': '#036A07', 'italic': 0, 'underline': 0}, 'triple': {'bold': 0, 'colour': '#03BA07', 'italic': 0, 'underline': 0}} if not STYLES.has_key('face'): STYLES['face'] = DEFAULT_FONT_FACE if not STYLES.has_key('size'): STYLES['size'] = FONT_SIZE if not STYLES.has_key('size2'): STYLES['size2'] = FONT_SIZE2 STYLES_PREVIEW_TEXT = '''# Comment ## Comment block from pyo import * class Bidule: """ Tripe string. """ def __init__(self): "Single string" self.osc = Sine(freq=100, mul=0.2) ''' snip_faces = {'face': DEFAULT_FONT_FACE, 'size': FONT_SIZE} ##### Data Event for processing events from the running thread ##### wxDATA_EVENT = wx.NewEventType() def EVT_DATA_EVENT(win, func): win.Connect(-1, -1, wxDATA_EVENT, func) class DataEvent(wx.PyEvent): def __init__(self, data): wx.PyEvent.__init__(self) self.SetEventType(wxDATA_EVENT) self.data = data def Clone (self): self.__class__ (self.GetId()) class RunningThread(threading.Thread): def __init__(self, path, cwd, event_receiver): threading.Thread.__init__(self) self.path = path self.cwd = cwd self.event_receiver = event_receiver self.terminated = False self.pid = None def setFileName(self, filename): self.filename = filename def setPID(self, pid): self.pid = pid def kill(self): self.terminated = True if PLATFORM == "win32": try: os.system("Taskkill /PID %d /F" % self.proc.pid) except: print '"Taskkill" does not succeed to kill the process %d.' % self.proc.pid else: self.proc.terminate() if self.proc.poll() == None: self.proc.kill() def run(self): if OSX_APP_BUNDLED: vars_to_remove = "PYTHONHOME PYTHONPATH EXECUTABLEPATH RESOURCEPATH ARGVZERO PYTHONOPTIMIZE" prelude = "export -n %s;export PATH=/usr/local/bin:/usr/local/lib:$PATH;" % vars_to_remove if CALLER_NEED_TO_INVOKE_32_BIT: self.proc = subprocess.Popen(['%s%s%s -u "%s"' % (prelude, SET_32_BIT_ARCH, WHICH_PYTHON, self.path)], shell=True, cwd=self.cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) else: self.proc = subprocess.Popen(['%s%s -u "%s"' % (prelude, WHICH_PYTHON, self.path)], cwd=self.cwd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) elif PLATFORM == "darwin": if CALLER_NEED_TO_INVOKE_32_BIT: self.proc = subprocess.Popen(['%s%s -u "%s"' % (SET_32_BIT_ARCH, WHICH_PYTHON, self.path)], shell=True, cwd=self.cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) else: self.proc = subprocess.Popen(['%s -u "%s"' % (WHICH_PYTHON, self.path)], cwd=self.cwd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) elif PLATFORM == "win32": self.proc = subprocess.Popen([WHICH_PYTHON, "-u", self.path], cwd=self.cwd, shell=False, # TODO: shell=True ? stdout=subprocess.PIPE, stderr=subprocess.STDOUT) else: self.proc = subprocess.Popen([WHICH_PYTHON, "-u", self.path], cwd=self.cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) header = '=== Output log of process "%s", launched: %s ===\n' % (self.filename, time.strftime('"%d %b %Y %H:%M:%S"', time.localtime())) data_event = DataEvent({"log": header, "pid": self.pid, "filename": self.filename, "active": True}) wx.PostEvent(self.event_receiver, data_event) while self.proc.poll() == None and not self.terminated: log = "" for line in self.proc.stdout.readline(): log = log + line log = log.replace(">>> ", "").replace("... ", "") data_event = DataEvent({"log": log, "pid": self.pid, "filename": self.filename, "active": True}) wx.PostEvent(self.event_receiver, data_event) sys.stdout.flush() time.sleep(.025) stdout, stderr = self.proc.communicate() output = "" if stdout is not None: output = output + stdout if stderr is not None: output = output + stderr output = output.replace(">>> ", "").replace("... ", "") if "StartNotification name = default" in output: output = output.replace("StartNotification name = default", "") if "epyo_tempfile.py" in output: try: findpos = output.find("epyo_tempfile.py") pos = findpos while (output[pos] != '"'): pos -= 1 startpos = pos + 1 pos = findpos while (output[pos] != '"'): pos += 1 endpos = pos output = output[:startpos] + self.filename + output[endpos:] pos = startpos + len(self.filename) slinepos = pos + 8 pos = slinepos while (output[pos] != ',' and output[pos] != '\n'): pos += 1 elinepos = pos linenum = int(output[slinepos:elinepos].strip()) output = output[:slinepos] + str(linenum-3) + output[elinepos:] except: pass if self.terminated: output = output + "\n=== Process killed. ===" data_event = DataEvent({"log": output, "pid": self.pid, "filename": self.filename, "active": False}) wx.PostEvent(self.event_receiver, data_event) class BackgroundServerThread(threading.Thread): def __init__(self, cwd, event_receiver): threading.Thread.__init__(self) self.cwd = cwd self.event_receiver = event_receiver self.terminated = False self.pid = None def setPID(self, pid): self.pid = pid def kill(self): self.terminated = True self.proc.stdin.write("_quit_()\n") if self.proc.poll() == None: self.proc.kill() def sendText(self, text): for line in text.splitlines(): self.proc.stdin.write(line + "\n") self.proc.stdin.write("\n") def run(self): if PLATFORM == "win32": self.proc = subprocess.Popen( [WHICH_PYTHON, '-i', os.path.join(TEMP_PATH, "background_server.py")], shell=True, cwd=self.cwd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT) else: self.proc = subprocess.Popen( ["%s -i -u %s" % (WHICH_PYTHON, os.path.join(TEMP_PATH, "background_server.py"))], cwd=self.cwd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE) header = '=== Output log of background server, launched: %s ===\n' % time.strftime('"%d %b %Y %H:%M:%S"', time.localtime()) data_event = DataEvent({"log": header, "pid": self.pid, "filename": 'background_server.py', "active": True}) wx.PostEvent(self.event_receiver, data_event) while self.proc.poll() == None and not self.terminated: log = "" for line in self.proc.stdout.readline(): log = log + line log = log.replace(">>> ", "").replace("... ", "") data_event = DataEvent({"log": log, "pid": self.pid, "filename": 'background_server.py', "active": True}) wx.PostEvent(self.event_receiver, data_event) sys.stdout.flush() time.sleep(.025) stdout, stderr = self.proc.communicate() output = "" if stdout is not None: output = output + stdout if stderr is not None: output = output + stderr output = output.replace(">>> ", "").replace("... ", "") if "StartNotification name = default" in output: output = output.replace("StartNotification name = default", "") if "background_server.py" in output: try: findpos = output.find("background_server.py") pos = findpos while (output[pos] != '"'): pos -= 1 startpos = pos + 1 pos = findpos while (output[pos] != '"'): pos += 1 endpos = pos output = output[:startpos] + self.filename + output[endpos:] pos = startpos + len(self.filename) slinepos = pos + 8 pos = slinepos while (output[pos] != ',' and output[pos] != '\n'): pos += 1 elinepos = pos linenum = int(output[slinepos:elinepos].strip()) output = output[:slinepos] + str(linenum-3) + output[elinepos:] except: pass if self.terminated: output = output + "\n=== Process killed. ===" data_event = DataEvent({"log": output, "pid": self.pid, "filename": 'background_server.py', "active": False}) wx.PostEvent(self.event_receiver, data_event) class KeyCommandsFrame(wx.Frame): def __init__(self, parent): wx.Frame.__init__(self, parent, wx.ID_ANY, title="Editor Key Commands List", size=(650,550)) self.menuBar = wx.MenuBar() menu1 = wx.Menu() menu1.Append(351, "Close\tCtrl+W") self.menuBar.Append(menu1, 'File') self.SetMenuBar(self.menuBar) self.Bind(wx.EVT_MENU, self.close, id=351) self.Bind(wx.EVT_CLOSE, self.close) panel = scrolled.ScrolledPanel(self) mainSizer = wx.BoxSizer(wx.VERTICAL) box = wx.FlexGridSizer(len(KEY_COMMANDS), 2, 15, 15) if PLATFORM == "darwin": accel = "Cmd" else: accel = "Ctrl" for key, value in sorted(KEY_COMMANDS.items()): short = key.replace("Ctrl/Cmd", accel) command = wx.StaticText(panel, wx.ID_ANY, label=short) box.Add(command, 0, wx.ALIGN_LEFT) action = wx.StaticText(panel, wx.ID_ANY, label=wordwrap(value, 350, wx.ClientDC(self))) box.Add(action, 1, wx.ALIGN_LEFT) mainSizer.Add(box, 1, wx.ALL, 15) panel.SetSizer(mainSizer) panel.SetAutoLayout(1) panel.SetupScrolling() def close(self, evt): self.Hide() class EditorPreview(stc.StyledTextCtrl): def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style= wx.SUNKEN_BORDER | wx.WANTS_CHARS): stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style) self.SetSTCCursor(2) self.panel = parent self.Colourise(0, -1) self.SetCurrentPos(0) self.SetText(STYLES_PREVIEW_TEXT) self.SetIndent(4) self.SetBackSpaceUnIndents(True) self.SetTabIndents(True) self.SetTabWidth(4) self.SetUseTabs(False) self.SetEOLMode(wx.stc.STC_EOL_LF) self.SetUseHorizontalScrollBar(False) self.SetReadOnly(True) self.SetProperty("fold", "1") self.SetProperty("tab.timmy.whinge.level", "1") self.SetMargins(5,5) self.SetUseAntiAliasing(True) self.SetEdgeColour(STYLES["lineedge"]['colour']) self.SetEdgeMode(stc.STC_EDGE_LINE) self.SetEdgeColumn(60) self.SetMarginType(0, stc.STC_MARGIN_SYMBOL) self.SetMarginWidth(0, 12) self.SetMarginMask(0, ~wx.stc.STC_MASK_FOLDERS) self.SetMarginSensitive(0, True) self.SetMarginType(1, stc.STC_MARGIN_NUMBER) self.SetMarginWidth(1, 28) self.SetMarginMask(1, 0) self.SetMarginSensitive(1, False) self.SetMarginType(2, stc.STC_MARGIN_SYMBOL) self.SetMarginWidth(2, 12) self.SetMarginMask(2, stc.STC_MASK_FOLDERS) self.SetMarginSensitive(2, True) self.setStyle() self.MarkerAdd(2, 0) wx.CallAfter(self.SetAnchor, 0) self.Refresh() def setStyle(self): def buildStyle(forekey, backkey=None, smallsize=False): if smallsize: st = "face:%s,fore:%s,size:%s" % (STYLES['face'], STYLES[forekey]['colour'], STYLES['size2']) else: st = "face:%s,fore:%s,size:%s" % (STYLES['face'], STYLES[forekey]['colour'], STYLES['size']) if backkey: st += ",back:%s" % STYLES[backkey]['colour'] if STYLES[forekey].has_key('bold'): if STYLES[forekey]['bold']: st += ",bold" if STYLES[forekey]['italic']: st += ",italic" if STYLES[forekey]['underline']: st += ",underline" return st self.StyleSetSpec(stc.STC_STYLE_DEFAULT, buildStyle('default', 'background')) self.StyleClearAll() # Reset all to be like the default self.MarkerDefine(0, stc.STC_MARK_SHORTARROW, STYLES['markerbg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_ARROW, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_ARROWDOWN, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_LCORNERCURVE, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.StyleSetSpec(stc.STC_STYLE_DEFAULT, buildStyle('default', 'background')) self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, buildStyle('linenumber', 'marginback', True)) self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, buildStyle('default')) self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, buildStyle('default', 'bracelight') + ",bold") self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, buildStyle('default', 'bracebad') + ",bold") self.SetLexer(stc.STC_LEX_PYTHON) self.SetKeyWords(0, " ".join(keyword.kwlist) + " None True False ") self.SetKeyWords(1, " ".join(PYO_WORDLIST)) self.StyleSetSpec(stc.STC_P_DEFAULT, buildStyle('default')) self.StyleSetSpec(stc.STC_P_COMMENTLINE, buildStyle('comment')) self.StyleSetSpec(stc.STC_P_NUMBER, buildStyle('number')) self.StyleSetSpec(stc.STC_P_STRING, buildStyle('string')) self.StyleSetSpec(stc.STC_P_CHARACTER, buildStyle('string')) self.StyleSetSpec(stc.STC_P_WORD, buildStyle('keyword')) self.StyleSetSpec(stc.STC_P_WORD2, buildStyle('pyokeyword')) self.StyleSetSpec(stc.STC_P_TRIPLE, buildStyle('triple')) self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, buildStyle('triple')) self.StyleSetSpec(stc.STC_P_CLASSNAME, buildStyle('class')) self.StyleSetSpec(stc.STC_P_DEFNAME, buildStyle('function')) self.StyleSetSpec(stc.STC_P_OPERATOR, buildStyle('operator')) self.StyleSetSpec(stc.STC_P_IDENTIFIER, buildStyle('default')) self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, buildStyle('commentblock')) self.SetEdgeColour(STYLES["lineedge"]['colour']) self.SetCaretForeground(STYLES['caret']['colour']) self.SetSelBackground(1, STYLES['selback']['colour']) self.SetFoldMarginColour(True, STYLES['foldmarginback']['colour']) self.SetFoldMarginHiColour(True, STYLES['foldmarginback']['colour']) self.SetEdgeColumn(60) # WxPython 3 needs the lexer to be set before folding property self.SetProperty("fold", "1") class ComponentPanel(scrolled.ScrolledPanel): def __init__(self, parent, size): scrolled.ScrolledPanel.__init__(self, parent, wx.ID_ANY, pos=(0,0), size=size, style=wx.SUNKEN_BORDER) self.SetBackgroundColour("#FFFFFF") self.buttonRefs = {} self.bTogRefs = {} self.iTogRefs = {} self.uTogRefs = {} mainSizer = wx.BoxSizer(wx.VERTICAL) for component in STYLES_TEXT_COMP: box = wx.BoxSizer(wx.HORIZONTAL) label = wx.StaticText(self, wx.ID_ANY, label=STYLES_LABELS[component]) box.Add(label, 1, wx.EXPAND|wx.TOP|wx.LEFT, 3) btog = wx.ToggleButton(self, wx.ID_ANY, label="B", size=(24,20)) btog.SetValue(STYLES[component]['bold']) box.Add(btog, 0, wx.TOP|wx.ALIGN_RIGHT, 1) btog.Bind(wx.EVT_TOGGLEBUTTON, self.OnBToggleButton) self.bTogRefs[btog] = component itog = wx.ToggleButton(self, wx.ID_ANY, label="I", size=(24,20)) itog.SetValue(STYLES[component]['italic']) box.Add(itog, 0, wx.TOP|wx.ALIGN_RIGHT, 1) itog.Bind(wx.EVT_TOGGLEBUTTON, self.OnIToggleButton) self.iTogRefs[itog] = component utog = wx.ToggleButton(self, wx.ID_ANY, label="U", size=(24,20)) utog.SetValue(STYLES[component]['underline']) box.Add(utog, 0, wx.TOP|wx.ALIGN_RIGHT, 1) utog.Bind(wx.EVT_TOGGLEBUTTON, self.OnUToggleButton) self.uTogRefs[utog] = component box.AddSpacer(20) selector = csel.ColourSelect(self, -1, "", hex_to_rgb(STYLES[component]['colour']), size=(20,20)) box.Add(selector, 0, wx.TOP|wx.ALIGN_RIGHT, 1) selector.Bind(csel.EVT_COLOURSELECT, self.OnSelectColour) self.buttonRefs[selector] = component mainSizer.Add(box, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, 10) mainSizer.Add(wx.StaticLine(self), 0, wx.LEFT|wx.RIGHT|wx.EXPAND, 1) for component in STYLES_INTER_COMP: box = wx.BoxSizer(wx.HORIZONTAL) label = wx.StaticText(self, wx.ID_ANY, label=STYLES_LABELS[component]) box.Add(label, 1, wx.EXPAND|wx.TOP|wx.LEFT, 3) selector = csel.ColourSelect(self, -1, "", hex_to_rgb(STYLES[component]['colour']), size=(20,20)) box.Add(selector, 0, wx.TOP|wx.ALIGN_RIGHT, 1) selector.Bind(csel.EVT_COLOURSELECT, self.OnSelectColour) self.buttonRefs[selector] = component mainSizer.Add(box, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, 10) if component != STYLES_INTER_COMP[-1]: mainSizer.Add(wx.StaticLine(self), 0, wx.LEFT|wx.RIGHT|wx.EXPAND, 1) self.SetSizer(mainSizer) self.SetAutoLayout(1) self.SetupScrolling() h = label.GetSize()[1]+6 num_rows = len(STYLES_TEXT_COMP) + len(STYLES_INTER_COMP) self.SetMaxSize((-1, h*num_rows)) def reset(self): for but, name in self.buttonRefs.items(): but.SetColour(hex_to_rgb(STYLES[name]['colour'])) for tog, name in self.bTogRefs.items(): tog.SetValue(STYLES[name]['bold']) for tog, name in self.iTogRefs.items(): tog.SetValue(STYLES[name]['italic']) for tog, name in self.uTogRefs.items(): tog.SetValue(STYLES[name]['underline']) def OnSelectColour(self, event): col = wx.Colour(*event.GetValue()) col = col.GetAsString(wx.C2S_HTML_SYNTAX) key = self.buttonRefs[event.GetEventObject()] STYLES[key]['colour'] = col self.GetParent().GetParent().editorPreview.setStyle() def OnBToggleButton(self, event): value = event.GetInt() key = self.bTogRefs[event.GetEventObject()] STYLES[key]['bold'] = value self.GetParent().GetParent().editorPreview.setStyle() def OnIToggleButton(self, event): value = event.GetInt() key = self.iTogRefs[event.GetEventObject()] STYLES[key]['italic'] = value self.GetParent().GetParent().editorPreview.setStyle() def OnUToggleButton(self, event): value = event.GetInt() key = self.uTogRefs[event.GetEventObject()] STYLES[key]['underline'] = value self.GetParent().GetParent().editorPreview.setStyle() class ColourEditor(wx.Frame): def __init__(self, parent, title, pos, size): wx.Frame.__init__(self, parent, -1, title, pos, size) self.SetMinSize((500,550)) self.SetMaxSize((500,-1)) self.menuBar = wx.MenuBar() menu1 = wx.Menu() menu1.Append(350, "Close\tCtrl+W") self.menuBar.Append(menu1, 'File') self.SetMenuBar(self.menuBar) self.Bind(wx.EVT_MENU, self.close, id=350) self.Bind(wx.EVT_CLOSE, self.close) self.cur_style = "" self.panel = wx.Panel(self) self.panel.SetAutoLayout(True) mainSizer = wx.BoxSizer(wx.VERTICAL) self.panel.SetSizer(mainSizer) toolbar = wx.ToolBar(self.panel, -1) saveButton = wx.Button(toolbar, wx.ID_ANY, label="Save Style") saveButton.Bind(wx.EVT_BUTTON, self.OnSave) toolbar.AddControl(saveButton) toolbar.AddSeparator() toolbar.AddControl(wx.StaticText(toolbar, wx.ID_ANY, label="Edit Style:")) choices = [f for f in os.listdir(STYLES_PATH) if f[0] != "."] self.choiceMenu = wx.Choice(toolbar, wx.ID_ANY, choices=choices) self.choiceMenu.SetStringSelection(PREFERENCES.get("pref_style", "Default")) self.choiceMenu.Bind(wx.EVT_CHOICE, self.OnStyleChoice) toolbar.AddControl(self.choiceMenu) toolbar.AddSeparator() deleteButton = wx.Button(toolbar, wx.ID_ANY, label="Delete Style") deleteButton.Bind(wx.EVT_BUTTON, self.OnDelete) toolbar.AddControl(deleteButton) toolbar.Realize() mainSizer.Add(toolbar, 0, wx.EXPAND) enum = wx.FontEnumerator() enum.EnumerateFacenames(fixedWidthOnly=True) facelist = enum.GetFacenames() facelist.sort() buttonData = [ (STYLES_GENERALS[0], STYLES['default']['colour'], (50, 24), STYLES_LABELS['default']), (STYLES_GENERALS[1], STYLES['background']['colour'], (50, 24), STYLES_LABELS['background']), (STYLES_GENERALS[2], STYLES['selback']['colour'], (50, 24), STYLES_LABELS['selback']), (STYLES_GENERALS[3], STYLES['caret']['colour'], (50, 24), STYLES_LABELS['caret']) ] self.buttonRefs = {} section1Sizer = wx.BoxSizer(wx.HORIZONTAL) buttonSizer1 = wx.FlexGridSizer(0, 2, 25, 5) for name, color, size, label in buttonData[:2]: b = csel.ColourSelect(self.panel, -1, "", hex_to_rgb(color), size=size) b.Bind(csel.EVT_COLOURSELECT, self.OnSelectColour) self.buttonRefs[b] = name buttonSizer1.AddMany([(wx.StaticText(self.panel, -1, label+":"), 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL), (b, 0, wx.LEFT|wx.RIGHT, 5)]) section1Sizer.Add(buttonSizer1, 0, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.ALIGN_LEFT, 10) section1Sizer.AddSpacer(110) buttonSizer2 = wx.FlexGridSizer(0, 2, 25, 5) for name, color, size, label in buttonData[2:4]: b = csel.ColourSelect(self.panel, -1, "", hex_to_rgb(color), size=size) b.Bind(csel.EVT_COLOURSELECT, self.OnSelectColour) self.buttonRefs[b] = name buttonSizer2.AddMany([(wx.StaticText(self.panel, -1, label+":"), 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL), (b, 0, wx.LEFT|wx.RIGHT, 5)]) section1Sizer.Add(buttonSizer2, 0, wx.LEFT|wx.RIGHT|wx.TOP|wx.ALIGN_RIGHT, 10) mainSizer.Add(section1Sizer, 0, wx.LEFT|wx.RIGHT|wx.TOP, 10) self.components = ComponentPanel(self.panel, size=(480, 100)) mainSizer.Add(self.components, 1, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, 10) mainSizer.Add(wx.StaticLine(self.panel), 0, wx.LEFT|wx.RIGHT|wx.EXPAND, 10) faceBox = wx.BoxSizer(wx.HORIZONTAL) faceLabel = wx.StaticText(self.panel, wx.ID_ANY, "Font Face:") faceBox.Add(faceLabel, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5) self.facePopup = wx.ComboBox(self.panel, wx.ID_ANY, STYLES['face'], size=(250, -1), choices=facelist, style=wx.CB_READONLY) faceBox.Add(self.facePopup, 1, wx.ALL|wx.EXPAND, 5) self.faceView = wx.StaticText(self.panel, wx.ID_ANY, STYLES['face']) self.font = self.faceView.GetFont() self.font.SetFaceName(STYLES['face']) self.faceView.SetFont(self.font) faceBox.Add(self.faceView, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5) self.facePopup.Bind(wx.EVT_COMBOBOX, self.OnFaceSelected) mainSizer.Add(faceBox, 0, wx.ALL|wx.EXPAND, 10) mainSizer.Add(wx.StaticLine(self.panel), 0, wx.LEFT|wx.RIGHT|wx.EXPAND, 10) mainSizer.Add(wx.StaticText(self.panel, wx.ID_ANY, label="Preview"), 0, wx.TOP|wx.CENTER, 10) self.editorPreview = EditorPreview(self.panel, wx.ID_ANY, size=(400, 180)) mainSizer.Add(self.editorPreview, 0, wx.ALL|wx.EXPAND, 10) self.panel.Layout() def setCurrentStyle(self, st): self.cur_style = st self.choiceMenu.SetStringSelection(st) self.editorPreview.setStyle() def close(self, evt): self.Hide() if self.cur_style != "": self.GetParent().setStyle(self.cur_style) def OnDelete(self, event): if self.cur_style != "": os.remove(os.path.join(STYLES_PATH, self.cur_style)) choices = [f for f in os.listdir(STYLES_PATH) if f[0] != "."] self.choiceMenu.SetItems(choices) self.choiceMenu.SetSelection(0) evt = wx.CommandEvent(10006, self.choiceMenu.GetId()) evt.SetInt(0) evt.SetString(choices[0]) self.choiceMenu.ProcessEvent(evt) self.GetParent().rebuildStyleMenu() def OnSave(self, event): dlg = wx.TextEntryDialog(self, "Enter the Style's name:", 'Save Style') dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: name = dlg.GetValue() if name != "": self.cur_style = name with open(os.path.join(STYLES_PATH, name), "w") as f: texttosave = pprint.pformat(STYLES, width=120) f.write("style = " + texttosave) choices = [f for f in os.listdir(STYLES_PATH) if f[0] != "."] self.choiceMenu.SetItems(choices) self.choiceMenu.SetStringSelection(name) self.GetParent().rebuildStyleMenu() def OnStyleChoice(self, event): global STYLES stl = event.GetString() self.cur_style = stl with open(os.path.join(ensureNFD(STYLES_PATH), stl)) as f: text = f.read() exec text in locals() STYLES = copy.deepcopy(style) if not STYLES.has_key('face'): STYLES['face'] = DEFAULT_FONT_FACE if not STYLES.has_key('size'): STYLES['size'] = FONT_SIZE if not STYLES.has_key('size2'): STYLES['size2'] = FONT_SIZE2 self.editorPreview.setStyle() for but, name in self.buttonRefs.items(): but.SetColour(hex_to_rgb(STYLES[name]['colour'])) self.facePopup.SetStringSelection(STYLES['face']) self.font.SetFaceName(STYLES['face']) self.faceView.SetFont(self.font) self.faceView.SetLabel(STYLES['face']) self.components.reset() def OnFaceSelected(self, event): face = event.GetString() self.font.SetFaceName(face) self.faceView.SetFont(self.font) self.faceView.SetLabel(face) STYLES['face'] = face self.editorPreview.setStyle() def OnSelectColour(self, event): col = wx.Colour(*event.GetValue()) col = col.GetAsString(wx.C2S_HTML_SYNTAX) key = self.buttonRefs[event.GetEventObject()] STYLES[key]['colour'] = col self.editorPreview.setStyle() class SearchProjectPanel(scrolled.ScrolledPanel): def __init__(self, parent, root, dict, size): scrolled.ScrolledPanel.__init__(self, parent, wx.ID_ANY, pos=(0,0), size=size, style=wx.SUNKEN_BORDER) self.SetBackgroundColour("#FFFFFF") self.root = root self.dict = dict self.files = sorted(self.dict.keys()) mainSizer = wx.BoxSizer(wx.VERTICAL) BUTID = 25000 textX = self.GetTextExtent("open")[0] textY = self.GetTextExtent("open")[1] for file in self.files: box = wx.BoxSizer(wx.HORIZONTAL) but = wx.Button(self, BUTID, label="open", size=(textX+16, textY+10)) box.Add(but, 0, wx.ALL, 1) self.Bind(wx.EVT_BUTTON, self.onOpenFile, id=BUTID) BUTID += 1 fileText = wx.StaticText(self, wx.ID_ANY, label="File : %s" % file) off = (but.GetSize()[1] - textY) / 2 box.Add(fileText, 1, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, off) mainSizer.Add(box, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, 10) for i in range(len(self.dict[file][0])): box2 = wx.BoxSizer(wx.HORIZONTAL) label = " line %d : %s" % (self.dict[file][0][i], self.dict[file][1][i]) fileText = wx.StaticText(self, wx.ID_ANY, label=label, size=(-1, textY)) box2.Add(fileText, 1, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, off) mainSizer.Add(box2, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, 10) mainSizer.Add(wx.StaticLine(self), 0, wx.LEFT|wx.RIGHT|wx.EXPAND, 1) self.SetSizer(mainSizer) self.SetAutoLayout(1) self.SetupScrolling() h = but.GetSize()[1]+2 num_rows = 0 for f in self.files: num_rows += len(self.dict[f][0]) self.SetMaxSize((-1, max(h*num_rows, self.GetSize()[1]))) def onOpenFile(self, evt): filename = self.root + self.files[evt.GetId() - 25000] self.GetParent().GetParent().panel.addPage(filename) class SearchProjectFrame(wx.Frame): def __init__(self, parent, root, dict, size=(500,500)): wx.Frame.__init__(self, parent, wx.ID_ANY, size=size) self.SetTitle('Search Results in Project "%s"' % os.path.split(root)[1]) self.menuBar = wx.MenuBar() menu1 = wx.Menu() menu1.Append(351, "Close\tCtrl+W") self.menuBar.Append(menu1, 'File') self.SetMenuBar(self.menuBar) self.Bind(wx.EVT_MENU, self.close, id=351) panel = SearchProjectPanel(self, root, dict, size=size) self.Show() def close(self, evt): self.Destroy() class SnippetTree(wx.Panel): def __init__(self, parent, size): wx.Panel.__init__(self, parent, -1, size=size, style=wx.WANTS_CHARS | wx.SUNKEN_BORDER | wx.EXPAND) self.SetMinSize((100, -1)) self.selected = None tsize = (24, 24) file_add_bmp = catalog['file_delete_icon.png'].GetBitmap() folder_add_bmp = catalog['folder_add_icon.png'].GetBitmap() self.sizer = wx.BoxSizer(wx.VERTICAL) toolbarbox = wx.BoxSizer(wx.HORIZONTAL) self.toolbar = wx.ToolBar(self, -1) self.toolbar.SetToolBitmapSize(tsize) self.toolbar.AddLabelTool(SNIPPET_ADD_FOLDER_ID, "Add Category", folder_add_bmp, shortHelp="Add a New Category") self.toolbar.AddLabelTool(SNIPPET_DEL_FILE_ID, "Delete", file_add_bmp, shortHelp="Delete Snippet or Category") self.toolbar.EnableTool(SNIPPET_DEL_FILE_ID, False) self.toolbar.Realize() toolbarbox.Add(self.toolbar, 1, wx.ALIGN_LEFT | wx.EXPAND, 0) wx.EVT_TOOL(self, SNIPPET_ADD_FOLDER_ID, self.onAdd) wx.EVT_TOOL(self, SNIPPET_DEL_FILE_ID, self.onDelete) self.sizer.Add(toolbarbox, 0, wx.EXPAND) self.tree = wx.TreeCtrl(self, -1, (0, 26), size, wx.TR_DEFAULT_STYLE|wx.TR_HIDE_ROOT|wx.SUNKEN_BORDER|wx.EXPAND) if wx.Platform == '__WXMAC__': self.tree.SetFont(wx.Font(11, wx.ROMAN, wx.NORMAL, wx.NORMAL, face=snip_faces['face'])) else: self.tree.SetFont(wx.Font(8, wx.ROMAN, wx.NORMAL, wx.NORMAL, face=snip_faces['face'])) self.sizer.Add(self.tree, 1, wx.EXPAND) self.SetSizer(self.sizer) isz = (12,12) self.il = wx.ImageList(isz[0], isz[1]) self.fldridx = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz)) self.fldropenidx = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, isz)) self.fileidx = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, isz)) self.tree.SetImageList(self.il) self.tree.SetSpacing(12) self.tree.SetIndent(6) self.root = self.tree.AddRoot("EPyo_Snippet_tree", self.fldridx, self.fldropenidx, None) self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnLeftClick) self.tree.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick) self.load() def load(self): categories = [d for d in os.listdir(SNIPPETS_PATH) if os.path.isdir(os.path.join(SNIPPETS_PATH, d)) and d[0] != "."] for category in categories: child = self.tree.AppendItem(self.root, category, self.fldridx, self.fldropenidx, None) files = [f for f in os.listdir(os.path.join(SNIPPETS_PATH, category)) if f[0] != "."] for file in files: item = self.tree.AppendItem(child, file, self.fileidx, self.fileidx, None) self.tree.SortChildren(child) self.tree.SortChildren(self.root) def addItem(self, name, category): child, cookie = self.tree.GetFirstChild(self.root) while child.IsOk(): if self.tree.GetItemText(child) == category: break child, cookie = self.tree.GetNextChild(self.root, cookie) subchild, subcookie = self.tree.GetFirstChild(child) while subchild.IsOk(): if self.tree.GetItemText(subchild) == name: return subchild, subcookie = self.tree.GetNextChild(child, subcookie) item = self.tree.AppendItem(child, name, self.fileidx, self.fileidx, None) self.tree.SortChildren(child) self.tree.SortChildren(self.root) def onAdd(self, evt): dlg = wx.TextEntryDialog(self, "Enter the Category's name:", 'New Category') dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: name = dlg.GetValue() if name != "" and name not in os.listdir(SNIPPETS_PATH): os.mkdir(os.path.join(SNIPPETS_PATH, name)) child = self.tree.AppendItem(self.root, name, self.fldridx, self.fldropenidx, None) self.tree.SortChildren(self.root) SNIPPETS_CATEGORIES.append(name) def onDelete(self, evt): item = self.tree.GetSelection() if item.IsOk(): name = self.tree.GetItemText(item) if self.tree.GetItemParent(item) == self.tree.GetRootItem(): files = os.listdir(os.path.join(SNIPPETS_PATH, name)) for file in files: os.remove(os.path.join(SNIPPETS_PATH, name, file)) os.rmdir(os.path.join(SNIPPETS_PATH, name)) SNIPPETS_CATEGORIES.remove(name) if self.tree.ItemHasChildren(item): self.tree.DeleteChildren(item) else: category = self.tree.GetItemText(self.tree.GetItemParent(item)) os.remove(os.path.join(SNIPPETS_PATH, category, name)) self.tree.Delete(item) self.GetParent().GetParent().GetParent().reloadSnippetMenu() def OnLeftClick(self, event): pt = event.GetPosition() item, flags = self.tree.HitTest(pt) if item: self.select(item) else: self.unselect() event.Skip() def OnLeftDClick(self, event): pt = event.GetPosition() item, flags = self.tree.HitTest(pt) if item: self.select(item) self.openPage(item) else: self.unselect() event.Skip() def openPage(self, item): if self.tree.GetItemParent(item) != self.tree.GetRootItem(): name = self.tree.GetItemText(item) ritem = self.tree.GetItemParent(item) category = self.tree.GetItemText(ritem) self.GetParent().GetParent().onLoad(name, category) def select(self, item): self.tree.SelectItem(item) self.selected = self.tree.GetItemText(item) self.toolbar.EnableTool(SNIPPET_DEL_FILE_ID, True) def unselect(self): self.tree.UnselectAll() self.selected = None self.toolbar.EnableTool(SNIPPET_DEL_FILE_ID, False) class SnippetEditor(stc.StyledTextCtrl): def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.SUNKEN_BORDER): stc.StyledTextCtrl.__init__(self, parent, id, pos, size, style) self.SetViewWhiteSpace(False) self.SetIndent(4) self.SetBackSpaceUnIndents(True) self.SetTabIndents(True) self.SetTabWidth(4) self.SetUseTabs(False) self.SetViewWhiteSpace(False) self.SetEOLMode(wx.stc.STC_EOL_LF) self.SetViewEOL(False) self.SetMarginWidth(1, 0) self.SetLexer(stc.STC_LEX_PYTHON) self.SetKeyWords(0, " ".join(keyword.kwlist) + " None True False " + " ".join(PYO_WORDLIST)) self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "fore:#000000,face:%(face)s,size:%(size)d,back:#FFFFFF" % snip_faces) self.StyleClearAll() self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "fore:#000000,face:%(face)s,size:%(size)d" % snip_faces) self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "fore:#000000,face:%(face)s" % snip_faces) self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#000000,back:#AABBDD,bold" % snip_faces) self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#DD0000,bold" % snip_faces) self.StyleSetSpec(stc.STC_P_DEFAULT, "fore:#000000,face:%(face)s,size:%(size)d" % snip_faces) self.StyleSetSpec(stc.STC_P_COMMENTLINE, "fore:#0066FF,face:%(face)s,italic,size:%(size)d" % snip_faces) self.StyleSetSpec(stc.STC_P_NUMBER, "fore:#0000CD,face:%(face)s,bold,size:%(size)d" % snip_faces) self.StyleSetSpec(stc.STC_P_STRING, "fore:#036A07,face:%(face)s,size:%(size)d" % snip_faces) self.StyleSetSpec(stc.STC_P_CHARACTER, "fore:#036A07,face:%(face)s,size:%(size)d" % snip_faces) self.StyleSetSpec(stc.STC_P_WORD, "fore:#0000FF,face:%(face)s,bold,size:%(size)d" % snip_faces) self.StyleSetSpec(stc.STC_P_TRIPLE, "fore:#038A07,face:%(face)s,size:%(size)d" % snip_faces) self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, "fore:#038A07,face:%(face)s,size:%(size)d" % snip_faces) self.StyleSetSpec(stc.STC_P_CLASSNAME, "fore:#000097,face:%(face)s,bold,size:%(size)d" % snip_faces) self.StyleSetSpec(stc.STC_P_DEFNAME, "fore:#0000A2,face:%(face)s,bold,size:%(size)d" % snip_faces) self.StyleSetSpec(stc.STC_P_OPERATOR, "fore:#000000,face:%(face)s,bold,size:%(size)d" % snip_faces) self.StyleSetSpec(stc.STC_P_IDENTIFIER, "fore:#000000,face:%(face)s,size:%(size)d" % snip_faces) self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, "fore:#0066FF,face:%(face)s,size:%(size)d" % snip_faces) self.SetSelBackground(1, "#C0DFFF") self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI) def OnUpdateUI(self, evt): if self.GetSelectedText(): self.GetParent().GetParent().GetParent().tagButton.Enable() self.GetParent().GetParent().GetParent().tagItem.Enable() else: self.GetParent().GetParent().GetParent().tagButton.Enable(False) self.GetParent().GetParent().GetParent().tagItem.Enable(False) class SnippetFrame(wx.Frame): def __init__(self, parent, title, pos, size): wx.Frame.__init__(self, parent, -1, title, pos, size) self.parent = parent self.menuBar = wx.MenuBar() menu1 = wx.Menu() self.tagItem = menu1.Append(249, "Tag Selection\tCtrl+T") menu1.AppendSeparator() menu1.Append(250, "Close\tCtrl+W") self.menuBar.Append(menu1, 'File') self.SetMenuBar(self.menuBar) self.Bind(wx.EVT_MENU, self.onTagSelection, id=249) self.Bind(wx.EVT_MENU, self.close, id=250) self.Bind(wx.EVT_CLOSE, self.close) self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_LIVE_UPDATE|wx.SP_3DSASH) self.snippet_tree = SnippetTree(self.splitter, (-1, -1)) self.panel = wx.Panel(self.splitter) self.panel.SetBackgroundColour("#DDDDDD") self.splitter.SplitVertically(self.snippet_tree, self.panel, 150) self.box = wx.BoxSizer(wx.VERTICAL) self.category_name = "" self.snippet_name = "" toolbarBox = wx.BoxSizer(wx.HORIZONTAL) self.toolbar = wx.ToolBar(self.panel, -1) saveButton = wx.Button(self.toolbar, wx.ID_ANY, label="Save Snippet") self.toolbar.AddControl(saveButton) self.Bind(wx.EVT_BUTTON, self.onSave, id=saveButton.GetId()) self.toolbar.Realize() toolbarBox.Add(self.toolbar, 1, wx.ALIGN_LEFT|wx.EXPAND|wx.LEFT, 5) toolbar2 = wx.ToolBar(self.panel, -1) self.tagButton = wx.Button(toolbar2, wx.ID_ANY, label="Tag Selection") toolbar2.AddControl(self.tagButton) self.Bind(wx.EVT_BUTTON, self.onTagSelection, id=self.tagButton.GetId()) toolbar2.Realize() toolbarBox.Add(toolbar2, 0, wx.ALIGN_RIGHT|wx.RIGHT, 5) self.box.Add(toolbarBox, 0, wx.EXPAND|wx.ALL, 5) self.entry = SnippetEditor(self.panel) self.box.Add(self.entry, 1, wx.EXPAND|wx.ALL, 10) activateBox = wx.BoxSizer(wx.HORIZONTAL) activateLabel = wx.StaticText(self.panel, wx.ID_ANY, label="Activation :") activateBox.Add(activateLabel, 0, wx.LEFT|wx.TOP, 10) self.short = wx.TextCtrl(self.panel, wx.ID_ANY, size=(170,-1)) activateBox.Add(self.short, 1, wx.EXPAND|wx.ALL, 8) self.short.SetValue("Type your shortcut...") self.short.SetForegroundColour("#AAAAAA") self.short.Bind(wx.EVT_KEY_DOWN, self.onKey) self.short.Bind(wx.EVT_LEFT_DOWN, self.onShortLeftClick) self.short.Bind(wx.EVT_KILL_FOCUS, self.onShortLooseFocus) self.box.Add(activateBox, 0, wx.EXPAND) self.panel.SetSizer(self.box) def close(self, evt): self.Hide() def onTagSelection(self, evt): select = self.entry.GetSelection() if select: self.entry.InsertText(select[1], "`") self.entry.InsertText(select[0], "`") def onLoad(self, name, category): if os.path.isfile(os.path.join(ensureNFD(SNIPPETS_PATH), category, name)): self.snippet_name = name self.category_name = category with codecs.open(os.path.join(ensureNFD(SNIPPETS_PATH), self.category_name, self.snippet_name), "r", encoding="utf-8") as f: text = f.read() exec text in locals() try: self.entry.SetTextUTF8(snippet["value"]) except: self.entry.SetText(snippet["value"]) if snippet["shortcut"]: self.short.SetValue(snippet["shortcut"]) self.short.SetForegroundColour("#000000") else: self.short.SetValue("Type your shortcut...") self.short.SetForegroundColour("#AAAAAA") def onSave(self, evt): dlg = wx.SingleChoiceDialog(self, 'Choose the Snippet Category', 'Snippet Category', SNIPPETS_CATEGORIES, wx.OK) dlg.SetSize((250,300)) dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: category = dlg.GetStringSelection() dlg.Destroy() dlg = wx.TextEntryDialog(self, "Enter the Snippet's name:", 'Save Snippet', self.snippet_name) dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: name = dlg.GetValue() if name != "": self.category_name = category self.snippet_name = name short = self.short.GetValue() if short == "Type your shortcut...": short = "" dic = {'shortcut': short, 'value': self.entry.GetTextUTF8()} with codecs.open(os.path.join(SNIPPETS_PATH, category, name), "w", encoding="utf-8") as f: f.write("snippet = %s" % pprint.pformat(dic)) self.snippet_tree.addItem(name, category) self.parent.reloadSnippetMenu() dlg.Destroy() def onShortLooseFocus(self, evt): short = self.short.GetValue() if short == "": self.short.SetValue("Type your shortcut...") self.short.SetForegroundColour("#AAAAAA") def onShortLeftClick(self, evt): self.short.SetValue("") evt.Skip() def onKey(self, evt): key = evt.GetKeyCode() if key < 256 and key != wx.WXK_TAB: id = evt.GetEventObject().GetId() txt = "" if evt.ShiftDown(): txt += "Shift-" if evt.ControlDown(): if sys.platform == "darwin": txt += "XCtrl-" else: txt += "Ctrl-" if evt.AltDown(): txt += "Alt-" if sys.platform == "darwin" and evt.CmdDown(): txt += "Ctrl-" if txt == "": return ch = chr(key) if ch in string.lowercase: ch = ch.upper() txt += ch self.short.SetValue(txt) self.short.SetForegroundColour("#000000") self.entry.SetFocus() else: evt.Skip() class FileSelectorCombo(wx.combo.ComboCtrl): def __init__(self, *args, **kw): wx.combo.ComboCtrl.__init__(self, *args, **kw) w, h = 12, 14 bmp = wx.EmptyBitmap(w,h) dc = wx.MemoryDC(bmp) bgcolor = wx.Colour(255,254,255) dc.SetBackground(wx.Brush(bgcolor)) dc.Clear() dc.SetBrush(wx.Brush("#444444")) dc.SetPen(wx.Pen("#444444")) dc.DrawPolygon([wx.Point(4,h/2-2), wx.Point(w/2,2), wx.Point(w-4,h/2-2)]) dc.DrawPolygon([wx.Point(4,h/2+2), wx.Point(w/2,h-2), wx.Point(w-4,h/2+2)]) del dc bmp.SetMaskColour(bgcolor) self.SetButtonBitmaps(bmp, True) class TreeCtrlComboPopup(wx.combo.ComboPopup): def Init(self): self.value = None self.curitem = None def Create(self, parent): self.tree = wx.TreeCtrl(parent, style=wx.TR_HIDE_ROOT |wx.TR_HAS_BUTTONS |wx.TR_SINGLE |wx.TR_LINES_AT_ROOT |wx.SIMPLE_BORDER) font, psize = self.tree.GetFont(), self.tree.GetFont().GetPointSize() if PLATFORM == "darwin": font.SetPointSize(psize-2) else: font.SetPointSize(psize-1) self.tree.SetFont(font) self.tree.Bind(wx.EVT_MOTION, self.OnMotion) self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) def GetControl(self): return self.tree def GetStringValue(self): if self.value: return self.tree.GetItemText(self.value) return "" def OnPopup(self): self.tree.DeleteAllItems() editor = self.GetCombo().GetParent().GetParent().panel.editor count = editor.GetLineCount() for i in range(count): text = editor.GetLineUTF8(i) if text.startswith("class "): text = text.replace("class ", "") text = text[0:text.find(":")] if len(text) > 50: text = text[:50] + "...)" item = self.AddItem(text, None, wx.TreeItemData(i)) elif text.startswith("def "): text = text.replace("def ", "") text = text[0:text.find(":")] if len(text) > 50: text = text[:50] + "...)" item = self.AddItem(text, None, wx.TreeItemData(i)) elif text.lstrip().startswith("def "): indent = editor.GetLineIndentation(i) text = text.lstrip().replace("def ", "") text = " "*indent + text[0:text.find(":")] if len(text) > 50: text = text[:50] + "...)" item = self.AddItem(text, None, wx.TreeItemData(i)) self.tree.SetSize((400, 500)) def SetStringValue(self, value): root = self.tree.GetRootItem() if not root: return found = self.FindItem(root, value) if found: self.value = found self.tree.SelectItem(found) def GetAdjustedSize(self, minWidth, prefHeight, maxHeight): return wx.Size(minWidth, min(200, maxHeight)) def FindItem(self, parentItem, text): item, cookie = self.tree.GetFirstChild(parentItem) while item: if self.tree.GetItemText(item) == text: return item if self.tree.ItemHasChildren(item): item = self.FindItem(item, text) item, cookie = self.tree.GetNextChild(parentItem, cookie) return wx.TreeItemId(); def AddItem(self, value, parent=None, data=None): if not parent: root = self.tree.GetRootItem() if not root: root = self.tree.AddRoot("") parent = root item = self.tree.AppendItem(parent, value, data=data) return item def OnMotion(self, evt): item, flags = self.tree.HitTest(evt.GetPosition()) if item and flags & wx.TREE_HITTEST_ONITEMLABEL: self.tree.SelectItem(item) self.curitem = item evt.Skip() def OnLeftDown(self, evt): item, flags = self.tree.HitTest(evt.GetPosition()) if item and flags & wx.TREE_HITTEST_ONITEMLABEL: self.curitem = item self.value = item self.Dismiss() editor = self.GetCombo().GetParent().GetParent().panel.editor line = self.tree.GetPyData(item) editor.GotoLine(line) halfNumLinesOnScreen = editor.LinesOnScreen() / 2 editor.ScrollToLine(line - halfNumLinesOnScreen) wx.CallAfter(editor.SetFocus) evt.Skip() class MainFrame(wx.Frame): def __init__(self, parent, ID, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE): wx.Frame.__init__(self, parent, ID, title, pos, size, style) self.Bind(wx.EVT_CLOSE, self.OnClose) EVT_DATA_EVENT(self, self.format_outputLog) if sys.platform == "darwin": accel_ctrl = wx.ACCEL_CMD else: accel_ctrl = wx.ACCEL_CTRL # To set up an accelerator key #aEntry = wx.AcceleratorEntry(accel_ctrl|wx.ACCEL_SHIFT, wx.WXK_UP, 602) # "\t%s" % aEntry.ToString() self.snippet_frame = SnippetFrame(self, title='Snippet Editor', pos=(25,25), size=(700,450)) self.style_frame = ColourEditor(self, title='Style Editor', pos=(100,100), size=(500,550)) self.style_frame.setCurrentStyle(PREF_STYLE) self.keyCommandsFrame = KeyCommandsFrame(self) self.server_pipe = None self.back_server_started = False self.master_document = None self.processID = 0 self.processes = {} self.filters = {} self.print_data = wx.PrintData() self.print_data.SetPaperId(wx.PAPER_LETTER) self.pastingList = [] self.panel = MainPanel(self, size=size) self.menuBar = wx.MenuBar() menu1 = wx.Menu() menu1.Append(wx.ID_NEW, "New\tCtrl+N") self.Bind(wx.EVT_MENU, self.new, id=wx.ID_NEW) self.submenu1 = wx.Menu() for key, name in sorted(TEMPLATE_NAMES.items(), reverse=True): self.submenu1.Append(key, "%s Template" % name) menu1.AppendMenu(99, "New From Template", self.submenu1) self.Bind(wx.EVT_MENU, self.newFromTemplate, id=min(TEMPLATE_NAMES.keys()), id2=max(TEMPLATE_NAMES.keys())) menu1.Append(wx.ID_OPEN, "Open\tCtrl+O") self.Bind(wx.EVT_MENU, self.open, id=wx.ID_OPEN) menu1.Append(160, "Open With Encoding") self.Bind(wx.EVT_MENU, self.openWithEncoding, id=160) menu1.Append(112, "Open Folder\tShift+Ctrl+O") self.Bind(wx.EVT_MENU, self.openFolder, id=112) self.submenu2 = wx.Menu() ID_OPEN_RECENT = 2000 recentFiles = [] filename = ensureNFD(os.path.join(TEMP_PATH,'.recent.txt')) if os.path.isfile(filename): f = codecs.open(filename, "r", encoding="utf-8") for line in f.readlines(): recentFiles.append(line.replace("\n", "")) f.close() if recentFiles: for file in recentFiles: self.submenu2.Append(ID_OPEN_RECENT, file) ID_OPEN_RECENT += 1 if ID_OPEN_RECENT > 2000: for i in range(2000, ID_OPEN_RECENT): self.Bind(wx.EVT_MENU, self.openRecent, id=i) menu1.AppendMenu(1999, "Open Recent...", self.submenu2) menu1.AppendSeparator() menu1.Append(wx.ID_CLOSE, "Close\tCtrl+W") self.Bind(wx.EVT_MENU, self.close, id=wx.ID_CLOSE) menu1.Append(wx.ID_CLOSE_ALL, "Close All Tabs\tShift+Ctrl+W") self.Bind(wx.EVT_MENU, self.closeAll, id=wx.ID_CLOSE_ALL) menu1.Append(wx.ID_SAVE, "Save\tCtrl+S") self.Bind(wx.EVT_MENU, self.save, id=wx.ID_SAVE) menu1.Append(wx.ID_SAVEAS, "Save As...\tShift+Ctrl+S") self.Bind(wx.EVT_MENU, self.saveas, id=wx.ID_SAVEAS) menu1.Append(100, "Save As Template...") self.Bind(wx.EVT_MENU, self.saveasTemplate, id=100) # TODO : printing not working well enough #menu1.AppendSeparator() #menu1.Append(wx.ID_PREVIEW, "Print Preview") #self.Bind(wx.EVT_MENU, self.OnPrintPreview, id=wx.ID_PREVIEW) #menu1.Append(wx.ID_PRINT, "Print\tCtrl+P") #self.Bind(wx.EVT_MENU, self.OnPrint, id=wx.ID_PRINT) if sys.platform != "darwin": menu1.AppendSeparator() prefItem = menu1.Append(wx.ID_PREFERENCES, "Preferences...\tCtrl+;") self.Bind(wx.EVT_MENU, self.openPrefs, prefItem) if sys.platform != "darwin": menu1.AppendSeparator() quitItem = menu1.Append(wx.ID_EXIT, "Quit\tCtrl+Q") self.Bind(wx.EVT_MENU, self.OnClose, quitItem) self.menuBar.Append(menu1, 'File') menu2 = wx.Menu() menu2.Append(wx.ID_UNDO, "Undo\tCtrl+Z") menu2.Append(wx.ID_REDO, "Redo\tShift+Ctrl+Z") self.Bind(wx.EVT_MENU, self.undo, id=wx.ID_UNDO, id2=wx.ID_REDO) menu2.AppendSeparator() menu2.Append(wx.ID_CUT, "Cut\tCtrl+X") self.Bind(wx.EVT_MENU, self.cut, id=wx.ID_CUT) menu2.Append(wx.ID_COPY, "Copy\tCtrl+C") self.Bind(wx.EVT_MENU, self.copy, id=wx.ID_COPY) menu2.Append(wx.ID_PASTE, "Paste\tCtrl+V") self.Bind(wx.EVT_MENU, self.paste, id=wx.ID_PASTE) menu2.Append(wx.ID_SELECTALL, "Select All\tCtrl+A") self.Bind(wx.EVT_MENU, self.selectall, id=wx.ID_SELECTALL) menu2.AppendSeparator() menu2.Append(200, "Add to Pasting List\tShift+Ctrl+C") self.Bind(wx.EVT_MENU, self.listCopy, id=200) menu2.Append(201, "Paste From List\tShift+Ctrl+V") self.Bind(wx.EVT_MENU, self.listPaste, id=201) menu2.Append(202, "Save Pasting List") self.Bind(wx.EVT_MENU, self.saveListPaste, id=202) menu2.Append(203, "Load Pasting List") self.Bind(wx.EVT_MENU, self.loadListPaste, id=203) menu2.Append(204, "Edit Pasting List") self.Bind(wx.EVT_MENU, self.editPastingList, id=204) menu2.AppendSeparator() menu2.Append(107, "Remove Trailing White Space") self.Bind(wx.EVT_MENU, self.removeTrailingWhiteSpace, id=107) menu2.AppendSeparator() menu2.Append(103, "Fold All\tCtrl+I") self.Bind(wx.EVT_MENU, self.fold, id=103) menu2.Append(104, "Expand All\tShift+Ctrl+I") self.Bind(wx.EVT_MENU, self.fold, id=104) menu2.Append(105, "Fold/Expand Current Scope\tCtrl+8") self.Bind(wx.EVT_MENU, self.foldExpandScope, id=105) menu2.Append(108, "Un/Comment Selection\tCtrl+J") self.Bind(wx.EVT_MENU, self.OnComment, id=108) menu2.Append(121, "Insert File Path...\tShift+Ctrl+P") self.Bind(wx.EVT_MENU, self.insertPath, id=121) menu2.AppendSeparator() submenublk = wx.Menu() submenublk.Append(400, "Insert Code Block Head\tCtrl+B") submenublk.Append(401, "Insert Code Block Tail\tShift+Ctrl+B") submenublk.Append(402, "Select Code Block\tCtrl+,") self.Bind(wx.EVT_MENU, self.onCodeBlock, id=400, id2=402) menu2.AppendMenu(-1, "Code Blocks", submenublk) menu2.AppendSeparator() menu2.Append(114, "Auto Complete container syntax", kind=wx.ITEM_CHECK) self.Bind(wx.EVT_MENU, self.autoCompContainer, id=114) menu2.Check(114, PREFERENCES.get("auto_comp_container", 0)) menu2.AppendSeparator() submenu2 = wx.Menu() submenu2.Append(170, "Convert Selection to Uppercase\tCtrl+U") submenu2.Append(171, "Convert Selection to Lowercase\tShift+Ctrl+U") self.Bind(wx.EVT_MENU, self.upperLower, id=170, id2=171) submenu2.Append(172, "Convert Tabs to Spaces") self.Bind(wx.EVT_MENU, self.tabsToSpaces, id=172) menu2.AppendMenu(-1, "Text Converters", submenu2) menu2.AppendSeparator() menu2.Append(140, "Goto line...\tCtrl+L") self.Bind(wx.EVT_MENU, self.gotoLine, id=140) menu2.Append(141, "Quick Search\tCtrl+F") self.Bind(wx.EVT_MENU, self.quickSearch, id=141) menu2.Append(142, "Quick Search Word Under Caret\tShift+Ctrl+J") self.Bind(wx.EVT_MENU, self.quickSearchWordUnderCaret, id=142) menu2.Append(143, "Search Again Next...\tCtrl+G") menu2.Append(144, "Search Again Previous...\tShift+Ctrl+G") self.Bind(wx.EVT_MENU, self.searchAgain, id=143, id2=144) menu2.Append(146, "Search in Project Files\tShift+Ctrl+H") self.Bind(wx.EVT_MENU, self.searchInProject, id=146) menu2.Append(wx.ID_FIND, "Find/Replace\tShift+Ctrl+F") self.Bind(wx.EVT_MENU, self.showFind, id=wx.ID_FIND) self.menuBar.Append(menu2, 'Code') self.menu3 = wx.Menu() self.menu3.Append(299, "Set Current Document as Master") self.Bind(wx.EVT_MENU, self.setMasterDocument, id=299) self.menu3.AppendSeparator() self.menu3.Append(300, "Run\tCtrl+R") self.Bind(wx.EVT_MENU, self.runner, id=300) self.menu3.Append(301, "Run Selection\tShift+Ctrl+R") self.Bind(wx.EVT_MENU, self.runSelection, id=301) self.menu3.Append(302, "Run Line/Selection as Pyo\tCtrl+E") self.Bind(wx.EVT_MENU, self.runSelectionAsPyo, id=302) self.menu3.Append(303, "Execute Line/Selection as Python\tShift+Ctrl+E") self.Bind(wx.EVT_MENU, self.execSelection, id=303) self.menu3.AppendSeparator() self.backServerItem = self.menu3.Append(304, "Start Pyo Background Server") self.Bind(wx.EVT_MENU, self.startStopBackgroundServer, id=304) self.sendToServerItem = self.menu3.Append(305, "Send Line/Selection to Pyo Background Server\tCtrl+.") self.sendToServerItem.Enable(False) self.Bind(wx.EVT_MENU, self.sendSelectionToBackgroundServer, id=305) self.menuBar.Append(self.menu3, 'Process') menu4 = wx.Menu() menu4.Append(wx.ID_ZOOM_IN, "Zoom in\tCtrl+=") menu4.Append(wx.ID_ZOOM_OUT, "Zoom out\tCtrl+-") self.Bind(wx.EVT_MENU, self.zoom, id=wx.ID_ZOOM_IN, id2=wx.ID_ZOOM_OUT) menu4.AppendSeparator() menu4.Append(130, "Show Invisibles", kind=wx.ITEM_CHECK) menu4.Check(130, PREFERENCES.get("show_invisibles", 0)) self.Bind(wx.EVT_MENU, self.showInvisibles, id=130) menu4.Append(131, "Show Edge Line", kind=wx.ITEM_CHECK) menu4.Check(131, PREFERENCES.get("show_edge_line", 0)) self.Bind(wx.EVT_MENU, self.showEdge, id=131) menu4.Append(132, "Wrap Text Line", kind=wx.ITEM_CHECK) menu4.Check(132, PREFERENCES.get("wrap_text_line", 0)) self.Bind(wx.EVT_MENU, self.wrapMode, id=132) menu4.AppendSeparator() self.showProjItem = menu4.Append(50, "Show Folder Panel", kind=wx.ITEM_CHECK) self.Bind(wx.EVT_MENU, self.showHideFolderPanel, id=50) self.showMarkItem = menu4.Append(49, "Show Markers Panel", kind=wx.ITEM_CHECK) self.Bind(wx.EVT_MENU, self.showHideMarkersPanel, id=49) self.showOutputItem = menu4.Append(48, "Show Output Panel", kind=wx.ITEM_CHECK) self.Bind(wx.EVT_MENU, self.showHideOutputPanel, id=48) menu4.AppendSeparator() menu4.Append(190, "Open Documentation Frame\tShift+Ctrl+D") self.Bind(wx.EVT_MENU, self.showDocFrame, id=190) menu4.Append(180, "Open Documentation for Pyo Object Under Caret\tCtrl+D") self.Bind(wx.EVT_MENU, self.showDoc, id=180) menu4.Append(181, "Show args for Pyo Object Under Caret\tShift+Return") self.Bind(wx.EVT_MENU, self.showArgs, id=181) menu4.Append(182, "Show __doc__ String for Word Under Caret\tCtrl+Return") self.Bind(wx.EVT_MENU, self.showDocString, id=182) menu4.AppendSeparator() menu4.Append(185, "Rebuild Documentation") self.Bind(wx.EVT_MENU, self.rebuildDoc, id=185) self.menuBar.Append(menu4, 'View') self.menu5 = wx.Menu() ID_STYLE = 500 for st in [f for f in os.listdir(STYLES_PATH) if f[0] != "."]: self.menu5.Append(ID_STYLE, st, "", wx.ITEM_RADIO) if st == PREFERENCES.get("pref_style", "Default"): self.menu5.Check(ID_STYLE, True) ID_STYLE += 1 self.menu5.AppendSeparator() self.menu5.Append(499, "Open Style Editor") self.Bind(wx.EVT_MENU, self.openStyleEditor, id=499) self.menuBar.Append(self.menu5, 'Styles') for i in range(500, ID_STYLE): self.Bind(wx.EVT_MENU, self.changeStyle, id=i) self.menu7 = wx.Menu() self.makeSnippetMenu() self.menuBar.Append(self.menu7, "Snippets") menu8 = wx.Menu() menu8.Append(600, "Add Marker to Current Line\tShift+Ctrl+M") self.Bind(wx.EVT_MENU, self.addMarker, id=600) menu8.Append(601, "Delete Current Line Marker\tShift+Ctrl+K") self.Bind(wx.EVT_MENU, self.deleteMarker, id=601) menu8.Append(604, "Delete All Markers") self.Bind(wx.EVT_MENU, self.deleteAllMarkers, id=604) menu8.AppendSeparator() menu8.Append(602, 'Navigate Markers Upward\tCtrl+9') menu8.Append(603, 'Navigate Markers Downward\tCtrl+0') self.Bind(wx.EVT_MENU, self.navigateMarkers, id=602, id2=603) self.menuBar.Append(menu8, "Markers") self.menu6 = wx.Menu() ID_EXAMPLE = 1000 for folder in EXAMPLE_FOLDERS: exmenu = wx.Menu(folder.lower()) for ex in sorted([exp for exp in os.listdir(os.path.join(EXAMPLE_PATH, folder.lower())) if exp[0] != "." and not exp.endswith("pyc")]): exmenu.Append(ID_EXAMPLE, ex) ID_EXAMPLE += 1 self.menu6.AppendMenu(-1, folder, exmenu) ID_EXAMPLE += 1 self.Bind(wx.EVT_MENU, self.openExample, id=1000, id2=ID_EXAMPLE) self.menuBar.Append(self.menu6, "Pyo Examples") self.ID_FILTERS = 12000 self.filters_menu = wx.Menu() self.filters_menu.Append(11998, "Open Filters File") self.Bind(wx.EVT_MENU, self.openFilters, id=11998) self.filters_menu.Append(11999, "Rebuild Filters Menu") self.Bind(wx.EVT_MENU, self.buildFilterMenu, id=11999) self.filters_menu.AppendSeparator() self.buildFilterMenu() self.menuBar.Append(self.filters_menu, "Filters") windowMenu = wx.Menu() aEntry = wx.AcceleratorEntry(wx.ACCEL_CTRL, wx.WXK_TAB, 10001) windowMenu.Append(10001, 'Navigate Tabs Forward\t%s' % aEntry.ToString()) aEntry = wx.AcceleratorEntry(wx.ACCEL_CTRL|wx.ACCEL_SHIFT, wx.WXK_TAB, 10002) windowMenu.Append(10002, 'Navigate Tabs Backward\t%s' % aEntry.ToString()) self.Bind(wx.EVT_MENU, self.onSwitchTabs, id=10001, id2=10002) self.menuBar.Append(windowMenu, '&Window') helpmenu = wx.Menu() helpItem = helpmenu.Append(wx.ID_ABOUT, '&About %s %s' % (APP_NAME, APP_VERSION), 'wxPython RULES!!!') self.Bind(wx.EVT_MENU, self.onHelpAbout, helpItem) helpmenu.Append(999, 'Show Editor Key Commands') self.Bind(wx.EVT_MENU, self.onShowEditorKeyCommands, id=999) helpmenu.Append(998, 'Tutorial: How to Create a Custom PyoObject - RingMod') self.Bind(wx.EVT_MENU, self.openTutorial, id=998) helpmenu.Append(997, 'Tutorial: How to Create a Custom PyoObject - Flanger') self.Bind(wx.EVT_MENU, self.openTutorial, id=997) helpmenu.Append(996, 'Tutorial: How to Create a Custom PyoTableObject - TriTable') self.Bind(wx.EVT_MENU, self.openTutorial, id=996) self.menuBar.Append(helpmenu, '&Help') self.SetMenuBar(self.menuBar) self.status = self.CreateStatusBar() self.status.Bind(wx.EVT_SIZE, self.StatusOnSize) self.status.SetFieldsCount(3) if PLATFORM == "darwin": ststyle = wx.TE_PROCESS_ENTER|wx.NO_BORDER sth = self.status.GetSize()[1] #16 cch = -1 elif PLATFORM == "linux2": ststyle = wx.TE_PROCESS_ENTER|wx.SIMPLE_BORDER sth = self.status.GetSize()[1]+1 #20 cch = self.status.GetSize()[1] #21 elif PLATFORM == "win32": ststyle = wx.TE_PROCESS_ENTER|wx.SIMPLE_BORDER sth = 20 cch = 20 self.field1X, field1Y = self.status.GetTextExtent("Quick Search:") self.status.SetStatusWidths([self.field1X+9,-1,-2]) self.status.SetStatusText("Quick Search:", 0) self.status_search = wx.TextCtrl(self.status, wx.ID_ANY, size=(150,sth), style=ststyle) self.status_search.Bind(wx.EVT_TEXT_ENTER, self.onQuickSearchEnter) self.cc = FileSelectorCombo(self.status, size=(250, cch), style=wx.CB_READONLY) self.tcp = TreeCtrlComboPopup() self.cc.SetPopupControl(self.tcp) self.Reposition() self.showProjectTree(PREFERENCES.get("show_folder_panel", 0)) self.showMarkersPanel(PREFERENCES.get("show_markers_panel", 0)) self.showOutputPanel(PREFERENCES.get("show_output_panel", 1)) if INSTALLATION_ERROR_MESSAGE != "": report = wx.MessageDialog(self, INSTALLATION_ERROR_MESSAGE, "Installation Report", wx.OK|wx.ICON_INFORMATION|wx.STAY_ON_TOP) report.ShowModal() report.Destroy() if foldersToOpen: for p in foldersToOpen: self.panel.project.loadFolder(p) sys.path.append(p) if filesToOpen: for f in filesToOpen: self.panel.addPage(f) wx.CallAfter(self.buildDoc) def Reposition(self): if PLATFORM == "darwin": yoff1 = -1 yoff2 = -5 elif PLATFORM == "linux2": yoff1 = -2 yoff2 = -1 elif PLATFORM == "win32": yoff1 = 0 yoff2 = -1 self.status.SetStatusText("Quick Search:", 0) rect = self.status.GetFieldRect(1) self.status_search.SetPosition((self.field1X+12, rect.y+yoff1)) rect = self.status.GetFieldRect(2) if rect.x > self.field1X+160: self.cc.SetPosition((rect.x, rect.y+yoff2)) def onCodeBlock(self, evt): if evt.GetId() == 400: self.panel.editor.insertBlockHead() elif evt.GetId() == 401: self.panel.editor.insertBlockTail() elif evt.GetId() == 402: self.panel.editor.selectCodeBlock() def setMasterDocument(self, evt): if self.master_document == None: self.master_document = self.panel.editor.path self.menu3.SetLabel(299, "Revert Master Document to None") else: self.master_document = None self.menu3.SetLabel(299, "Set Current Document as Master") def StatusOnSize(self, evt): self.Reposition() def rebuildStyleMenu(self): items = self.menu5.GetMenuItems() for item in items: self.menu5.DeleteItem(item) ID_STYLE = 500 for st in [f for f in os.listdir(STYLES_PATH) if f[0] != "."]: self.menu5.Append(ID_STYLE, st, "", wx.ITEM_RADIO) ID_STYLE += 1 self.menu5.AppendSeparator() self.menu5.Append(499, "Open Style Editor") self.Bind(wx.EVT_MENU, self.openStyleEditor, id=499) for i in range(500, ID_STYLE): self.Bind(wx.EVT_MENU, self.changeStyle, id=i) def reloadSnippetMenu(self): items = self.menu7.GetMenuItems() for item in items: self.menu7.DeleteItem(item) self.makeSnippetMenu() def makeSnippetMenu(self): itemId = 30000 accel_entries = [] for cat in SNIPPETS_CATEGORIES: submenu = wx.Menu(title=cat) files = [f for f in os.listdir(os.path.join(SNIPPETS_PATH, cat))] for file in files: with open(os.path.join(SNIPPETS_PATH, cat, file), "r") as f: text = f.read() exec text in locals() short = snippet["shortcut"] accel = 0 if "Shift" in short: accel |= wx.ACCEL_SHIFT short = short.replace("Shift", "") if "XCtrl" in short: accel |= wx.ACCEL_CTRL short = short.replace("XCtrl", "") if "Ctrl" in short: if PLATFORM == "darwin": accel |= wx.ACCEL_CMD else: accel |= wx.ACCEL_CTRL short = short.replace("Ctrl", "") if "Alt" in short: accel |= wx.ACCEL_ALT short = short.replace("Alt", "") if accel == 0: accel = wx.ACCEL_NORMAL short = short.replace("-", "") if short != "": accel_tuple = wx.AcceleratorEntry(accel, ord(short), itemId) accel_entries.append(accel_tuple) short = accel_tuple.ToString() submenu.Append(itemId, "%s\t%s" % (file, short)) else: submenu.Append(itemId, file) self.Bind(wx.EVT_MENU, self.insertSnippet, id=itemId) itemId += 1 self.menu7.AppendMenu(itemId, cat, submenu) itemId += 1 if accel_entries != []: accel_table = wx.AcceleratorTable(accel_entries) self.SetAcceleratorTable(accel_table) self.menu7.AppendSeparator() self.menu7.Append(51, "Open Snippet Editor") self.Bind(wx.EVT_MENU, self.showSnippetEditor, id=51) ### Editor functions ### def cut(self, evt): self.panel.editor.Cut() def copy(self, evt): self.panel.editor.Copy() def listCopy(self, evt): text = self.panel.editor.GetSelectedTextUTF8() self.pastingList.append(toSysEncoding(text)) def paste(self, evt): if self.FindFocus() == self.status_search: self.status_search.Paste() else: self.panel.editor.Paste() def listPaste(self, evt): self.panel.editor.listPaste(self.pastingList) def saveListPaste(self, evt): if self.pastingList != []: dlg = wx.FileDialog(self, message="Save file as ...", defaultDir=os.path.expanduser('~'), style=wx.SAVE) if dlg.ShowModal() == wx.ID_OK: path = ensureNFD(dlg.GetPath()) with open(path, "w") as f: f.write(str(self.pastingList)) def loadListPaste(self, evt): dlg = wx.FileDialog(self, message="Choose a file", defaultDir=os.path.expanduser("~"), style=wx.OPEN) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.pastingList = [] with open(path, "r") as f: try: pastingList = eval(f.read()) if type(pastingList) == ListType: self.pastingList = pastingList except: f.seek(0) for line in f: if line.replace("\n", "").strip() != "": self.pastingList.append(line) def editPastingList(self, evt): f = PastingListEditorFrame(self, self.pastingList) f.Show() def selectall(self, evt): self.panel.editor.SelectAll() def upperLower(self, evt): if evt.GetId() == 170: self.panel.editor.UpperCase() else: self.panel.editor.LowerCase() def tabsToSpaces(self, evt): self.panel.editor.tabsToSpaces() def buildFilterMenu(self, evt=None): if self.ID_FILTERS != 12000: for i in range(12000, self.ID_FILTERS): self.filters_menu.Delete(i) ID_FILTERS = 12000 with open(FILTERS_FILE, "r") as f: for line in f.readlines(): if line.startswith("def "): ppos = line.find("(") name = line[4:ppos] self.filters_menu.Append(ID_FILTERS, name) self.Bind(wx.EVT_MENU, self.applyFilter, id=ID_FILTERS) self.filters[ID_FILTERS] = name ID_FILTERS += 1 self.ID_FILTERS = ID_FILTERS def openFilters(self, evt): self.panel.addPage(FILTERS_FILE) def applyFilter(self, evt): execfile(FILTERS_FILE, {}, locals()) filter = self.filters[evt.GetId()] try: text = self.panel.editor.GetSelectedTextUTF8() except: text = self.panel.editor.GetSelectedText() if text == "": dlg = wx.MessageDialog(self, "You must select some text to apply a filter...", "No selected text!", style=wx.OK|wx.STAY_ON_TOP) dlg.ShowModal() dlg.Destroy() else: self.panel.editor.ReplaceSelection(locals()[filter](text)) def undo(self, evt): if evt.GetId() == wx.ID_UNDO: self.panel.editor.Undo() else: self.panel.editor.Redo() def zoom(self, evt): if evt.GetId() == wx.ID_ZOOM_IN: self.panel.editor.SetZoom(self.panel.editor.GetZoom() + 1) else: self.panel.editor.SetZoom(self.panel.editor.GetZoom() - 1) def showInvisibles(self, evt): state = evt.GetInt() PREFERENCES["show_invisibles"] = state for i in range(self.panel.notebook.GetPageCount()): ed = self.panel.notebook.GetPage(i) ed.showInvisibles(state) def showEdge(self, evt): state = evt.GetInt() PREFERENCES["show_edge_line"] = state for i in range(self.panel.notebook.GetPageCount()): ed = self.panel.notebook.GetPage(i) ed.showEdge(state) def wrapMode(self, evt): state = evt.GetInt() PREFERENCES["wrap_text_line"] = state mode = {0: stc.STC_WRAP_NONE, 1: stc.STC_WRAP_WORD}[state] for i in range(self.panel.notebook.GetPageCount()): ed = self.panel.notebook.GetPage(i) ed.SetWrapMode(mode) def removeTrailingWhiteSpace(self, evt): self.panel.editor.removeTrailingWhiteSpace() def addMarker(self, evt): line = self.panel.editor.GetCurrentLine() self.panel.editor.addMarker(line) def deleteMarker(self, evt): line = self.panel.editor.GetCurrentLine() self.panel.editor.deleteMarker(line) def deleteAllMarkers(self, evt): self.panel.editor.deleteAllMarkers() def navigateMarkers(self, evt): if evt.GetId() == 602: self.panel.editor.navigateMarkers(down=False) else: self.panel.editor.navigateMarkers(down=True) def gotoLine(self, evt): dlg = wx.TextEntryDialog(self, "Enter a line number:", "Go to Line") val = -1 if dlg.ShowModal() == wx.ID_OK: try: val = int(dlg.GetValue()) except: val = -1 dlg.Destroy() if val != -1: val -= 1 pos = self.panel.editor.FindColumn(val, 0) self.panel.editor.GotoLine(val) first = self.panel.editor.GetFirstVisibleLine() if val == first: self.panel.editor.LineScroll(0, -self.panel.editor.LinesOnScreen()/2) else: self.panel.editor.LineScroll(0, self.panel.editor.LinesOnScreen()/2) #self.panel.editor.SetCurrentPos(pos) #self.panel.editor.EnsureVisible(val) #self.panel.editor.EnsureCaretVisible() wx.CallAfter(self.panel.editor.SetAnchor, pos) def OnComment(self, evt): self.panel.editor.OnComment() def fold(self, event): if event.GetId() == 103: self.panel.editor.FoldAll() else: self.panel.editor.ExpandAll() def foldExpandScope(self, evt): self.panel.editor.foldExpandCurrentScope() def autoCompContainer(self, evt): state = evt.GetInt() PREFERENCES["auto_comp_container"] = state self.panel.editor.showAutoCompContainer(state) def showFind(self, evt): self.panel.editor.OnShowFindReplace() def quickSearch(self, evt): self.status.SetStatusText("Quick Search:", 0) self.status_search.SetFocus() self.status_search.SelectAll() def quickSearchWordUnderCaret(self, evt): self.status.SetStatusText("Quick Search:", 0) word = self.panel.editor.getWordUnderCaret() self.status_search.SetValue(word) self.onQuickSearchEnter(None) def onQuickSearchEnter(self, evt): str = self.status_search.GetValue() self.panel.editor.SetFocus() self.panel.editor.OnQuickSearch(str) def searchAgain(self, evt): if evt.GetId() == 143: next = True else: next = False str = self.status_search.GetValue() self.panel.editor.OnQuickSearch(str, next) def searchInProject(self, evt): ok = False search = "" choices = self.panel.project.projectDict.keys() if len(choices) == 0: dlg = wx.MessageDialog(self, 'You must load at least one folder to use the "Search in Project Files" option.', 'No project folder', wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() elif len(choices) == 1: rootdir = self.panel.project.projectDict[choices[0]] ok = True else: dlg = wx.SingleChoiceDialog(self, 'Choose a project folder...', 'Search in project files', choices, wx.CHOICEDLG_STYLE) if dlg.ShowModal() == wx.ID_OK: root = dlg.GetStringSelection() rootdir = self.panel.project.projectDict[root] ok = True if ok: dlg = wx.TextEntryDialog(self, 'Enter a search term...', 'Search in Project Files') if dlg.ShowModal() == wx.ID_OK: search = dlg.GetValue() dlg.Destroy() if search: wx.CallAfter(self.doSearchInProject, rootdir, search) def doSearchInProject(self, rootdir, search): result = {} filters = ["build"] for root, dirs, files in os.walk(rootdir): if os.path.split(root)[1].startswith("."): filters.append(os.path.split(root)[1]) continue filter_detect = False for filter in filters: if filter in root: filter_detect = True break if filter_detect: continue for file in files: filepath = os.path.join(root, file).replace(rootdir, "") if filepath.endswith("~"): continue with open(os.path.join(root, file), "r") as f: for i, line in enumerate(f.readlines()): if "\0" in line: # binary file detected break if search.encode("utf-8").lower() in line.lower(): if not result.has_key(filepath): result[filepath] = ([], []) result[filepath][0].append(i+1) if len(line) < 50: result[filepath][1].append(line.strip().replace("\n", "")) else: pos = line.lower().find(search.encode("utf-8").lower()) p1 = pos - 25 if p1 < 0: p1, pre = 0, "" else: pre = "... " p2 = pos + 25 if p2 >= len(line): p2, post = len(line), "" else: post = " ..." result[filepath][1].append(pre + line[p1:p2].strip().replace("\n", "") + post) if result: f = SearchProjectFrame(self, rootdir, result) def insertPath(self, evt): dlg = wx.FileDialog(self, message="Choose a file", defaultDir=PREFERENCES.get("insert_path", os.path.expanduser("~")), defaultFile="", style=wx.OPEN | wx.MULTIPLE) if dlg.ShowModal() == wx.ID_OK: paths = dlg.GetPaths() if len(paths) == 1: text = ensureNFD(paths[0]) if PLATFORM == "win32": text = text.replace("\\", "/") self.panel.editor.ReplaceSelection("'" + text + "'") else: text = ", ".join(["'"+ensureNFD(path)+"'" for path in paths]) if PLATFORM == "win32": text = text.replace("\\", "/") self.panel.editor.ReplaceSelection("[" + text + "]") PREFERENCES["insert_path"] = os.path.split(paths[0])[0] dlg.Destroy() def insertSnippet(self, evt): id = evt.GetId() menu = self.menu7 item = menu.FindItemById(id) name = item.GetLabel() category = item.GetMenu().GetTitle() with codecs.open(os.path.join(ensureNFD(SNIPPETS_PATH), category, name), "r", encoding="utf-8") as f: text = f.read() exec text in locals() self.panel.editor.insertSnippet(snippet["value"]) def openStyleEditor(self, evt): self.style_frame.Show() def changeStyle(self, evt): menu = self.GetMenuBar() id = evt.GetId() st = menu.FindItemById(id).GetLabel() self.setStyle(st, fromMenu=True) self.style_frame.setCurrentStyle(st) def setStyle(self, st, fromMenu=False): global STYLES with open(os.path.join(ensureNFD(STYLES_PATH), st)) as f: text = f.read() exec text in locals() STYLES = copy.deepcopy(style) if not STYLES.has_key('face'): STYLES['face'] = DEFAULT_FONT_FACE if not STYLES.has_key('size'): STYLES['size'] = FONT_SIZE if not STYLES.has_key('size2'): STYLES['size2'] = FONT_SIZE2 for i in range(self.panel.notebook.GetPageCount()): ed = self.panel.notebook.GetPage(i) ed.setStyle() self.panel.project.setStyle() self.panel.markers.scroll.setStyle() self.panel.outputlog.editor.setStyle() PREFERENCES["pref_style"] = st if not fromMenu: itemList = self.menu5.GetMenuItems() for item in itemList: if self.menu5.GetLabelText(item.GetId()) == st: self.menu5.Check(item.GetId(), True) break def onSwitchTabs(self, evt): if evt.GetId() == 10001: forward = True else: forward = False self.panel.notebook.AdvanceSelection(forward) ### Open Prefs ang Logs ### def openPrefs(self, evt): dlg = PreferencesDialog() if dlg.ShowModal() == wx.ID_OK: dlg.writePrefs() dlg.Destroy() def showSnippetEditor(self, evt): self.snippet_frame.Show() def showHideFolderPanel(self, evt): state = evt.GetInt() self.showProjectTree(state) def showHideMarkersPanel(self, evt): state = evt.GetInt() self.showMarkersPanel(state) def showHideOutputPanel(self, evt): state = evt.GetInt() self.showOutputPanel(state) def showProjectTree(self, state): self.showProjItem.Check(state) PREFERENCES["show_folder_panel"] = state if state: if self.panel.project.IsShownOnScreen(): return if not self.panel.splitter.IsSplit(): self.panel.splitter.SplitVertically(self.panel.left_splitter, self.panel.right_splitter, 175) h = self.panel.GetSize()[1] self.panel.left_splitter.SplitHorizontally(self.panel.project, self.panel.markers, h*3/4) self.panel.left_splitter.Unsplit(self.panel.markers) else: h = self.panel.GetSize()[1] self.panel.left_splitter.SplitHorizontally(self.panel.project, self.panel.markers, h*3/4) else: if self.panel.markers.IsShown(): self.panel.left_splitter.Unsplit(self.panel.project) else: self.panel.splitter.Unsplit(self.panel.left_splitter) def showMarkersPanel(self, state): self.showMarkItem.Check(state) PREFERENCES["show_markers_panel"] = state if state: if self.panel.markers.IsShownOnScreen(): return if not self.panel.splitter.IsSplit(): self.panel.splitter.SplitVertically(self.panel.left_splitter, self.panel.right_splitter, 175) h = self.panel.GetSize()[1] self.panel.left_splitter.SplitHorizontally(self.panel.project, self.panel.markers, h*3/4) self.panel.left_splitter.Unsplit(self.panel.project) else: h = self.panel.GetSize()[1] self.panel.left_splitter.SplitHorizontally(self.panel.project, self.panel.markers, h*3/4) else: if self.panel.project.IsShown(): self.panel.left_splitter.Unsplit(self.panel.markers) else: self.panel.splitter.Unsplit(self.panel.left_splitter) def showOutputPanel(self, state): self.showOutputItem.Check(state) PREFERENCES["show_output_panel"] = state if state: if self.panel.outputlog.IsShownOnScreen(): return h = self.panel.GetSize()[1] self.panel.right_splitter.SplitHorizontally(self.panel.notebook, self.panel.outputlog, h*4/5 - h) else: if not self.panel.outputlog.IsShownOnScreen(): return self.panel.right_splitter.Unsplit(self.panel.outputlog) ### New / Open / Save / Delete ### def new(self, event): self.panel.addNewPage() def newFromTemplate(self, event): self.panel.addNewPage() temp = TEMPLATE_DICT[event.GetId()] self.panel.editor.setText(temp) def newRecent(self, file): filename = ensureNFD(os.path.join(TEMP_PATH,'.recent.txt')) try: f = codecs.open(filename, "r", encoding="utf-8") lines = [line.replace("\n", "") for line in f.readlines()] f.close() except: lines = [] if not file in lines: f = codecs.open(filename, "w", encoding="utf-8") lines.insert(0, file) if len(lines) > 20: lines = lines[0:20] for line in lines: f.write(line + '\n') f.close() subId2 = 2000 if lines != []: for item in self.submenu2.GetMenuItems(): self.submenu2.DeleteItem(item) for file in lines: self.submenu2.Append(subId2, toSysEncoding(file)) subId2 += 1 if subId2 > 2000: for i in range(2000, subId2): self.Bind(wx.EVT_MENU, self.openRecent, id=i) def openRecent(self, event): menu = self.GetMenuBar() id = event.GetId() file = menu.FindItemById(id).GetLabel() self.panel.addPage(ensureNFD(file)) def open(self, event, encoding=None): dlg = wx.FileDialog(self, message="Choose a file", defaultDir=PREFERENCES.get("open_file_path", os.path.expanduser("~")), defaultFile="", style=wx.OPEN | wx.MULTIPLE) if dlg.ShowModal() == wx.ID_OK: paths = dlg.GetPaths() for path in paths: filename = ensureNFD(path) self.panel.addPage(filename, encoding=encoding) self.newRecent(filename) PREFERENCES["open_file_path"] = os.path.split(paths[0])[0] dlg.Destroy() def openWithEncoding(self, event): ok = False dlg = wx.SingleChoiceDialog(self, 'Choose the encoding:', 'Encoding', sorted(ENCODING_DICT.keys()), wx.CHOICEDLG_STYLE) dlg.SetSize((-1, 370)) if dlg.ShowModal() == wx.ID_OK: encoding = ENCODING_DICT[dlg.GetStringSelection()] ok = True dlg.Destroy() if ok: self.open(event, encoding=encoding) def openExample(self, event): id = event.GetId() menu = self.menu6 item = menu.FindItemById(id) filename = item.GetLabel() folder = item.GetMenu().GetTitle() path = os.path.join(ensureNFD(EXAMPLE_PATH), folder, filename) self.panel.addPage(ensureNFD(path)) def openTutorial(self, event): filename = {998: "Tutorial_01_RingMod.py", 997: "Tutorial_02_Flanger.py", 996: "Tutorial_03_TriTable.py"}[event.GetId()] if WIN_APP_BUNDLED: self.panel.addPage(os.path.join(os.getcwd(), "Resources", filename)) else: self.panel.addPage(os.path.join(os.getcwd(), filename)) def openFolder(self, event): dlg = wx.DirDialog(self, message="Choose a folder", defaultPath=PREFERENCES.get("open_folder_path", os.path.expanduser("~")), style=wx.DD_DEFAULT_STYLE) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.folder = path self.panel.project.loadFolder(self.folder) sys.path.append(path) PREFERENCES["open_folder_path"] = os.path.split(path)[0] dlg.Destroy() def save(self, event): path = self.panel.editor.path if not path or "Untitled-" in path: self.saveas(None) else: self.panel.editor.saveMyFile(path) self.SetTitle(path) tab = self.panel.notebook.GetSelection() self.panel.notebook.SetPageText(tab, os.path.split(path)[1].split('.')[0]) def saveas(self, event): deffile = os.path.split(self.panel.editor.path)[1] dlg = wx.FileDialog(self, message="Save file as ...", defaultDir=PREFERENCES.get("save_file_path", os.path.expanduser("~")), defaultFile=deffile, style=wx.SAVE) dlg.SetFilterIndex(0) if dlg.ShowModal() == wx.ID_OK: path = ensureNFD(dlg.GetPath()) self.panel.editor.path = path self.panel.editor.setStyle() self.panel.editor.SetCurrentPos(0) self.panel.editor.addText(" ", False) self.panel.editor.DeleteBackNotLine() self.panel.editor.saveMyFile(path) self.SetTitle(path) tab = self.panel.notebook.GetSelection() self.panel.notebook.SetPageText(tab, os.path.split(path)[1].split('.')[0]) self.newRecent(path) PREFERENCES["save_file_path"] = os.path.split(path)[0] dlg.Destroy() def saveasTemplate(self, event): dlg = wx.TextEntryDialog(self, 'Give a name to your template:', 'Save file as template...') if dlg.ShowModal() == wx.ID_OK: fname = dlg.GetValue() if not fname.endswith(".py"): fname = fname + ".py" try: text = self.panel.editor.GetTextUTF8() except: text = self.panel.editor.GetText() with open(os.path.join(TEMPLATE_PATH, fname), "w") as f: f.write(text) dlg.Destroy() def close(self, event): action = self.panel.editor.close() if action == 'delete': self.panel.close_from_menu = True self.panel.deletePage() else: pass self.panel.close_from_menu = False def closeAll(self, event): count = self.panel.notebook.GetPageCount() while count > 0: count -= 1 self.panel.setPage(count) self.close(None) ### Run actions ### def getCurrentWorkingDirectory(self): if self.master_document != None: path = ensureNFD(self.master_document) else: path = ensureNFD(self.panel.editor.path) cwd = os.path.expanduser("~") if os.path.isfile(path): try: cwd = toSysEncoding(os.path.split(path)[0]) except: pass return cwd def addCwdToSysPath(self, text): cwd = self.getCurrentWorkingDirectory() check = True newtext = "" for line in text.splitlines(): if check and not line.startswith("#"): newtext += '# encoding: utf-8\nimport sys\nsys.path.append("%s")\n' % cwd check = False newtext += line + "\n" return newtext def format_outputLog(self, evt): data = evt.data self.panel.outputlog.appendToLog(data["log"]) if not data["active"]: self.panel.outputlog.removeProcess(data["pid"], data["filename"]) def run(self, path): cwd = self.getCurrentWorkingDirectory() th = RunningThread(path, cwd, self) if self.master_document != None: filename = os.path.split(self.master_document)[1] elif "Untitled-" in self.panel.editor.path: filename = self.panel.editor.path else: filename = os.path.split(self.panel.editor.path)[1] th.setFileName(filename) th.setPID(self.processID) self.processes[self.processID] = [th, filename] self.panel.outputlog.addProcess(self.processID, filename) self.processID += 1 th.start() def runner(self, event): if self.master_document != None: with open(self.master_document, "r") as f: text = f.read() else: text = self.panel.editor.GetTextUTF8() if text != "": text = self.addCwdToSysPath(text) with open(TEMP_FILE, "w") as f: f.write(text) self.run(TEMP_FILE) def runSelection(self, event): text = self.panel.editor.GetSelectedTextUTF8() if text != "": text = self.addCwdToSysPath(text) with open(TEMP_FILE, "w") as f: f.write(text) self.run(TEMP_FILE) def runSelectionAsPyo(self, event): text = self.panel.editor.GetSelectedTextUTF8() if text == "": pos = self.panel.editor.GetCurrentPos() line = self.panel.editor.LineFromPosition(pos) text = self.panel.editor.GetLineUTF8(line) text = self.addCwdToSysPath(text) with open(TEMP_FILE, "w") as f: f.write("from pyo import *\ns = Server().boot()\n") f.write(text) f.write("\ns.gui(locals())\n") self.run(TEMP_FILE) def execSelection(self, event): text = self.panel.editor.GetSelectedTextUTF8() if text == "": pos = self.panel.editor.GetCurrentPos() line = self.panel.editor.LineFromPosition(pos) text = self.panel.editor.GetLineUTF8(line) if not text.startswith("print"): text = "print " + text else: pos = self.panel.editor.GetSelectionEnd() line = self.panel.editor.LineFromPosition(pos) pos = self.panel.editor.GetLineEndPosition(line) self.panel.editor.SetCurrentPos(pos) self.panel.editor.addText("\n", False) with stdoutIO() as s: exec text self.panel.editor.addText(s.getvalue()) def prepareBackgroundServer(self): outDriverIndex = -1 preferedDriver = PREFERENCES.get("background_server_out_device", "") if preferedDriver != "": driverList, driverIndexes = pa_get_output_devices() driverList = [ensureNFD(driver) for driver in driverList] if preferedDriver and preferedDriver in driverList: outDriverIndex = driverIndexes[driverList.index(preferedDriver)] inDriverIndex = -1 preferedDriver = PREFERENCES.get("background_server_in_device", "") if preferedDriver != "": driverList, driverIndexes = pa_get_input_devices() driverList = [ensureNFD(driver) for driver in driverList] if preferedDriver and preferedDriver in driverList: inDriverIndex = driverIndexes[driverList.index(preferedDriver)] midiOutDriverIndex = -1 preferedDriver = PREFERENCES.get("background_server_midiout_device", "") if preferedDriver != "": driverList, driverIndexes = pm_get_output_devices() driverList = [ensureNFD(driver) for driver in driverList] if preferedDriver and preferedDriver in driverList: midiOutDriverIndex = driverIndexes[driverList.index(preferedDriver)] midiInDriverIndex = -1 preferedDriver = PREFERENCES.get("background_server_midiin_device", "") if preferedDriver != "": driverList, driverIndexes = pm_get_input_devices() driverList = [ensureNFD(driver) for driver in driverList] if preferedDriver and preferedDriver in driverList: midiInDriverIndex = driverIndexes[driverList.index(preferedDriver)] with open(os.path.join(TEMP_PATH, "background_server.py"), "w") as f: f.write("print 'Starting background server...'\nimport time, sys, os\nsys.path.append(os.getcwd())\nfrom pyo import *\n") f.write("s = Server(%s)\n" % BACKGROUND_SERVER_ARGS) if outDriverIndex != -1: f.write("s.setOutputDevice(%d)\n" % outDriverIndex) if inDriverIndex != -1: f.write("s.setInputDevice(%d)\n" % inDriverIndex) if midiOutDriverIndex != -1: f.write("s.setMidiOutputDevice(%d)\n" % midiOutDriverIndex) if midiInDriverIndex != -1: f.write("s.setMidiInputDevice(%d)\n" % midiInDriverIndex) f.write("s.boot()\ns.start()\n\n") f.write("def _quit_():\n s.stop()\n time.sleep(0.25)\n exit()\n") def resetBackgroundServerMenu(self): self.back_server_started = False self.backServerItem.SetItemLabel("Start Pyo Background Server") self.sendToServerItem.Enable(False) def startStopBackgroundServer(self, evt): if not self.back_server_started: self.prepareBackgroundServer() cwd = self.getCurrentWorkingDirectory() th = BackgroundServerThread(cwd, self) th.setPID(1000) self.processes[1000] = [th, 'background_server.py'] self.panel.outputlog.addProcess(1000, 'background_server.py') th.start() self.back_server_started = True self.backServerItem.SetItemLabel("Stop Pyo Background Server") self.sendToServerItem.Enable(True) else: self.processes[1000][0].kill() self.back_server_started = False self.backServerItem.SetItemLabel("Start Pyo Background Server") self.sendToServerItem.Enable(False) def sendSelectionToBackgroundServer(self, evt): end = None text = self.panel.editor.GetSelectedTextUTF8() if text == "": pos = self.panel.editor.GetCurrentPos() line = self.panel.editor.LineFromPosition(pos) text = self.panel.editor.GetLineUTF8(line) else: end = self.panel.editor.GetSelectionEnd() if self.back_server_started: self.processes[1000][0].sendText(text) if end != None: self.panel.editor.SetCurrentPos(end) self.panel.editor.LineDown() line = self.panel.editor.GetCurrentLine() pos = self.panel.editor.PositionFromLine(line) self.panel.editor.SetCurrentPos(pos) self.panel.editor.SetSelectionEnd(pos) def buildDoc(self): self.doc_frame = ManualFrame(osx_app_bundled=OSX_APP_BUNDLED, which_python=WHICH_PYTHON, caller_need_to_invoke_32_bit=CALLER_NEED_TO_INVOKE_32_BIT, set_32_bit_arch=SET_32_BIT_ARCH) def showDoc(self, evt): if not self.doc_frame.IsShown(): self.doc_frame.Show() word = self.panel.editor.getWordUnderCaret() if word: self.doc_frame.doc_panel.getPage(word) def showDocFrame(self, evt): if not self.doc_frame.IsShown(): self.doc_frame.Show() def rebuildDoc(self, evt): shutil.rmtree(os.path.join(TEMP_PATH, "doc"), True) try: self.doc_frame.Destroy() except: pass self.buildDoc() def showArgs(self, evt): self.panel.editor.onShowTip() def showDocString(self, evt): self.panel.editor.onShowDocString() def onShowEditorKeyCommands(self, evt): if not self.keyCommandsFrame.IsShown(): self.keyCommandsFrame.CenterOnParent() self.keyCommandsFrame.Show() def onHelpAbout(self, evt): info = wx.AboutDialogInfo() info.Name = APP_NAME info.Version = APP_VERSION info.Copyright = u"(C) 2012 Olivier Belanger" info.Description = "E-Pyo is a text editor especially configured to edit pyo audio programs.\n\n" wx.AboutBox(info) def OnClose(self, event): if self.back_server_started == True: try: self.startStopBackgroundServer(None) time.sleep(0.5) except: pass with open(PREFERENCES_PATH, "w") as f: f.write("epyo_prefs = %s" % str(PREFERENCES)) try: self.snippet_frame.Destroy() except: pass try: self.doc_frame.Destroy() except: pass try: self.keyCommandsFrame.Destroy() except: pass self.panel.OnQuit() self.Destroy() def getPrintData(self): return self.print_data def OnPrintPreview(self, evt): wx.CallAfter(self.showPrintPreview) def showPrintPreview(self): printout = STCPrintout(self.panel.editor, title="", border=False, output_point_size=None) printout2 = STCPrintout(self.panel.editor, title="", border=False, output_point_size=None) preview = wx.PrintPreview(printout, printout2, self.getPrintData()) preview.SetZoom(100) if preview.IsOk(): pre_frame = wx.PreviewFrame(preview, self, "Print Preview") dsize = wx.GetDisplaySize() pre_frame.SetInitialSize((self.GetSize()[0], dsize.GetHeight() - 100)) pre_frame.Initialize() pre_frame.Show() else: wx.MessageBox("Failed to create print preview", "Print Error", style=wx.ICON_ERROR|wx.OK) def OnPrint(self, evt): wx.CallAfter(self.showPrint) def showPrint(self): pdd = wx.PrintDialogData(self.getPrintData()) printer = wx.Printer(pdd) printout = STCPrintout(self.panel.editor, title="", border=False, output_point_size=None) result = printer.Print(self.panel.editor, printout) if result: data = printer.GetPrintDialogData() self.print_data = wx.PrintData(data.GetPrintData()) elif printer.GetLastError() == wx.PRINTER_ERROR: wx.MessageBox("There was an error when printing.\n" "Check that your printer is properly connected.", "Printer Error", style=wx.ICON_ERROR|wx.OK) printout.Destroy() class MainPanel(wx.Panel): def __init__(self, parent, size=(1200,800), style=wx.SUNKEN_BORDER): wx.Panel.__init__(self, parent, size=size, style=wx.SUNKEN_BORDER) self.new_inc = 0 self.close_from_menu = False self.mainFrame = parent mainBox = wx.BoxSizer(wx.HORIZONTAL) self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_LIVE_UPDATE|wx.SP_3DSASH) self.splitter.SetMinimumPaneSize(150) self.left_splitter = wx.SplitterWindow(self.splitter, -1, style=wx.SP_LIVE_UPDATE|wx.SP_3DSASH) self.right_splitter = wx.SplitterWindow(self.splitter, -1, style=wx.SP_LIVE_UPDATE|wx.SP_3DSASH) self.project = ProjectTree(self.left_splitter, self, (-1, -1)) self.markers = MarkersPanel(self.left_splitter, self, (-1, -1)) self.notebook = FNB.FlatNotebook(self.right_splitter, size=(-1,-1)) self.notebook.SetAGWWindowStyleFlag(FNB.FNB_FF2|FNB.FNB_X_ON_TAB|FNB.FNB_NO_X_BUTTON|FNB.FNB_DROPDOWN_TABS_LIST|FNB.FNB_HIDE_ON_SINGLE_TAB) self.addNewPage() self.outputlog = OutputLogPanel(self.right_splitter, self, size=(-1,150)) self.right_splitter.SplitHorizontally(self.notebook, self.outputlog, (self.GetSize()[1]*4/5) - self.GetSize()[1]) self.splitter.SplitVertically(self.left_splitter, self.right_splitter, 175) self.splitter.Unsplit(self.left_splitter) mainBox.Add(self.splitter, 1, wx.EXPAND) self.SetSizer(mainBox) self.notebook.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.onPageChange) self.notebook.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.onClosingPage) def addNewPage(self): title = "Untitled-%i.py" % self.new_inc self.new_inc += 1 editor = Editor(self.notebook, -1, size=(0, -1), setTitle=self.SetTitle, getTitle=self.GetTitle) editor.path = title editor.setStyle() self.notebook.AddPage(editor, title, True) self.editor = editor def addPage(self, file, encoding=None): editor = Editor(self.notebook, -1, size=(0, -1), setTitle=self.SetTitle, getTitle=self.GetTitle) label = os.path.split(file)[1].split('.')[0] self.notebook.AddPage(editor, label, True) text = "" if encoding != None: with codecs.open(file, "r", encoding=encoding) as f: text = f.read() else: for enc in ENCODING_LIST: try: with codecs.open(file, "r", encoding=enc) as f: text = f.read() break except: continue editor.setText(ensureNFD(text)) # Scan the entire document (needed for FoldAll to fold everything) editor.GotoLine(editor.GetLineCount()) wx.CallAfter(editor.GotoLine, 0) editor.path = file editor.saveMark = True editor.EmptyUndoBuffer() editor.SetSavePoint() editor.setStyle() self.editor = editor self.SetTitle(file) with open(MARKERS_FILE, "r") as f: lines = [line.replace("\n", "").split("=") for line in f.readlines()] founded = False for line in lines: if line[1] == editor.path: marker_file = line[0] founded = True break if founded: with open(os.path.join(MARKERS_PATH, marker_file), "r") as f: text = f.read() exec text in locals() self.editor.setMarkers(copy.deepcopy(markers)) def onClosingPage(self, evt): if not self.close_from_menu: action = self.editor.close() if action == "keep": evt.Veto() def deletePage(self): select = self.notebook.GetSelection() self.notebook.DeletePage(select) if self.notebook.GetPageCount() == 0: self.addNewPage() def setPage(self, pageNum): totalNum = self.notebook.GetPageCount() if pageNum < totalNum: self.notebook.SetSelection(pageNum) def onPageChange(self, event): self.markers.setDict({}) self.editor = self.notebook.GetPage(self.notebook.GetSelection()) self.editor.SetFocus() if not self.editor.path: if self.editor.GetModify(): self.SetTitle("*** E-Pyo Editor ***") else: self.SetTitle("E-Pyo Editor") else: if self.editor.GetModify(): self.SetTitle('*** ' + self.editor.path + ' ***') else: self.SetTitle(self.editor.path) self.markers.setDict(self.editor.markers_dict) def SetTitle(self, title): self.mainFrame.SetTitle(title) def GetTitle(self): return self.mainFrame.GetTitle() def OnQuit(self): for i in range(self.notebook.GetPageCount()): ed = self.notebook.GetPage(i) ed.Close() ####################################################### ### The idea of EditorPanel is to allow multiple views ### at the same time in a single notebook page. ### Also: A tree view of classes and functions of the file ### Not yet implemented... ( TODO ) ####################################################### class EditorPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent, -1) self.editor = Editor(parent, -1, size=(0, -1)) self.editor2 = Editor(parent, -1, size=(0, -1)) box = wx.BoxSizer(wx.HORIZONTAL) box.Add(self.editor, 1, wx.ALL|wx.EXPAND, 5) box.Add(self.editor2, 1, wx.ALL|wx.EXPAND, 5) self.SetSizerAndFit(box) class Editor(stc.StyledTextCtrl): def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style= wx.NO_BORDER | wx.WANTS_CHARS, setTitle=None, getTitle=None): stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style) dt = MyFileDropTarget(self) self.SetDropTarget(dt) self.SetSTCCursor(2) self.panel = parent self.path = '' self.setTitle = setTitle self.getTitle = getTitle self.saveMark = False self.inside = False self.anchor1 = self.anchor2 = 0 self.args_buffer = [] self.snip_buffer = [] self.args_line_number = [0,0] self.quit_navigate_args = False self.quit_navigate_snip = False self.markers_dict = {} self.current_marker = -1 self.objs_attr_dict = {} self.auto_comp_container = PREFERENCES.get("auto_comp_container", 0) self.alphaStr = string.lowercase + string.uppercase + '0123456789' self.Colourise(0, -1) self.SetCurrentPos(0) self.SetIndent(4) self.SetBackSpaceUnIndents(True) self.SetTabIndents(True) self.SetTabWidth(4) self.SetUseTabs(False) self.AutoCompSetChooseSingle(True) self.SetEOLMode(wx.stc.STC_EOL_LF) self.SetPasteConvertEndings(True) self.SetControlCharSymbol(32) self.SetLayoutCache(True) self.SetViewWhiteSpace(PREFERENCES.get("show_invisibles", 0)) self.SetViewEOL(PREFERENCES.get("show_invisibles", 0)) self.SetEdgeMode(PREFERENCES.get("show_edge_line", 0)) mode = {0: stc.STC_WRAP_NONE, 1: stc.STC_WRAP_WORD}[PREFERENCES.get("wrap_text_line", 0)] self.SetWrapMode(mode) self.SetProperty("fold", "1") self.SetProperty("tab.timmy.whinge.level", "1") self.SetMargins(5, 5) self.SetUseAntiAliasing(True) self.SetEdgeColour(STYLES["lineedge"]['colour']) self.SetEdgeColumn(78) self.SetMarginType(0, stc.STC_MARGIN_SYMBOL) self.SetMarginWidth(0, 12) self.SetMarginMask(0, ~wx.stc.STC_MASK_FOLDERS) self.SetMarginSensitive(0, True) self.SetMarginType(1, stc.STC_MARGIN_NUMBER) self.SetMarginWidth(1, 28) self.SetMarginMask(1, 0) self.SetMarginSensitive(1, False) self.SetMarginType(2, stc.STC_MARGIN_SYMBOL) self.SetMarginWidth(2, 12) self.SetMarginMask(2, stc.STC_MASK_FOLDERS) self.SetMarginSensitive(2, True) self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) self.Bind(wx.EVT_CHAR, self.OnChar) self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI) self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick) self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick) self.EmptyUndoBuffer() self.SetFocus() self.setStyle() # Remove unwanted KeyCommands self.CmdKeyClear(stc.STC_KEY_RIGHT, stc.STC_SCMOD_ALT) self.CmdKeyClear(stc.STC_KEY_LEFT, stc.STC_SCMOD_ALT) self.CmdKeyClear(stc.STC_KEY_RIGHT, stc.STC_SCMOD_SHIFT | stc.STC_SCMOD_ALT) self.CmdKeyClear(stc.STC_KEY_LEFT, stc.STC_SCMOD_SHIFT | stc.STC_SCMOD_ALT) self.CmdKeyClear(stc.STC_KEY_RIGHT, stc.STC_SCMOD_CTRL) self.CmdKeyClear(stc.STC_KEY_LEFT, stc.STC_SCMOD_CTRL) self.CmdKeyClear(stc.STC_KEY_RIGHT, stc.STC_SCMOD_SHIFT | stc.STC_SCMOD_CTRL) self.CmdKeyClear(stc.STC_KEY_LEFT, stc.STC_SCMOD_SHIFT | stc.STC_SCMOD_CTRL) self.CmdKeyClear(stc.STC_KEY_DELETE, 0) self.CmdKeyClear(stc.STC_KEY_DELETE, stc.STC_SCMOD_SHIFT) self.CmdKeyClear(stc.STC_KEY_DELETE, stc.STC_SCMOD_CTRL) self.CmdKeyClear(stc.STC_KEY_DELETE, stc.STC_SCMOD_SHIFT | stc.STC_SCMOD_CTRL) self.CmdKeyClear(stc.STC_KEY_BACK, stc.STC_SCMOD_ALT) self.CmdKeyClear(stc.STC_KEY_BACK, stc.STC_SCMOD_SHIFT) self.CmdKeyClear(stc.STC_KEY_BACK, stc.STC_SCMOD_CTRL) self.CmdKeyClear(stc.STC_KEY_BACK, stc.STC_SCMOD_CTRL | stc.STC_SCMOD_SHIFT) self.CmdKeyClear(stc.STC_KEY_INSERT, 0) self.CmdKeyClear(stc.STC_KEY_INSERT, stc.STC_SCMOD_SHIFT) self.CmdKeyClear(stc.STC_KEY_INSERT, stc.STC_SCMOD_CTRL) self.CmdKeyClear(ord('Y'), stc.STC_SCMOD_CTRL) self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL) self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL) self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL) self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL | stc.STC_SCMOD_SHIFT) self.CmdKeyClear(stc.STC_KEY_RETURN, stc.STC_SCMOD_SHIFT) self.CmdKeyClear(stc.STC_KEY_ADD, stc.STC_SCMOD_CTRL) self.CmdKeyClear(stc.STC_KEY_SUBTRACT, stc.STC_SCMOD_CTRL) self.CmdKeyClear(stc.STC_KEY_DIVIDE, stc.STC_SCMOD_CTRL) self.CmdKeyAssign(ord('U'), stc.STC_SCMOD_CTRL, stc.STC_CMD_UPPERCASE) self.CmdKeyAssign(ord('U'), stc.STC_SCMOD_CTRL | stc.STC_SCMOD_SHIFT, stc.STC_CMD_LOWERCASE) wx.CallAfter(self.SetAnchor, 0) self.Refresh() def setStyle(self): def buildStyle(forekey, backkey=None, smallsize=False): if smallsize: st = "face:%s,fore:%s,size:%s" % (STYLES['face'], STYLES[forekey]['colour'], STYLES['size2']) else: st = "face:%s,fore:%s,size:%s" % (STYLES['face'], STYLES[forekey]['colour'], STYLES['size']) if backkey: st += ",back:%s" % STYLES[backkey]['colour'] if STYLES[forekey].has_key('bold'): if STYLES[forekey]['bold']: st += ",bold" if STYLES[forekey]['italic']: st += ",italic" if STYLES[forekey]['underline']: st += ",underline" return st self.StyleSetSpec(stc.STC_STYLE_DEFAULT, buildStyle('default', 'background')) self.StyleClearAll() # Reset all to be like the default self.MarkerDefine(0, stc.STC_MARK_SHORTARROW, STYLES['markerbg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_ARROW, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_ARROWDOWN, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_LCORNERCURVE, STYLES['markerfg']['colour'], STYLES['markerbg']['colour']) self.StyleSetSpec(stc.STC_STYLE_DEFAULT, buildStyle('default', 'background')) self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, buildStyle('linenumber', 'marginback', True)) self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, buildStyle('default') + ",size:5") self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, buildStyle('default', 'bracelight') + ",bold") self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, buildStyle('default', 'bracebad') + ",bold") ext = os.path.splitext(self.path)[1].strip(".") if ext == "": try: with open(self.path, "r") as f: fline = f.readline() if fline.startswith("#!"): fline = fline.replace("/", " ") last = fline.split()[-1] ext = {"python": "py", "bash": "sh", "sh": "sh"}.get(last, "") else: text = f.read() if "desc:" in text: ext = "jsfx" except: pass if ext in ["py", "pyw", "c5"]: self.SetLexer(stc.STC_LEX_PYTHON) self.SetStyleBits(self.GetStyleBitsNeeded()) self.SetKeyWords(0, " ".join(keyword.kwlist) + " None True False ") self.SetKeyWords(1, " ".join(PYO_WORDLIST)) self.StyleSetSpec(stc.STC_P_DEFAULT, buildStyle('default')) self.StyleSetSpec(stc.STC_P_COMMENTLINE, buildStyle('comment')) self.StyleSetSpec(stc.STC_P_NUMBER, buildStyle('number')) self.StyleSetSpec(stc.STC_P_STRING, buildStyle('string')) self.StyleSetSpec(stc.STC_P_CHARACTER, buildStyle('string')) self.StyleSetSpec(stc.STC_P_WORD, buildStyle('keyword')) self.StyleSetSpec(stc.STC_P_WORD2, buildStyle('pyokeyword')) self.StyleSetSpec(stc.STC_P_TRIPLE, buildStyle('triple')) self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, buildStyle('triple')) self.StyleSetSpec(stc.STC_P_CLASSNAME, buildStyle('class')) self.StyleSetSpec(stc.STC_P_DEFNAME, buildStyle('function')) self.StyleSetSpec(stc.STC_P_OPERATOR, buildStyle('operator')) self.StyleSetSpec(stc.STC_P_IDENTIFIER, buildStyle('default')) self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, buildStyle('commentblock')) elif ext in ["c", "cc", "cpp", "cxx", "cs", "h", "hh", "hpp", "hxx"]: self.SetLexer(stc.STC_LEX_CPP) self.SetStyleBits(self.GetStyleBitsNeeded()) self.SetProperty('fold.comment', '1') self.SetProperty('fold.preprocessor', '1') self.SetProperty('fold.compact', '1') self.SetProperty('styling.within.preprocessor', '0') self.SetKeyWords(0, "auto break case char const continue default do double else enum extern float for goto if int long \ register return short signed sizeof static struct switch typedef union unsigned void volatile while ") self.StyleSetSpec(stc.STC_C_DEFAULT, buildStyle('default')) self.StyleSetSpec(stc.STC_C_COMMENT, buildStyle('comment')) self.StyleSetSpec(stc.STC_C_COMMENTDOC, buildStyle('comment')) self.StyleSetSpec(stc.STC_C_COMMENTLINE, buildStyle('comment')) self.StyleSetSpec(stc.STC_C_COMMENTLINEDOC, buildStyle('comment')) self.StyleSetSpec(stc.STC_C_NUMBER, buildStyle('number')) self.StyleSetSpec(stc.STC_C_STRING, buildStyle('string')) self.StyleSetSpec(stc.STC_C_CHARACTER, buildStyle('string')) self.StyleSetSpec(stc.STC_C_WORD, buildStyle('keyword')) self.StyleSetSpec(stc.STC_C_OPERATOR, buildStyle('operator')) self.StyleSetSpec(stc.STC_C_IDENTIFIER, buildStyle('default')) self.StyleSetSpec(stc.STC_C_PREPROCESSOR, buildStyle('commentblock')) elif ext == "sh": self.SetLexer(stc.STC_LEX_BASH) self.SetStyleBits(self.GetStyleBitsNeeded()) self.SetKeyWords(0, "! [[ ]] case do done elif else esac fi for function if in select then time until while { } \ alias bg bind break builtin caller cd command compgen complete compopt continue declare dirs disown echo enable \ eval exec exit export fc fg getopts hash help history jobs kill let local logout mapfile popd printf pushd pwd \ read readarray readonly return set shift shopt source suspend test times trap type typeset ulimit umask unalias unset wait") self.StyleSetSpec(stc.STC_SH_DEFAULT, buildStyle('default')) self.StyleSetSpec(stc.STC_SH_COMMENTLINE, buildStyle('comment')) self.StyleSetSpec(stc.STC_SH_NUMBER, buildStyle('number')) self.StyleSetSpec(stc.STC_SH_STRING, buildStyle('string')) self.StyleSetSpec(stc.STC_SH_CHARACTER, buildStyle('string')) self.StyleSetSpec(stc.STC_SH_WORD, buildStyle('keyword')) self.StyleSetSpec(stc.STC_SH_OPERATOR, buildStyle('default')) self.StyleSetSpec(stc.STC_SH_IDENTIFIER, buildStyle('default')) self.StyleSetSpec(stc.STC_SH_PARAM, buildStyle('default')) self.StyleSetSpec(stc.STC_SH_SCALAR, buildStyle('function')) elif ext in ["jsfx", "jsfx-inc"]: self.SetLexer(stc.STC_LEX_CPP) self.SetStyleBits(self.GetStyleBitsNeeded()) self.SetProperty('fold.comment', '1') self.SetProperty('fold.preprocessor', '1') self.SetProperty('fold.compact', '1') self.SetProperty('styling.within.preprocessor', '0') self.SetKeyWords(1, "abs acos asin atan atan2 atexit ceil convolve_c cos defer eval exp fclose feof fflush \ fft fft_ipermute fft_permute fgetc floor fopen fprintf fread freembuf fseek ftell fwrite \ gfx_aaaaa gfx_arc gfx_blit gfx_blit gfx_blitext gfx_blurto gfx_circle gfx_deltablit \ gfx_drawchar gfx_drawnumber gfx_drawstr gfx_getchar gfx_getfont gfx_getimgdim gfx_getpixel \ gfx_gradrect gfx_init gfx_line gfx_lineto gfx_loadimg gfx_measurestr gfx_muladdrect gfx_printf \ gfx_quit gfx_rect gfx_rectto gfx_roundrect gfx_setfont gfx_setimgdim gfx_setpixel gfx_transformblit \ gfx_update ifft invsqrt log log10 match matchi max memcpy memset min pow printf rand sign sin sleep \ sprintf sqr sqrt stack_exch stack_peek stack_pop stack_push str_delsub str_getchar str_insert \ str_setchar str_setlen strcat strcmp strcpy strcpy_from strcpy_substr stricmp strlen strncat strncmp \ strncpy strnicmp tan tcp_close tcp_connect tcp_listen tcp_listen_end tcp_recv tcp_send tcp_set_block \ time time_precise") self.SetKeyWords(0, "loop while function local static instance this global globals _global gfx_r gfx_g gfx_b gfx_a gfx_w \ gfx_h gfx_x gfx_y gfx_mode gfx_clear gfx_dest gfx_texth mouse_x mouse_y mouse_cap mouse_wheel mouse_hwheel \ @init @slider @sample @block @serialize @gfx import desc slider1 slider2 slider3 slider4 slider5 \ slider6 slider7 slider8 slider9 slider10 slider11 slider12 slider13 slider14 slider15 slider16 in_pin \ out_pin filename ") self.StyleSetSpec(stc.STC_C_DEFAULT, buildStyle('default')) self.StyleSetSpec(stc.STC_C_COMMENT, buildStyle('comment')) self.StyleSetSpec(stc.STC_C_COMMENTDOC, buildStyle('comment')) self.StyleSetSpec(stc.STC_C_COMMENTLINE, buildStyle('comment')) self.StyleSetSpec(stc.STC_C_COMMENTLINEDOC, buildStyle('comment')) self.StyleSetSpec(stc.STC_C_NUMBER, buildStyle('number')) self.StyleSetSpec(stc.STC_C_STRING, buildStyle('string')) self.StyleSetSpec(stc.STC_C_CHARACTER, buildStyle('string')) self.StyleSetSpec(stc.STC_C_WORD, buildStyle('keyword')) self.StyleSetSpec(stc.STC_C_WORD2, buildStyle('pyokeyword')) self.StyleSetSpec(stc.STC_C_OPERATOR, buildStyle('operator')) self.StyleSetSpec(stc.STC_C_IDENTIFIER, buildStyle('default')) self.StyleSetSpec(stc.STC_C_PREPROCESSOR, buildStyle('commentblock')) elif ext == "md": self.SetLexer(stc.STC_LEX_MARKDOWN) self.SetStyleBits(self.GetStyleBitsNeeded()) self.StyleSetSpec(stc.STC_MARKDOWN_DEFAULT, buildStyle('default')) self.StyleSetSpec(stc.STC_MARKDOWN_LINE_BEGIN, buildStyle('default')) self.StyleSetSpec(stc.STC_MARKDOWN_STRONG1, buildStyle('default') + ",italic,bold") self.StyleSetSpec(stc.STC_MARKDOWN_STRONG2, buildStyle('default') + ",italic,bold") self.StyleSetSpec(stc.STC_MARKDOWN_EM1, buildStyle('default') + ",italic") self.StyleSetSpec(stc.STC_MARKDOWN_EM2, buildStyle('default') + ",italic") self.StyleSetSpec(stc.STC_MARKDOWN_HEADER1, buildStyle('comment') + ", bold") self.StyleSetSpec(stc.STC_MARKDOWN_HEADER2, buildStyle('comment')) self.StyleSetSpec(stc.STC_MARKDOWN_HEADER3, buildStyle('commentblock') + ", bold") self.StyleSetSpec(stc.STC_MARKDOWN_HEADER4, buildStyle('commentblock') + ", bold") self.StyleSetSpec(stc.STC_MARKDOWN_HEADER5, buildStyle('commentblock')) self.StyleSetSpec(stc.STC_MARKDOWN_HEADER6, buildStyle('commentblock')) self.StyleSetSpec(stc.STC_MARKDOWN_PRECHAR, buildStyle('default')) self.StyleSetSpec(stc.STC_MARKDOWN_ULIST_ITEM, buildStyle('string')) self.StyleSetSpec(stc.STC_MARKDOWN_OLIST_ITEM, buildStyle('triple')) self.StyleSetSpec(stc.STC_MARKDOWN_BLOCKQUOTE, buildStyle('string')) self.StyleSetSpec(stc.STC_MARKDOWN_STRIKEOUT, buildStyle('string')) self.StyleSetSpec(stc.STC_MARKDOWN_HRULE, buildStyle('triple')) self.StyleSetSpec(stc.STC_MARKDOWN_LINK, buildStyle('function')) self.StyleSetSpec(stc.STC_MARKDOWN_CODE, buildStyle('default') + ",italic,bold") self.StyleSetSpec(stc.STC_MARKDOWN_CODE2, buildStyle('default') + ",italic,bold") self.StyleSetSpec(stc.STC_MARKDOWN_CODEBK, buildStyle('default') + ",italic,bold") elif ext == "lua": self.SetLexer(stc.STC_LEX_LUA) self.SetStyleBits(self.GetStyleBitsNeeded()) self.SetKeyWords(0, "and break do else elseif for if in nil not or \ repeat then until while function local end return true false ") self.StyleSetSpec(stc.STC_LUA_DEFAULT, buildStyle('default')) self.StyleSetSpec(stc.STC_LUA_COMMENT, buildStyle('comment')) self.StyleSetSpec(stc.STC_LUA_COMMENTLINE, buildStyle('comment')) self.StyleSetSpec(stc.STC_LUA_COMMENTDOC, buildStyle('commentblock')) self.StyleSetSpec(stc.STC_LUA_NUMBER, buildStyle('number')) self.StyleSetSpec(stc.STC_LUA_WORD, buildStyle('keyword')) self.StyleSetSpec(stc.STC_LUA_STRING, buildStyle('string')) self.StyleSetSpec(stc.STC_LUA_CHARACTER, buildStyle('string')) self.StyleSetSpec(stc.STC_LUA_LITERALSTRING, buildStyle('triple')) self.StyleSetSpec(stc.STC_LUA_PREPROCESSOR, buildStyle('default') + ",italic") self.StyleSetSpec(stc.STC_LUA_OPERATOR, buildStyle('operator')) self.StyleSetSpec(stc.STC_LUA_IDENTIFIER, buildStyle('default')) self.StyleSetSpec(stc.STC_LUA_STRINGEOL, buildStyle('default') + ",bold") self.StyleSetSpec(stc.STC_LUA_WORD2, buildStyle('pyokeyword')) self.StyleSetSpec(stc.STC_LUA_WORD3, buildStyle('pyokeyword')) self.StyleSetSpec(stc.STC_LUA_WORD4, buildStyle('pyokeyword')) self.StyleSetSpec(stc.STC_LUA_WORD5, buildStyle('pyokeyword')) self.StyleSetSpec(stc.STC_LUA_WORD6, buildStyle('pyokeyword')) self.StyleSetSpec(stc.STC_LUA_WORD7, buildStyle('pyokeyword')) self.StyleSetSpec(stc.STC_LUA_WORD8, buildStyle('pyokeyword')) self.StyleSetSpec(stc.STC_LUA_LABEL, buildStyle('default') + ",italic,bold") self.SetEdgeColour(STYLES["lineedge"]['colour']) self.SetCaretForeground(STYLES['caret']['colour']) self.SetSelBackground(1, STYLES['selback']['colour']) self.SetFoldMarginColour(True, STYLES['foldmarginback']['colour']) self.SetFoldMarginHiColour(True, STYLES['foldmarginback']['colour']) self.CallTipSetForeground(STYLES['default']['colour']) self.CallTipSetBackground(STYLES['background']['colour']) # WxPython 3 needs the lexer to be set before folding property self.SetProperty("fold", "1") def insertBlockHead(self): pos = self.PositionFromLine(self.GetCurrentLine()) if self.GetLine(self.GetCurrentLine()).strip() == "": self.InsertText(pos, "#-->") else: self.InsertText(pos, "#-->\n") def insertBlockTail(self): pos = self.GetLineEndPosition(self.GetCurrentLine()) if self.GetLine(self.GetCurrentLine()).strip() == "": self.InsertText(pos, "#<--") else: self.InsertText(pos, "\n#<--") def selectCodeBlock(self): self.OnDoubleClick(None) def OnDoubleClick(self, evt): """ Double-click used to select chunk of code between #--> and #<-- """ if "#-->" in self.GetLine(self.GetCurrentLine()): first = self.GetCurrentLine() last = self.GetLineCount() self.LineDown() while (self.GetCurrentLine() < self.GetLineCount()): if "#<--" in self.GetLine(self.GetCurrentLine()): last = self.GetCurrentLine() - 1 break self.LineDown() self.SetSelection(self.GetLineEndPosition(first)+1, self.GetLineEndPosition(last)+1) if evt is not None: evt.StopPropagation() elif "#<--" in self.GetLine(self.GetCurrentLine()): first = 0 last = self.GetCurrentLine() - 1 self.LineUp() while (self.GetCurrentLine() > 0): if "#-->" in self.GetLine(self.GetCurrentLine()): first = self.GetCurrentLine() break self.LineUp() self.SetSelection(self.GetLineEndPosition(first)+1, self.GetLineEndPosition(last)+1) if evt is not None: evt.StopPropagation() else: if evt is not None: evt.Skip() def OnQuickSearch(self, str, next=True): if self.GetSelection() != (0,0): self.SetSelection(self.GetSelectionEnd()-1, self.GetSelectionEnd()) self.SearchAnchor() if next: res = self.SearchNext(stc.STC_FIND_MATCHCASE, str) else: res = self.SearchPrev(stc.STC_FIND_MATCHCASE, str) if res == -1: if next: self.SetCurrentPos(0) self.SetAnchor(0) self.SearchAnchor() res = self.SearchNext(stc.STC_FIND_MATCHCASE, str) else: pos = self.GetTextLength() self.SetCurrentPos(pos) self.SetAnchor(pos) self.SearchAnchor() res = self.SearchPrev(stc.STC_FIND_MATCHCASE, str) line = self.GetCurrentLine() halfNumLinesOnScreen = self.LinesOnScreen() / 2 self.ScrollToLine(line - halfNumLinesOnScreen) def OnShowFindReplace(self): self.data = wx.FindReplaceData() dlg = wx.FindReplaceDialog(self, self.data, "Find & Replace", wx.FR_REPLACEDIALOG | wx.FR_NOUPDOWN) dlg.Bind(wx.EVT_FIND, self.OnFind) dlg.Bind(wx.EVT_FIND_NEXT, self.OnFind) dlg.Bind(wx.EVT_FIND_REPLACE, self.OnFind) dlg.Bind(wx.EVT_FIND_REPLACE_ALL, self.OnFind) dlg.Bind(wx.EVT_FIND_CLOSE, self.OnFindClose) dlg.Show(True) def OnFind(self, evt): map = { wx.wxEVT_COMMAND_FIND : "FIND", wx.wxEVT_COMMAND_FIND_NEXT : "FIND_NEXT", wx.wxEVT_COMMAND_FIND_REPLACE : "REPLACE", wx.wxEVT_COMMAND_FIND_REPLACE_ALL : "REPLACE_ALL" } evtType = evt.GetEventType() findTxt = evt.GetFindString() newTxt = evt.GetReplaceString() findStrLen = len(findTxt) newStrLen = len(newTxt) diffLen = newStrLen - findStrLen selection = self.GetSelection() if selection[0] == selection[1]: selection = (0, self.GetLength()) if map[evtType] == 'FIND': startpos = self.FindText(selection[0], selection[1], findTxt, evt.GetFlags()) endpos = startpos+len(findTxt) self.anchor1 = endpos self.anchor2 = selection[1] self.SetSelection(startpos, endpos) elif map[evtType] == 'FIND_NEXT': startpos = self.FindText(self.anchor1, self.anchor2, findTxt, evt.GetFlags()) endpos = startpos+len(findTxt) self.anchor1 = endpos self.SetSelection(startpos, endpos) elif map[evtType] == 'REPLACE': startpos = self.FindText(selection[0], selection[1], findTxt, evt.GetFlags()) if startpos != -1: endpos = startpos+len(findTxt) self.SetSelection(startpos, endpos) self.ReplaceSelection(newTxt) self.anchor1 = startpos + newStrLen + 1 self.anchor2 += diffLen elif map[evtType] == 'REPLACE_ALL': self.anchor1 = startpos = selection[0] self.anchor2 = selection[1] while startpos != -1: startpos = self.FindText(self.anchor1, self.anchor2, findTxt, evt.GetFlags()) if startpos != -1: endpos = startpos+len(findTxt) self.SetSelection(startpos, endpos) self.ReplaceSelection(newTxt) self.anchor1 = startpos + newStrLen + 1 self.anchor2 += diffLen line = self.GetCurrentLine() halfNumLinesOnScreen = self.LinesOnScreen() / 2 self.ScrollToLine(line - halfNumLinesOnScreen) def OnFindClose(self, evt): evt.GetDialog().Destroy() def showInvisibles(self, x): self.SetViewWhiteSpace(x) self.SetViewEOL(x) def showEdge(self, x): if x: self.SetEdgeMode(stc.STC_EDGE_LINE) else: self.SetEdgeMode(stc.STC_EDGE_NONE) def removeTrailingWhiteSpace(self): text = self.GetTextUTF8() lines = [line.rstrip() for line in text.splitlines(False)] text= "\n".join(lines) self.setText(text, False) def tabsToSpaces(self): text = self.GetTextUTF8() text = text.replace("\t", " ") self.setText(text, False) ### Save and Close file ### def saveMyFile(self, file): #with codecs.open(file, "w", encoding="utf-8") as f: # f.write(self.GetTextUTF8()) self.SaveFile(file) self.path = file self.saveMark = False marker_file = os.path.split(self.path)[1].split(".")[0] marker_file += "%04d" % random.randint(0,1000) with open(MARKERS_FILE, "r") as f: lines = [line.replace("\n", "").split("=") for line in f.readlines()] founded = False for line in lines: if line[1] == self.path: marker_file = line[0] founded = True break if self.markers_dict != {}: with open(os.path.join(MARKERS_PATH, marker_file), "w") as f: f.write("markers = " + str(self.markers_dict)) if not founded: lines.append([marker_file, self.path]) else: if founded: os.remove(os.path.join(MARKERS_PATH, marker_file)) lines.remove(line) with open(MARKERS_FILE, "w") as f: for line in lines: f.write("%s=%s\n" % (line[0], line[1])) def close(self): if self.GetModify(): if not self.path: f = "Untitled" else: f = self.path dlg = wx.MessageDialog(None, 'file ' + f + ' has been modified. Do you want to save?', 'Warning!', wx.YES | wx.NO | wx.CANCEL) but = dlg.ShowModal() if but == wx.ID_YES: dlg.Destroy() if not self.path or "Untitled-" in self.path: dlg2 = wx.FileDialog(None, message="Save file as ...", defaultDir=os.getcwd(), defaultFile="", style=wx.SAVE|wx.FD_OVERWRITE_PROMPT) dlg2.SetFilterIndex(0) if dlg2.ShowModal() == wx.ID_OK: path = dlg2.GetPath() self.SaveFile(path) dlg2.Destroy() else: dlg2.Destroy() return 'keep' else: self.SaveFile(self.path) return 'delete' elif but == wx.ID_NO: dlg.Destroy() return 'delete' elif but == wx.ID_CANCEL: dlg.Destroy() return 'keep' else: return 'delete' def OnClose(self, event): if self.GetModify(): if not self.path: f = "Untitled" else: f = os.path.split(self.path)[1] dlg = wx.MessageDialog(None, 'file ' + f + ' has been modified. Do you want to save?', 'Warning!', wx.YES | wx.NO) if dlg.ShowModal() == wx.ID_YES: dlg.Destroy() if not self.path or "Untitled-" in self.path: dlg2 = wx.FileDialog(None, message="Save file as ...", defaultDir=os.getcwd(), defaultFile="", style=wx.SAVE|wx.FD_OVERWRITE_PROMPT) dlg2.SetFilterIndex(0) if dlg2.ShowModal() == wx.ID_OK: path = dlg2.GetPath() self.SaveFile(path) dlg2.Destroy() else: self.SaveFile(self.path) else: dlg.Destroy() def OnModified(self): title = self.getTitle() if self.GetModify() and not "***" in title: str = '*** ' + title + ' ***' self.setTitle(str) tab = self.panel.GetSelection() tabtitle = self.panel.GetPageText(tab) self.panel.SetPageText(tab, "*" + tabtitle) self.saveMark = True ### Text Methods ### def addText(self, text, update=True): try: self.AddTextUTF8(text) except: self.AddText(text) if update: count = self.GetLineCount() for i in range(count): self.updateVariableDict(i) def insertText(self, pos, text, update=True): try: self.InsertTextUTF8(pos, text) except: self.InsertText(pos, text) if update: count = self.GetLineCount() for i in range(count): self.updateVariableDict(i) def setText(self, text, update=True): try: self.SetTextUTF8(text) except: self.SetText(text) if update: count = self.GetLineCount() for i in range(count): self.updateVariableDict(i) ### Editor functions ### def listPaste(self, pastingList): if pastingList != []: self.popupmenu = wx.Menu() for item in pastingList: item = self.popupmenu.Append(-1, item) self.Bind(wx.EVT_MENU, self.onPasteFromList, item) self.PopupMenu(self.popupmenu, self.PointFromPosition(self.GetCurrentPos())) self.popupmenu.Destroy() def onPasteFromList(self, evt): item = self.popupmenu.FindItemById(evt.GetId()) text = item.GetText() self.insertText(self.GetCurrentPos(), text) self.SetCurrentPos(self.GetCurrentPos() + len(text)) wx.CallAfter(self.SetAnchor, self.GetCurrentPos()) def getWordUnderCaret(self): caretPos = self.GetCurrentPos() startpos = self.WordStartPosition(caretPos, True) endpos = self.WordEndPosition(caretPos, True) currentword = self.GetTextRangeUTF8(startpos, endpos) return currentword def showAutoCompContainer(self, state): self.auto_comp_container = state def showAutoComp(self): propagate = True charBefore = " " caretPos = self.GetCurrentPos() if caretPos > 0: charBefore = self.GetTextRangeUTF8(caretPos - 1, caretPos) currentword = self.getWordUnderCaret() if charBefore in self.alphaStr: list = '' for word in PYO_WORDLIST: if word.startswith(currentword) and word != currentword and word != "class_args": list = list + word + ' ' if list: self.AutoCompShow(len(currentword), list) propagate = False return propagate def insertDefArgs(self, currentword, charat): propagate = True braceend = True currentword = "" if charat == ord("("): pos = self.GetCurrentPos() if chr(self.GetCharAt(pos)) == ')': braceend = False startpos = self.WordStartPosition(pos-2, True) endpos = self.WordEndPosition(pos-2, True) currentword = self.GetTextRangeUTF8(startpos, endpos) for word in PYO_WORDLIST: if word == currentword: text = class_args(eval(word)).replace(word, "") self.args_buffer = text.replace("(", "").replace(")", "").split(",") self.args_buffer = [arg.strip() for arg in self.args_buffer] self.args_line_number = [self.GetCurrentLine(), self.GetCurrentLine()+1] if braceend: self.insertText(self.GetCurrentPos(), text[1:], False) else: self.insertText(self.GetCurrentPos(), text[1:-1], False) self.selection = self.GetSelectedText() wx.CallAfter(self.navigateArgs) propagate = False break return propagate def navigateArgs(self): if self.selection != "": self.SetCurrentPos(self.GetSelectionEnd()) arg = self.args_buffer.pop(0) if len(self.args_buffer) == 0: self.quit_navigate_args = True if "=" in arg: search = arg.split("=")[1].strip() else: search = arg self.SearchAnchor() self.SearchNext(stc.STC_FIND_MATCHCASE, search) def quitNavigateArgs(self): pos = self.GetLineEndPosition(self.GetCurrentLine()) + 1 self.SetCurrentPos(pos) wx.CallAfter(self.SetAnchor, self.GetCurrentPos()) def formatBuiltinComp(self, text, indent=0): self.snip_buffer = [] a1 = text.find("`", 0) while a1 != -1: a2 = text.find("`", a1+1) if a2 != -1: self.snip_buffer.append(ensureNFD(text[a1+1:a2])) a1 = text.find("`", a2+1) text = text.replace("`", "") lines = text.splitlines(True) text = lines[0] for i in range(1, len(lines)): text += " "*indent + lines[i] return text, len(text) def checkForBuiltinComp(self): text, pos = self.GetCurLine() if text.strip() in BUILTINS_DICT.keys(): indent = self.GetLineIndentation(self.GetCurrentLine()) text, tlen = self.formatBuiltinComp(BUILTINS_DICT[text.strip()], indent) self.args_line_number = [self.GetCurrentLine(), self.GetCurrentLine()+len(text.splitlines())] self.insertText(self.GetCurrentPos(), text) if len(self.snip_buffer) == 0: pos = self.GetCurrentPos() + len(text) + 1 self.SetCurrentPos(pos) wx.CallAfter(self.SetAnchor, self.GetCurrentPos()) else: self.selection = self.GetSelectedText() pos = self.GetSelectionStart() wx.CallAfter(self.navigateSnips, pos) return False else: return True def insertSnippet(self, text): indent = self.GetLineIndentation(self.GetCurrentLine()) text, tlen = self.formatBuiltinComp(text, 0) self.args_line_number = [self.GetCurrentLine(), self.GetCurrentLine()+len(text.splitlines())] self.insertText(self.GetCurrentPos(), text) if len(self.snip_buffer) == 0: pos = self.GetCurrentPos() + len(text) + 1 self.SetCurrentPos(pos) wx.CallAfter(self.SetAnchor, self.GetCurrentPos()) else: self.selection = self.GetSelectedTextUTF8() pos = self.GetSelectionStart() wx.CallAfter(self.navigateSnips, pos) def navigateSnips(self, pos): if self.selection != "": self.SetCurrentPos(self.GetSelectionEnd()) arg = self.snip_buffer.pop(0) if len(self.snip_buffer) == 0: self.quit_navigate_snip = True self.SearchAnchor() self.SearchNext(stc.STC_FIND_MATCHCASE, arg) def quitNavigateSnips(self, pos): pos = self.PositionFromLine(self.args_line_number[1]) self.SetCurrentPos(pos) wx.CallAfter(self.SetAnchor, self.GetCurrentPos()) def checkForAttributes(self, charat, pos): propagate = True currentword = "" while charat == ord("."): startpos = self.WordStartPosition(pos-2, True) endpos = self.WordEndPosition(pos-2, True) currentword = "%s.%s" % (self.GetTextRangeUTF8(startpos, endpos), currentword) pos = startpos - 1 charat = self.GetCharAt(pos) if currentword != "": currentword = currentword[:-1] if currentword in self.objs_attr_dict.keys(): pyokeyword = self.objs_attr_dict[currentword] obj = eval(pyokeyword) list = [word for word in dir(obj) if not word.startswith("_")] for i, word in enumerate(list): if type(getattr(obj, word)) == MethodType: args, varargs, varkw, defaults = inspect.getargspec(getattr(obj, word)) args = inspect.formatargspec(args, varargs, varkw, defaults, formatvalue=removeExtraDecimals) args = args.replace('self, ', '').replace('self', '') list[i] = word + args list = "/".join(list) if list: self.AutoCompSetSeparator(ord("/")) self.AutoCompShow(0, list) self.AutoCompSetSeparator(ord(" ")) propagate = False return propagate def updateVariableDict(self, line): text = self.GetLineUTF8(line).replace(" ", "") egpos = text.find("=") brpos = text.find("(") if egpos != -1 and brpos != -1: if egpos < brpos: name = text[:egpos] obj = text[egpos+1:brpos] if obj in PYO_WORDLIST: self.objs_attr_dict[name] = obj def processReturn(self): prevline = self.GetCurrentLine() - 1 self.updateVariableDict(prevline) if self.GetLineUTF8(prevline).strip().endswith(":"): indent = self.GetLineIndentation(prevline) self.addText(" "*(indent+4), False) elif self.GetLineIndentation(prevline) != 0 and self.GetLineUTF8(prevline).strip() != "": indent = self.GetLineIndentation(prevline) self.addText(" "*indent, False) def processTab(self, currentword, autoCompActive, charat, pos): propagate = self.showAutoComp() if propagate: propagate = self.insertDefArgs(currentword, charat) if propagate: propagate = self.checkForBuiltinComp() if propagate: propagate = self.checkForAttributes(charat, pos) return propagate def onShowTip(self): currentword = self.getWordUnderCaret() try: text = class_args(eval(currentword)).replace(currentword, "") self.CallTipShow(self.GetCurrentPos(), text) except: pass def onShowDocString(self): if self.GetSelectedText() != "": currentword = self.GetSelectedText() else: currentword = self.getWordUnderCaret() firstCaretPos = self.GetCurrentPos() caretPos = self.GetCurrentPos() startpos = self.WordStartPosition(caretPos, True) while chr(self.GetCharAt(startpos-1)) == ".": self.GotoPos(startpos-2) parent = self.getWordUnderCaret() currentword = parent + "." + currentword caretPos = self.GetCurrentPos() startpos = self.WordStartPosition(caretPos, True) self.GotoPos(firstCaretPos) lineCount = self.GetLineCount() text = "" for i in range(lineCount): line = self.GetLine(i) if "import " in line: text = text + line try: exec text in locals() docstr = eval(currentword).__doc__ dlg = wx.lib.dialogs.ScrolledMessageDialog(self, docstr, "__doc__ string for %s" % currentword, size=(700,500)) dlg.CenterOnParent() dlg.ShowModal() except: pass def OnChar(self, evt): propagate = True if chr(evt.GetKeyCode()) in ['[', '{', '(', '"', '`'] and self.auto_comp_container: if chr(evt.GetKeyCode()) == '[': self.AddText('[]') elif chr(evt.GetKeyCode()) == '{': self.AddText('{}') elif chr(evt.GetKeyCode()) == '(': self.AddText('()') elif chr(evt.GetKeyCode()) == '"': self.AddText('""') elif chr(evt.GetKeyCode()) == '`': self.AddText('``') self.CharLeft() propagate = False if propagate: evt.Skip() else: evt.StopPropagation() def OnKeyDown(self, evt): if PLATFORM == "darwin": ControlDown = evt.CmdDown else: ControlDown = evt.ControlDown propagate = True # Stop propagation on markers navigation --- Shift+Ctrl+Arrows up/down if evt.GetKeyCode() in [wx.WXK_DOWN,wx.WXK_UP] and evt.ShiftDown() and ControlDown(): propagate = False # Stop propagation on Tip Show of pyo keyword --- Shift+Return elif evt.GetKeyCode() == wx.WXK_RETURN and evt.ShiftDown(): self.onShowTip() propagate = False # Stop propagation on Tip Show of __doc__ string --- Ctrl+Return elif evt.GetKeyCode() == wx.WXK_RETURN and ControlDown(): self.onShowDocString() propagate = False # Move and/or Select one word left or right --- (Shift+)Alt+Arrows left/right elif evt.GetKeyCode() == wx.WXK_LEFT and evt.AltDown() and evt.ShiftDown(): self.CmdKeyExecute(stc.STC_CMD_WORDLEFTEXTEND) elif evt.GetKeyCode() == wx.WXK_LEFT and evt.AltDown(): self.CmdKeyExecute(stc.STC_CMD_WORDLEFT) elif evt.GetKeyCode() == wx.WXK_RIGHT and evt.AltDown() and evt.ShiftDown(): self.CmdKeyExecute(stc.STC_CMD_WORDRIGHTEXTEND) elif evt.GetKeyCode() == wx.WXK_RIGHT and evt.AltDown(): self.CmdKeyExecute(stc.STC_CMD_WORDRIGHT) # Move and/or Select one line left or right --- (Shift+)Ctrl+Arrows left/right elif evt.GetKeyCode() == wx.WXK_LEFT and ControlDown() and evt.ShiftDown(): self.CmdKeyExecute(stc.STC_CMD_HOMEDISPLAYEXTEND) propagate = False elif evt.GetKeyCode() == wx.WXK_LEFT and ControlDown(): self.CmdKeyExecute(stc.STC_CMD_HOMEDISPLAY) propagate = False elif evt.GetKeyCode() == wx.WXK_RIGHT and ControlDown() and evt.ShiftDown(): self.CmdKeyExecute(stc.STC_CMD_LINEENDEXTEND) propagate = False elif evt.GetKeyCode() == wx.WXK_RIGHT and ControlDown(): self.CmdKeyExecute(stc.STC_CMD_LINEEND) propagate = False # Delete forward DELETE elif evt.GetKeyCode() == wx.WXK_DELETE: self.CmdKeyExecute(stc.STC_CMD_CHARRIGHT) self.CmdKeyExecute(stc.STC_CMD_DELETEBACK) propagate = False # Delete the word to the right of the caret --- Shift+Alt+BACK elif evt.GetKeyCode() == wx.WXK_BACK and evt.AltDown() and evt.ShiftDown(): self.DelWordRight() propagate = False # Delete the word to the left of the caret --- Alt+BACK elif evt.GetKeyCode() == wx.WXK_BACK and evt.AltDown(): self.DelWordLeft() propagate = False # Delete the line to the right of the caret --- Shift+Ctrl+BACK elif evt.GetKeyCode() == wx.WXK_BACK and ControlDown() and evt.ShiftDown(): self.DelLineRight() propagate = False # Delete the line to the left of the caret --- Ctrl+BACK elif evt.GetKeyCode() == wx.WXK_BACK and ControlDown(): self.DelLineLeft() propagate = False # Line Copy / Duplicate / Cut / Paste --- Alt+'C', Alt+'D', Alt+'C', Alt+'V' elif evt.GetKeyCode() in [ord('X'), ord('D'), ord('C'), ord('V')] and evt.AltDown(): if evt.GetKeyCode() == ord('C'): self.LineCopy() elif evt.GetKeyCode() == ord('D'): self.LineDuplicate() elif evt.GetKeyCode() == ord('X'): self.LineCut() elif evt.GetKeyCode() == ord('V'): self.GotoPos(self.PositionFromLine(self.GetCurrentLine())) self.Paste() propagate = False # Show documentation for pyo object under the caret elif evt.GetKeyCode() == ord('D') and ControlDown(): self.GetParent().GetParent().GetParent().GetParent().GetParent().showDoc(None) propagate = False # Goto line elif evt.GetKeyCode() == ord('L') and ControlDown(): self.GetParent().GetParent().GetParent().GetParent().GetParent().gotoLine(None) propagate = False # Process Return key --- automatic indentation elif evt.GetKeyCode() == wx.WXK_RETURN: wx.CallAfter(self.processReturn) # Process Tab key --- AutoCompletion, Insert object's args, snippet for builtin keywords elif evt.GetKeyCode() == wx.WXK_TAB: autoCompActive = self.AutoCompActive() currentword = self.getWordUnderCaret() currentline = self.GetCurrentLine() charat = self.GetCharAt(self.GetCurrentPos()-1) pos = self.GetCurrentPos() if len(self.args_buffer) > 0 and currentline in range(*self.args_line_number): self.selection = self.GetSelectedText() self.navigateArgs() propagate = False elif self.quit_navigate_args and currentline in range(*self.args_line_number): self.quit_navigate_args = False self.selection = self.GetSelectedText() self.quitNavigateArgs() propagate = False elif len(self.snip_buffer) > 0 and currentline in range(*self.args_line_number): self.selection = self.GetSelectedText() pos = self.GetSelectionStart() self.navigateSnips(pos) propagate = False elif self.quit_navigate_snip and currentline in range(*self.args_line_number): self.quit_navigate_snip = False self.selection = self.GetSelectedText() pos = self.GetSelectionStart() self.quitNavigateSnips(pos) propagate = False elif autoCompActive: propagate = True else: propagate = self.processTab(currentword, autoCompActive, charat, pos) if propagate: evt.Skip() else: evt.StopPropagation() def OnUpdateUI(self, evt): # check for matching braces braceAtCaret = -1 braceOpposite = -1 charBefore = None caretPos = self.GetCurrentPos() if caretPos > 0: charBefore = self.GetCharAt(caretPos - 1) styleBefore = self.GetStyleAt(caretPos - 1) # check before if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR: braceAtCaret = caretPos - 1 # check after if braceAtCaret < 0: charAfter = self.GetCharAt(caretPos) styleAfter = self.GetStyleAt(caretPos) if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR: braceAtCaret = caretPos if braceAtCaret >= 0: braceOpposite = self.BraceMatch(braceAtCaret) if braceAtCaret != -1 and braceOpposite == -1: self.BraceBadLight(braceAtCaret) else: self.BraceHighlight(braceAtCaret, braceOpposite) if self.GetCurrentLine() not in range(*self.args_line_number): self.args_line_number = [0,0] self.args_buffer = [] self.quit_navigate_args = False # if self.endOfLine: # for i in range(self.GetLineCount()): # pos = self.GetLineEndPosition(i) # if self.GetCharAt(pos-1) != 172: # self.InsertTextUTF8(pos, "¬") self.moveMarkers() self.checkScrollbar() self.OnModified() evt.Skip() def checkScrollbar(self): lineslength = [self.LineLength(i)+1 for i in range(self.GetLineCount())] maxlength = max(lineslength) width = self.GetCharWidth() + (self.GetZoom() * 0.5) if (self.GetSize()[0]) < (maxlength * width): self.SetUseHorizontalScrollBar(True) else: self.SetUseHorizontalScrollBar(False) self.SetXOffset(0) def OnComment(self): selStartPos, selEndPos = self.GetSelection() self.firstLine = self.LineFromPosition(selStartPos) self.endLine = self.LineFromPosition(selEndPos) for i in range(self.firstLine, self.endLine+1): lineLen = len(self.GetLine(i)) pos = self.PositionFromLine(i) if self.GetTextRangeUTF8(pos,pos+1) != '#' and lineLen > 2: self.insertText(pos, '#', False) elif self.GetTextRangeUTF8(pos,pos+1) == '#': self.GotoPos(pos+1) self.DelWordLeft() def navigateMarkers(self, down=True): if self.markers_dict != {}: llen = len(self.markers_dict) swap = [(x[1], x[0]) for x in self.markers_dict.items()] handles = [x[1] for x in sorted(swap)] if down: self.current_marker += 1 else: self.current_marker -= 1 if self.current_marker < 0: self.current_marker = llen - 1 elif self.current_marker >= llen: self.current_marker = 0 handle = handles[self.current_marker] line = self.markers_dict[handle][0] self.GotoLine(line) halfNumLinesOnScreen = self.LinesOnScreen() / 2 self.ScrollToLine(line - halfNumLinesOnScreen) self.GetParent().GetParent().GetParent().GetParent().markers.setSelected(handle) def setMarkers(self, dic): try: key = dic.keys()[0] except: return if type(dic[key]) != ListType: return self.markers_dict = dic for handle in self.markers_dict.keys(): line = self.markers_dict[handle][0] self.MarkerAdd(line, 0) self.GetParent().GetParent().GetParent().GetParent().markers.setDict(self.markers_dict) def moveMarkers(self): dict = {} for handle in self.markers_dict.keys(): line = self.MarkerLineFromHandle(handle) comment = self.markers_dict[handle][1] dict[handle] = [line, comment] if dict != self.markers_dict: self.markers_dict = dict self.GetParent().GetParent().GetParent().GetParent().markers.setDict(self.markers_dict) def addMarker(self, line): if not self.MarkerGet(line): handle = self.MarkerAdd(line, 0) self.markers_dict[handle] = [line, ""] comment = "" dlg = wx.TextEntryDialog(self, 'Enter a comment for that marker:', 'Marker Comment') if dlg.ShowModal() == wx.ID_OK: comment = dlg.GetValue() dlg.Destroy() else: dlg.Destroy() return self.markers_dict[handle][1] = comment self.GetParent().GetParent().GetParent().GetParent().markers.setDict(self.markers_dict) def deleteMarker(self, line): for handle in self.markers_dict.keys(): if line == self.markers_dict[handle][0]: del self.markers_dict[handle] self.MarkerDeleteHandle(handle) self.GetParent().GetParent().GetParent().GetParent().markers.setDict(self.markers_dict) def deleteAllMarkers(self): self.markers_dict = {} self.MarkerDeleteAll(0) self.GetParent().GetParent().GetParent().GetParent().markers.setDict(self.markers_dict) def OnMarginClick(self, evt): if evt.GetMargin() == 0: lineClicked = self.LineFromPosition(evt.GetPosition()) if evt.GetShift(): self.deleteMarker(lineClicked) else: self.addMarker(lineClicked) elif evt.GetMargin() == 2: if evt.GetShift() and evt.GetControl(): self.ToggleFoldAll() else: lineClicked = self.LineFromPosition(evt.GetPosition()) if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG: self.ToggleFold(lineClicked) def FoldAll(self): lineCount = self.GetLineCount() lineNum = 0 while lineNum < lineCount: level = self.GetFoldLevel(lineNum) if level & stc.STC_FOLDLEVELHEADERFLAG and \ (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE: lastChild = self.GetLastChild(lineNum, -1) self.SetFoldExpanded(lineNum, False) if lastChild > lineNum: self.HideLines(lineNum+1, lastChild) lineNum = lineNum + 1 def ExpandAll(self): lineCount = self.GetLineCount() lineNum = 0 while lineNum < lineCount: level = self.GetFoldLevel(lineNum) if level & stc.STC_FOLDLEVELHEADERFLAG and \ (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE: self.SetFoldExpanded(lineNum, True) lineNum = self.Expand(lineNum, True) lineNum = lineNum - 1 lineNum = lineNum + 1 def ToggleFoldAll(self): lineCount = self.GetLineCount() expanding = True # find out if we are folding or unfolding for lineNum in range(lineCount): if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG: expanding = not self.GetFoldExpanded(lineNum) break lineNum = 0 while lineNum < lineCount: level = self.GetFoldLevel(lineNum) if level & stc.STC_FOLDLEVELHEADERFLAG and \ (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE: if expanding: self.SetFoldExpanded(lineNum, True) lineNum = self.Expand(lineNum, True) lineNum = lineNum - 1 else: lastChild = self.GetLastChild(lineNum, -1) self.SetFoldExpanded(lineNum, False) if lastChild > lineNum: self.HideLines(lineNum+1, lastChild) lineNum = lineNum + 1 def foldExpandCurrentScope(self): line = self.GetCurrentLine() while (line >= 0): level = self.GetFoldLevel(line) if level & stc.STC_FOLDLEVELHEADERFLAG and (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE: self.ToggleFold(line) self.GotoLine(line) break line -= 1 def Expand(self, line, doExpand, force=False, visLevels=0, level=-1): lastChild = self.GetLastChild(line, level) line = line + 1 while line <= lastChild: if force: if visLevels > 0: self.ShowLines(line, line) else: self.HideLines(line, line) else: if doExpand: self.ShowLines(line, line) if level == -1: level = self.GetFoldLevel(line) if level & stc.STC_FOLDLEVELHEADERFLAG: if force: if visLevels > 1: self.SetFoldExpanded(line, True) else: self.SetFoldExpanded(line, False) line = self.Expand(line, doExpand, force, visLevels-1) else: if doExpand and self.GetFoldExpanded(line): line = self.Expand(line, True, force, visLevels-1) else: line = self.Expand(line, False, force, visLevels-1) else: line = line + 1 return line class SimpleEditor(stc.StyledTextCtrl): def __init__(self, parent, ID=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style= wx.NO_BORDER): stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style) self.panel = parent self.alphaStr = string.lowercase + string.uppercase + '0123456789' self.Colourise(0, -1) self.SetCurrentPos(0) self.SetIndent(4) self.SetBackSpaceUnIndents(True) self.SetTabIndents(True) self.SetTabWidth(4) self.SetUseTabs(False) self.SetEOLMode(wx.stc.STC_EOL_LF) self.SetPasteConvertEndings(True) self.SetControlCharSymbol(32) self.SetLayoutCache(True) self.SetViewWhiteSpace(0) self.SetViewEOL(0) self.SetEdgeMode(0) self.SetWrapMode(stc.STC_WRAP_WORD) self.SetUseAntiAliasing(True) self.SetEdgeColour(STYLES["lineedge"]['colour']) self.SetEdgeColumn(78) self.SetReadOnly(True) self.setStyle() def setStyle(self): def buildStyle(forekey, backkey=None, smallsize=False): if smallsize: st = "face:%s,fore:%s,size:%s" % (STYLES['face'], STYLES[forekey]['colour'], STYLES['size2']) else: st = "face:%s,fore:%s,size:%s" % (STYLES['face'], STYLES[forekey]['colour'], STYLES['size']) if backkey: st += ",back:%s" % STYLES[backkey]['colour'] if STYLES[forekey].has_key('bold'): if STYLES[forekey]['bold']: st += ",bold" if STYLES[forekey]['italic']: st += ",italic" if STYLES[forekey]['underline']: st += ",underline" return st self.StyleSetSpec(stc.STC_STYLE_DEFAULT, buildStyle('default', 'background')) self.StyleClearAll() # Reset all to be like the default self.StyleSetSpec(stc.STC_STYLE_DEFAULT, buildStyle('default', 'background')) self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, buildStyle('linenumber', 'marginback', True)) self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, buildStyle('default') + ",size:5") self.SetEdgeColour(STYLES["lineedge"]['colour']) self.SetCaretForeground(STYLES['caret']['colour']) self.SetSelBackground(1, STYLES['selback']['colour']) self.SetFoldMarginColour(True, STYLES['foldmarginback']['colour']) self.SetFoldMarginHiColour(True, STYLES['foldmarginback']['colour']) class OutputLogEditor(SimpleEditor): def __init__(self, parent, ID=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style= wx.NO_BORDER): SimpleEditor.__init__(self, parent=parent, ID=ID, pos=pos, size=size, style=style) def appendToLog(self, text): self.SetReadOnly(False) self.AppendText(text) self.GotoLine(self.GetLineCount()) self.SetReadOnly(True) def setLog(self, text): self.SetReadOnly(False) self.SetText(text) self.SetReadOnly(True) class OutputLogPanel(wx.Panel): def __init__(self, parent, mainPanel, size=(175,400)): wx.Panel.__init__(self, parent, wx.ID_ANY, size=size, style=wx.SUNKEN_BORDER) self.mainPanel = mainPanel self.running = 0 tsize = (30, 30) close_panel_bmp = catalog['close_panel_icon.png'].GetBitmap() self.sizer = wx.BoxSizer(wx.VERTICAL) toolbarbox = wx.BoxSizer(wx.HORIZONTAL) self.toolbar = wx.ToolBar(self, -1) self.toolbar.SetMargins((5, 0)) font, psize = self.toolbar.GetFont(), self.toolbar.GetFont().GetPointSize() if PLATFORM == "darwin": font.SetPointSize(psize-1) self.toolbar.SetToolBitmapSize(tsize) if PLATFORM == "win32": self.toolbar.AddSeparator() title = wx.StaticText(self.toolbar, -1, " Output panel") title.SetFont(font) self.toolbar.AddControl(title) self.toolbar.AddSeparator() if PLATFORM == "win32": self.toolbar.AddSeparator() self.processPopup = wx.Choice(self.toolbar, -1, choices=[]) self.processPopup.SetFont(font) self.toolbar.AddControl(self.processPopup) if PLATFORM == "win32": self.toolbar.AddSeparator() self.processKill = wx.Button(self.toolbar, -1, label="Kill", size=(40,self.processPopup.GetSize()[1])) self.processKill.SetFont(font) self.toolbar.AddControl(self.processKill) self.processKill.Bind(wx.EVT_BUTTON, self.killProcess) if PLATFORM == "win32": self.toolbar.AddSeparator() self.runningLabel = wx.StaticText(self.toolbar, -1, " Running: 0") self.runningLabel.SetFont(font) self.toolbar.AddControl(self.runningLabel) self.toolbar.AddSeparator() self.copyLog = wx.Button(self.toolbar, -1, label="Copy log", size=(70,self.processPopup.GetSize()[1])) self.copyLog.SetFont(font) self.toolbar.AddControl(self.copyLog) self.copyLog.Bind(wx.EVT_BUTTON, self.onCopy) self.toolbar.AddSeparator() zoomLabel = wx.StaticText(self.toolbar, -1, "Zoom:") zoomLabel.SetFont(font) self.toolbar.AddControl(zoomLabel) if PLATFORM == "win32": self.toolbar.AddSeparator() self.zoomer = wx.SpinCtrl(self.toolbar, -1, "0", size=(60, -1)) self.zoomer.SetRange(-10,10) self.toolbar.AddControl(self.zoomer) self.zoomer.Bind(wx.EVT_SPINCTRL, self.onZoom) self.toolbar.Realize() toolbarbox.Add(self.toolbar, 1, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 0) tb2 = wx.ToolBar(self, -1, size=(-1,32)) if PLATFORM == "darwin": tb2.SetToolBitmapSize(tsize) tb2.AddSeparator() tb2.AddLabelTool(17, "Close Panel", close_panel_bmp, shortHelp="Close Panel") tb2.Realize() toolbarbox.Add(tb2, 0, wx.ALIGN_RIGHT, 0) wx.EVT_TOOL(self, 17, self.onCloseOutputPanel) self.sizer.Add(toolbarbox, 0, wx.EXPAND) self.editor = OutputLogEditor(self, size=(-1, -1)) self.sizer.Add(self.editor, 1, wx.EXPAND|wx.ALL, 0) self.SetSizer(self.sizer) def onZoom(self, evt): self.editor.SetZoom(self.zoomer.GetValue()) def onCopy(self, evt): self.editor.SelectAll() self.editor.Copy() self.editor.SetAnchor(0) def addProcess(self, procID, filename): self.processPopup.Append("%d :: %s" % (procID, filename)) self.processPopup.SetStringSelection("%d :: %s" % (procID, filename)) self.running += 1 self.runningLabel.SetLabel(" Running: %d" % self.running) self.editor.setLog("") def removeProcess(self, procID, filename): str = "%d :: %s" % (procID, filename) del self.mainPanel.mainFrame.processes[procID] self.processPopup.Delete(self.processPopup.GetItems().index(str)) self.running -= 1 self.runningLabel.SetLabel(" Running: %d" % self.running) def killProcess(self, evt): str = self.processPopup.GetStringSelection() if str != "": procID = int(str.split("::")[0].strip()) thread = self.mainPanel.mainFrame.processes[procID][0] thread.kill() if procID == 1000: self.mainPanel.mainFrame.resetBackgroundServerMenu() def appendToLog(self, text): self.editor.appendToLog(text) def setLog(self, text): self.editor.setLog(text) def onCloseOutputPanel(self, evt): self.mainPanel.mainFrame.showOutputPanel(False) class PastingListEditorFrame(wx.Frame): def __init__(self, parent, pastingList): wx.Frame.__init__(self, parent, wx.ID_ANY, title="Pasting List Editor ", size=(700,500)) self.parent = parent self.menuBar = wx.MenuBar() menu1 = wx.Menu() menu1.Append(351, "Close\tCtrl+W") self.menuBar.Append(menu1, 'File') self.SetMenuBar(self.menuBar) self.Bind(wx.EVT_MENU, self.close, id=351) self.Bind(wx.EVT_CLOSE, self.close) mainSizer = wx.BoxSizer(wx.VERTICAL) panel = scrolled.ScrolledPanel(self) self.editors = [] if PLATFORM == "darwin": heightSum = 22 else: heightSum = 50 if pastingList != []: for line in pastingList: editor = SimpleEditor(panel, style=wx.SUNKEN_BORDER) editor.SetReadOnly(False) height = editor.TextHeight(0) * len(line.splitlines()) + editor.TextHeight(0) * 2 heightSum += height editor.SetMinSize((-1, height)) editor.SetMaxSize((-1, height)) mainSizer.Add(editor, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 0) self.editors.append(editor) if not line.endswith("\n"): line = line + "\n" try: editor.AddTextUTF8(line) except: editor.AddText(line) Y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y) if heightSum > Y - 100: self.SetSize((-1, Y - 100)) else: self.SetSize((-1, heightSum)) panel.SetSizer(mainSizer) panel.SetAutoLayout(1) panel.SetupScrolling() def close(self, evt): pastingList = [] for editor in self.editors: text = editor.GetTextUTF8() if text.replace("\n", "").strip() != "": pastingList.append(text) self.parent.pastingList = pastingList self.Destroy() TOOL_ADD_FILE_ID = 10 TOOL_ADD_FOLDER_ID = 11 TOOL_REFRESH_TREE_ID = 12 class ProjectTree(wx.Panel): """Project panel""" def __init__(self, parent, mainPanel, size): wx.Panel.__init__(self, parent, -1, size=size, style=wx.WANTS_CHARS|wx.SUNKEN_BORDER|wx.EXPAND) self.SetMinSize((150, -1)) self.mainPanel = mainPanel self.projectDict = {} self.selectedItem = None self.edititem = self.editfolder = self.itempath = self.scope = None tsize = (24, 24) file_add_bmp = catalog['file_add_icon.png'].GetBitmap() folder_add_bmp = catalog['folder_add_icon.png'].GetBitmap() close_panel_bmp = catalog['close_panel_icon.png'].GetBitmap() refresh_tree_bmp = catalog['refresh_tree_icon.png'].GetBitmap() self.sizer = wx.BoxSizer(wx.VERTICAL) toolbarbox = wx.BoxSizer(wx.HORIZONTAL) self.toolbar = wx.ToolBar(self, -1, size=(-1,36)) self.toolbar.SetToolBitmapSize(tsize) self.toolbar.AddLabelTool(TOOL_ADD_FILE_ID, "Add File", file_add_bmp, shortHelp="Add File") self.toolbar.AddLabelTool(TOOL_ADD_FOLDER_ID, "Add Folder", folder_add_bmp, shortHelp="Add Folder") self.toolbar.AddLabelTool(TOOL_REFRESH_TREE_ID, "Refresh Tree", refresh_tree_bmp, shortHelp="Refresh Tree") self.toolbar.EnableTool(TOOL_ADD_FILE_ID, False) self.toolbar.Realize() toolbarbox.Add(self.toolbar, 1, wx.ALIGN_LEFT | wx.EXPAND, 0) tb2 = wx.ToolBar(self, -1, size=(-1,36)) tb2.SetToolBitmapSize(tsize) tb2.AddLabelTool(15, "Close Panel", close_panel_bmp, shortHelp="Close Panel") tb2.Realize() toolbarbox.Add(tb2, 0, wx.ALIGN_RIGHT, 0) wx.EVT_TOOL(self, TOOL_ADD_FILE_ID, self.onAdd) wx.EVT_TOOL(self, TOOL_ADD_FOLDER_ID, self.onAdd) wx.EVT_TOOL(self, TOOL_REFRESH_TREE_ID, self.onRefresh) wx.EVT_TOOL(self, 15, self.onCloseProjectPanel) self.sizer.Add(toolbarbox, 0, wx.EXPAND) stls = wx.TR_DEFAULT_STYLE|wx.TR_HIDE_ROOT|wx.SUNKEN_BORDER|wx.EXPAND self.tree = wx.TreeCtrl(self, -1, (0, 26), size, stls) self.tree.SetBackgroundColour(STYLES['background']['colour']) if PLATFORM == 'darwin': pt = 11 else: pt = 8 fnt = wx.Font(pt, wx.ROMAN, wx.NORMAL, wx.NORMAL, face=STYLES['face']) self.tree.SetFont(fnt) self.sizer.Add(self.tree, 1, wx.EXPAND) self.SetSizer(self.sizer) isz = (12,12) self.il = wx.ImageList(isz[0], isz[1]) bmp = wx.ArtProvider_GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz) self.fldridx = self.il.Add(bmp) bmp = wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, isz) self.fldropenidx = self.il.Add(bmp) bmp = wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, isz) self.fileidx = self.il.Add(bmp) self.tree.SetImageList(self.il) self.tree.SetSpacing(12) self.tree.SetIndent(6) self.root = self.tree.AddRoot("EPyo_Project_tree", self.fldridx, self.fldropenidx, None) self.tree.SetItemTextColour(self.root, STYLES['default']['colour']) self.tree.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnEndEdit) self.tree.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnLeftClick) self.tree.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick) def _tree_analyze(self, item, expanded_list): if self.tree.ItemHasChildren(item): it, cookie = self.tree.GetFirstChild(item) while it.IsOk(): if self.tree.ItemHasChildren(it) and self.tree.IsExpanded(it): parent = self.tree.GetItemText(self.tree.GetItemParent(it)) expanded_list.append((parent, self.tree.GetItemText(it))) self._tree_analyze(it, expanded_list) it, cookie = self.tree.GetNextChild(item, cookie) def _tree_restore(self, item, expanded_list): if self.tree.ItemHasChildren(item): it, cookie = self.tree.GetFirstChild(item) while it.IsOk(): if self.tree.ItemHasChildren(it): parent = self.tree.GetItemText(self.tree.GetItemParent(it)) if (parent, self.tree.GetItemText(it)) in expanded_list: self.tree.Expand(it) self._tree_restore(it, expanded_list) it, cookie = self.tree.GetNextChild(item, cookie) def onRefresh(self, evt): expanded = [] self._tree_analyze(self.root, expanded) self.tree.DeleteAllItems() self.root = self.tree.AddRoot("EPyo_Project_tree", self.fldridx, self.fldropenidx, None) for folder, path in self.projectDict.items(): self.loadFolder(path) self._tree_restore(self.root, expanded) def loadFolder(self, dirPath): folderName = os.path.split(dirPath)[1] self.projectDict[folderName] = dirPath self.mainPanel.mainFrame.showProjectTree(True) item = self.tree.AppendItem(self.root, folderName, self.fldridx, self.fldropenidx, None) self.tree.SetPyData(item, dirPath) self.tree.SetItemTextColour(item, STYLES['default']['colour']) self.buildRecursiveTree(dirPath, item) def buildRecursiveTree(self, dir, item): elems = [f for f in os.listdir(dir) if f[0] != "."] for elem in sorted(elems): child = None path = os.path.join(dir, elem) if os.path.isfile(path): if not path.endswith("~") and \ os.path.splitext(path)[1].strip(".") in ALLOWED_EXT: child = self.tree.AppendItem(item, elem, self.fileidx, self.fileidx) self.tree.SetPyData(child, os.path.join(dir, path)) elif os.path.isdir(path): if elem != "build": child = self.tree.AppendItem(item, elem, self.fldridx, self.fldropenidx) self.tree.SetPyData(child, os.path.join(dir, path)) self.buildRecursiveTree(path, child) if child is not None: self.tree.SetItemTextColour(child, STYLES['default']['colour']) def onAdd(self, evt): id = evt.GetId() treeItemId = self.tree.GetSelection() if self.selectedItem != None: selPath = self.tree.GetPyData(self.selectedItem) if os.path.isdir(selPath): self.scope = selPath elif os.path.isfile(selPath): treeItemId = self.tree.GetItemParent(treeItemId) self.scope = self.tree.GetPyData(treeItemId) elif self.selectedItem == None and id == TOOL_ADD_FOLDER_ID: dlg = wx.DirDialog(self, "Choose directory where to save your folder:", defaultPath=os.path.expanduser("~"), style=wx.DD_DEFAULT_STYLE) if dlg.ShowModal() == wx.ID_OK: self.scope = dlg.GetPath() dlg.Destroy() else: dlg.Destroy() return treeItemId = self.tree.GetRootItem() if id == TOOL_ADD_FILE_ID: item = self.tree.AppendItem(treeItemId, "Untitled", self.fileidx, self.fileidx, None) self.edititem = item else: item = self.tree.AppendItem(treeItemId, "Untitled", self.fldridx, self.fldropenidx, None) self.editfolder = item self.tree.SetPyData(item, os.path.join(self.scope, "Untitled")) self.tree.SetItemTextColour(item, STYLES['default']['colour']) self.tree.EnsureVisible(item) if PLATFORM == "darwin": self.tree.ScrollTo(item) self.tree.EditLabel(item) txtctrl = self.tree.GetEditControl() txtctrl.SetSize((self.GetSize()[0], 22)) txtctrl.SelectAll() else: self.tree.EditLabel(item) def setStyle(self): def set_item_style(root_item, colour): self.tree.SetItemTextColour(root_item, colour) item, cookie = self.tree.GetFirstChild(root_item) while item.IsOk(): self.tree.SetItemTextColour(item, colour) if self.tree.ItemHasChildren(item): set_item_style(item, colour) item, cookie = self.tree.GetNextChild(root_item, cookie) if not self.tree.IsEmpty(): self.tree.SetBackgroundColour(STYLES['background']['colour']) set_item_style(self.tree.GetRootItem(), STYLES['default']['colour']) def OnRightDown(self, event): pt = event.GetPosition(); self.edititem, flags = self.tree.HitTest(pt) if self.edititem: self.itempath = self.tree.GetPyData(self.edititem) self.select(self.edititem) self.tree.EditLabel(self.edititem) else: self.unselect() def OnEndEdit(self, event): if self.edititem and self.itempath: self.select(self.edititem) head, tail = os.path.split(self.itempath) newlabel = event.GetLabel() if newlabel != "": newpath = os.path.join(head, event.GetLabel()) os.rename(self.itempath, newpath) self.tree.SetPyData(self.edititem, newpath) elif self.edititem and self.scope: newitem = event.GetLabel() if not newitem: newitem = "Untitled" wx.CallAfter(self.tree.SetItemText, self.edititem, newitem) newpath = os.path.join(self.scope, newitem) self.tree.SetPyData(self.edititem, newpath) f = open(newpath, "w") f.close() self.mainPanel.addPage(newpath) elif self.editfolder and self.scope: newitem = event.GetLabel() if not newitem: newitem = "Untitled" wx.CallAfter(self.tree.SetItemText, self.editfolder, newitem) newpath = os.path.join(self.scope, newitem) self.tree.SetPyData(self.editfolder, newpath) os.mkdir(newpath) if self.selectedItem == None: self.projectDict[newitem] = self.scope self.edititem = self.editfolder = self.itempath = self.scope = None def OnLeftClick(self, event): pt = event.GetPosition() item, flags = self.tree.HitTest(pt) if item: self.select(item) else: self.unselect() event.Skip() def OnLeftDClick(self, event): pt = event.GetPosition() item, flags = self.tree.HitTest(pt) if item: self.select(item) self.openPage(item) else: self.unselect() event.Skip() def openPage(self, item): hasChild = self.tree.ItemHasChildren(item) if not hasChild: path = self.tree.GetPyData(item) self.mainPanel.addPage(path) def select(self, item): self.tree.SelectItem(item) self.selectedItem = item self.toolbar.EnableTool(TOOL_ADD_FILE_ID, True) def unselect(self): self.tree.UnselectAll() self.selectedItem = None self.toolbar.EnableTool(TOOL_ADD_FILE_ID, False) def onCloseProjectPanel(self, evt): self.mainPanel.mainFrame.showProjectTree(False) class MarkersListScroll(scrolled.ScrolledPanel): def __init__(self, parent, id=-1, pos=(25,25), size=(500,400)): scrolled.ScrolledPanel.__init__(self, parent, wx.ID_ANY, pos=(0,0), size=size, style=wx.SUNKEN_BORDER) self.parent = parent self.SetBackgroundColour(STYLES['background']['colour']) self.arrow_bit = catalog['left_arrow.png'].GetBitmap() self.row_dict = {} self.box = wx.FlexGridSizer(0, 3, 0, 10) self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.selected = None self.selected2 = None if wx.Platform == '__WXMAC__': self.font = wx.Font(11, wx.ROMAN, wx.NORMAL, wx.NORMAL, face=STYLES['face']) else: self.font = wx.Font(8, wx.ROMAN, wx.NORMAL, wx.NORMAL, face=STYLES['face']) self.SetSizer(self.box) self.SetAutoLayout(1) self.SetupScrolling() def setDict(self, dic): self.row_dict = dic self.box.Clear(True) swap = [(x[1], x[0]) for x in self.row_dict.items()] handles = [x[1] for x in sorted(swap)] for i in handles: label = wx.StaticBitmap(self, wx.ID_ANY) label.SetBitmap(self.arrow_bit) self.box.Add(label, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 2, userData=(i,self.row_dict[i][0])) line = wx.StaticText(self, wx.ID_ANY, label=str(self.row_dict[i][0]+1)) line.SetFont(self.font) self.box.Add(line, 0, wx.ALIGN_LEFT|wx.TOP, 3, userData=(i,self.row_dict[i][0])) comment = wx.StaticText(self, wx.ID_ANY, label=self.row_dict[i][1]) comment.SetFont(self.font) self.box.Add(comment, 1, wx.EXPAND|wx.ALIGN_LEFT|wx.TOP, 3, userData=(i,self.row_dict[i][0])) self.box.Layout() label.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) line.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) comment.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.setStyle() def OnLeftDown(self, evt): evtobj = evt.GetEventObject() editor = self.parent.mainPanel.editor if not evt.ShiftDown(): self.selected = None self.selected2 = None for item in self.box.GetChildren(): obj = item.GetWindow() if obj == evtobj: if not evt.ShiftDown() or self.selected == None: self.selected = item.GetUserData()[0] line = item.GetUserData()[1] editor.GotoLine(line) halfNumLinesOnScreen = editor.LinesOnScreen() / 2 editor.ScrollToLine(line - halfNumLinesOnScreen) else: line = self.row_dict[self.selected][0] self.selected2 = item.GetUserData()[0] line2 = item.GetUserData()[1] l1, l2 = min(line, line2), max(line, line2) editor.GotoLine(l1) halfNumLinesOnScreen = editor.LinesOnScreen() / 2 editor.ScrollToLine(l1 - halfNumLinesOnScreen) editor.SetSelection(editor.PositionFromLine(l1), editor.PositionFromLine(l2+1)) break self.setColour() def setColour(self): for item in self.box.GetChildren(): obj = item.GetWindow() data = item.GetUserData()[0] if self.selected == data or self.selected2 == data: obj.SetForegroundColour(STYLES['comment']['colour']) else: obj.SetForegroundColour(STYLES['default']['colour']) self.Refresh() def setStyle(self): self.SetBackgroundColour(STYLES['background']['colour']) self.setColour() def setSelected(self, mark): self.selected = mark self.selected2 = None self.setColour() TOOL_DELETE_ALL_MARKERS_ID = 12 class MarkersPanel(wx.Panel): def __init__(self, parent, mainPanel, size=(175,400)): wx.Panel.__init__(self, parent, wx.ID_ANY, size=size, style=wx.SUNKEN_BORDER) self.mainPanel = mainPanel tsize = (24, 24) delete_all_markers = catalog['delete_all_markers.png'].GetBitmap() close_panel_bmp = catalog['close_panel_icon.png'].GetBitmap() self.sizer = wx.BoxSizer(wx.VERTICAL) toolbarbox = wx.BoxSizer(wx.HORIZONTAL) self.toolbar = wx.ToolBar(self, -1, size=(-1,36)) self.toolbar.SetToolBitmapSize(tsize) self.toolbar.AddLabelTool(TOOL_DELETE_ALL_MARKERS_ID, "Delete All Markers", delete_all_markers, shortHelp="Delete All Markers") self.toolbar.Realize() toolbarbox.Add(self.toolbar, 1, wx.ALIGN_LEFT | wx.EXPAND, 0) tb2 = wx.ToolBar(self, -1, size=(-1,36)) tb2.SetToolBitmapSize(tsize) tb2.AddLabelTool(16, "Close Panel", close_panel_bmp, shortHelp="Close Panel") tb2.Realize() toolbarbox.Add(tb2, 0, wx.ALIGN_RIGHT, 0) wx.EVT_TOOL(self, TOOL_DELETE_ALL_MARKERS_ID, self.onDeleteAll) wx.EVT_TOOL(self, 16, self.onCloseMarkersPanel) self.sizer.Add(toolbarbox, 0, wx.EXPAND) self.scroll = MarkersListScroll(self, size=(-1, -1)) self.sizer.Add(self.scroll, 1, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, 0) self.SetSizer(self.sizer) def setSelected(self, mark): self.scroll.setSelected(mark) def setDict(self, dic): self.row_dict = copy.deepcopy(dic) self.scroll.setDict(dic) def onDeleteAll(self, evt): self.mainPanel.mainFrame.deleteAllMarkers(evt) def onCloseMarkersPanel(self, evt): self.mainPanel.mainFrame.showMarkersPanel(False) class PreferencesDialog(wx.Dialog): def __init__(self): wx.Dialog.__init__(self, None, wx.ID_ANY, 'E-Pyo Preferences') mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.AddSpacer((-1,10)) font, entryfont, pointsize = self.GetFont(), self.GetFont(), self.GetFont().GetPointSize() font.SetWeight(wx.BOLD) if PLATFORM == "linux2": entryfont.SetPointSize(pointsize) elif PLATFORM == "win32": entryfont.SetPointSize(pointsize) else: font.SetPointSize(pointsize-1) entryfont.SetPointSize(pointsize-2) lbl = wx.StaticText(self, label="Python Executable:") lbl.SetFont(font) mainSizer.Add(lbl, 0, wx.LEFT|wx.RIGHT, 10) ctrlSizer = wx.BoxSizer(wx.HORIZONTAL) self.entry_exe = wx.TextCtrl(self, size=(500,-1), value=WHICH_PYTHON) self.entry_exe.SetFont(entryfont) if PLATFORM == "win32": self.entry_exe.SetEditable(False) ctrlSizer.Add(self.entry_exe, 0, wx.ALL|wx.EXPAND, 5) but = wx.Button(self, id=wx.ID_ANY, label="Choose...") but.Bind(wx.EVT_BUTTON, self.setExecutable) ctrlSizer.Add(but, 0, wx.ALL, 5) but2 = wx.Button(self, id=wx.ID_ANY, label="Revert") but2.Bind(wx.EVT_BUTTON, self.revertExecutable) ctrlSizer.Add(but2, 0, wx.ALL, 5) if PLATFORM == "win32": but.Disable() but2.Disable() mainSizer.Add(ctrlSizer, 0, wx.BOTTOM|wx.LEFT|wx.RIGHT, 5) lbl = wx.StaticText(self, label="Resources Folder:") lbl.SetFont(font) mainSizer.Add(lbl, 0, wx.LEFT|wx.RIGHT, 10) ctrlSizer = wx.BoxSizer(wx.HORIZONTAL) self.entry_res = wx.TextCtrl(self, size=(500,-1), value=RESOURCES_PATH) self.entry_res.SetFont(entryfont) ctrlSizer.Add(self.entry_res, 0, wx.ALL|wx.EXPAND, 5) but = wx.Button(self, id=wx.ID_ANY, label="Choose...") but.Bind(wx.EVT_BUTTON, self.setResourcesFolder) ctrlSizer.Add(but, 0, wx.ALL, 5) but2 = wx.Button(self, id=wx.ID_ANY, label="Revert") but2.Bind(wx.EVT_BUTTON, self.revertResourcesFolder) ctrlSizer.Add(but2, 0, wx.ALL, 5) mainSizer.Add(ctrlSizer, 0, wx.BOTTOM|wx.LEFT|wx.RIGHT, 5) mainSizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.BOTTOM|wx.LEFT|wx.RIGHT, 5) lbl = wx.StaticText(self, label="=== Background Pyo Server ===") lbl.SetFont(font) mainSizer.Add(lbl, 0, wx.BOTTOM|wx.LEFT|wx.RIGHT, 10) lbl = wx.StaticText(self, label="Arguments:") lbl.SetFont(font) mainSizer.Add(lbl, 0, wx.LEFT|wx.RIGHT, 10) ctrlSizer = wx.BoxSizer(wx.HORIZONTAL) self.server_args = wx.TextCtrl(self, size=(500,-1), value=BACKGROUND_SERVER_ARGS) self.server_args.SetFont(entryfont) ctrlSizer.Add(self.server_args, 0, wx.ALL|wx.EXPAND, 5) but = wx.Button(self, id=wx.ID_ANY, label=" Restore default args ") but.Bind(wx.EVT_BUTTON, self.setServerDefaultArgs) ctrlSizer.Add(but, 0, wx.ALL, 5) mainSizer.Add(ctrlSizer, 0, wx.BOTTOM|wx.LEFT|wx.RIGHT, 5) popupSizer = wx.FlexGridSizer(2, 4, 5, 10) for label in ["Input Driver", "Output Driver", "Midi Input", "Midi Output"]: lbl = wx.StaticText(self, label=label) lbl.SetFont(font) popupSizer.Add(lbl) cX = 160 preferedDriver = PREFERENCES.get("background_server_in_device", "") driverList, driverIndexes = pa_get_input_devices() driverList = [ensureNFD(driver) for driver in driverList] defaultDriver = pa_get_default_input() self.popupInDriver = wx.Choice(self, choices=driverList, size=(cX,-1)) popupSizer.Add(self.popupInDriver, 1, wx.EXPAND, 5) if preferedDriver and preferedDriver in driverList: driverIndex = driverIndexes[driverList.index(preferedDriver)] self.popupInDriver.SetStringSelection(preferedDriver) elif defaultDriver: self.popupInDriver.SetSelection(driverIndexes.index(defaultDriver)) preferedDriver = PREFERENCES.get("background_server_out_device", "") driverList, driverIndexes = pa_get_output_devices() driverList = [ensureNFD(driver) for driver in driverList] defaultDriver = pa_get_default_output() self.popupOutDriver = wx.Choice(self, choices=driverList, size=(cX,-1)) popupSizer.Add(self.popupOutDriver, 1, wx.EXPAND, 5) if preferedDriver and preferedDriver in driverList: driverIndex = driverIndexes[driverList.index(preferedDriver)] self.popupOutDriver.SetStringSelection(preferedDriver) elif defaultDriver: self.popupOutDriver.SetSelection(driverIndexes.index(defaultDriver)) # TODO: Added "all" interfaces option in input and output preferedDriver = PREFERENCES.get("background_server_midiin_device", "") driverList, driverIndexes = pm_get_input_devices() driverList = [ensureNFD(driver) for driver in driverList] if driverList != []: defaultDriver = pm_get_default_input() self.popupMidiInDriver = wx.Choice(self, choices=driverList, size=(cX,-1)) if preferedDriver and preferedDriver in driverList: driverIndex = driverIndexes[driverList.index(preferedDriver)] self.popupMidiInDriver.SetStringSelection(preferedDriver) elif defaultDriver >= 0: self.popupMidiInDriver.SetSelection(driverIndexes.index(defaultDriver)) else: self.popupMidiInDriver = wx.Choice(self, choices=["No Interface"]) self.popupMidiInDriver.SetSelection(0) popupSizer.Add(self.popupMidiInDriver, 1, wx.EXPAND, 5) preferedDriver = PREFERENCES.get("background_server_midiout_device", "") driverList, driverIndexes = pm_get_output_devices() driverList = [ensureNFD(driver) for driver in driverList] if driverList != []: defaultDriver = pm_get_default_output() self.popupMidiOutDriver = wx.Choice(self, choices=driverList, size=(cX,-1)) if preferedDriver and preferedDriver in driverList: driverIndex = driverIndexes[driverList.index(preferedDriver)] self.popupMidiOutDriver.SetStringSelection(preferedDriver) elif defaultDriver >= 0: self.popupMidiOutDriver.SetSelection(driverIndexes.index(defaultDriver)) else: self.popupMidiOutDriver = wx.Choice(self, choices=["No Interface"]) self.popupMidiOutDriver.SetSelection(0) popupSizer.Add(self.popupMidiOutDriver, 1, wx.EXPAND, 5) mainSizer.Add(popupSizer, 0, wx.EXPAND|wx.BOTTOM|wx.LEFT|wx.RIGHT, 10) mainSizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.BOTTOM|wx.LEFT|wx.RIGHT, 5) lbl = wx.StaticText(self, label="Allowed File Types in Folder Panel (file extension):") lbl.SetFont(font) mainSizer.Add(lbl, 0, wx.LEFT|wx.RIGHT, 10) ctrlSizer = wx.BoxSizer(wx.HORIZONTAL) self.entry_ext = wx.TextCtrl(self, size=(500,-1), value=", ".join(ALLOWED_EXT)) self.entry_ext.SetFont(entryfont) ctrlSizer.Add(self.entry_ext, 1, wx.ALL|wx.EXPAND, 5) mainSizer.Add(ctrlSizer, 0, wx.EXPAND|wx.BOTTOM|wx.LEFT|wx.RIGHT, 5) btnSizer = self.CreateButtonSizer(wx.CANCEL|wx.OK) mainSizer.AddSpacer((-1,5)) mainSizer.Add(wx.StaticLine(self), 1, wx.EXPAND|wx.ALL, 2) mainSizer.Add(btnSizer, 0, wx.ALL | wx.ALIGN_RIGHT, 5) self.SetSizer(mainSizer) self.SetClientSize(self.GetBestSize()) def setExecutable(self, evt): dlg = wx.FileDialog(self, "Choose your python executable", os.path.expanduser("~"), style=wx.FD_OPEN) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.entry_exe.SetValue(path) dlg.Destroy() def setResourcesFolder(self, evt): dlg = wx.DirDialog(self, "Choose your resources folder", os.path.expanduser("~"), style=wx.FD_OPEN) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.entry_res.SetValue(path) dlg.Destroy() def revertExecutable(self, evt): self.entry_exe.SetValue(WHICH_PYTHON) def revertResourcesFolder(self, evt): self.entry_res.SetValue(RESOURCES_PATH) def setServerDefaultArgs(self, evt): self.server_args.SetValue(BACKGROUND_SERVER_DEFAULT_ARGS) def writePrefs(self): global ALLOWED_EXT, WHICH_PYTHON, RESOURCES_PATH, SNIPPETS_PATH, STYLES_PATH, BACKGROUND_SERVER_ARGS which_python = self.entry_exe.GetValue() if os.path.isfile(which_python) and "python" in which_python: WHICH_PYTHON = PREFERENCES["which_python"] = which_python res_folder = self.entry_res.GetValue() if os.path.isdir(res_folder): if res_folder != ensureNFD(RESOURCES_PATH): RESOURCES_PATH = PREFERENCES["resources_path"] = res_folder # snippets old_snippets_path = SNIPPETS_PATH SNIPPETS_PATH = os.path.join(RESOURCES_PATH, 'snippets') if not os.path.isdir(SNIPPETS_PATH): os.mkdir(SNIPPETS_PATH) for rep in SNIPPETS_CATEGORIES: if not os.path.isdir(os.path.join(SNIPPETS_PATH, rep)): os.mkdir(os.path.join(SNIPPETS_PATH, rep)) files = [f for f in os.listdir(os.path.join(old_snippets_path, rep)) if f[0] != "."] for file in files: try: shutil.copy(os.path.join(old_snippets_path, rep, file), os.path.join(SNIPPETS_PATH, rep)) except: pass # styles old_styles_path = STYLES_PATH STYLES_PATH = os.path.join(RESOURCES_PATH, 'styles') if not os.path.isdir(STYLES_PATH): os.mkdir(STYLES_PATH) files = [f for f in os.listdir(old_styles_path) if f[0] != "."] for file in files: try: shutil.copy(os.path.join(old_styles_path, file), STYLES_PATH) except: pass extensions = [ext.strip() for ext in self.entry_ext.GetValue().split(",")] ALLOWED_EXT = PREFERENCES["allowed_ext"] = extensions server_args = self.server_args.GetValue() BACKGROUND_SERVER_ARGS = PREFERENCES["background_server_args"] = server_args PREFERENCES["background_server_out_device"] = self.popupOutDriver.GetStringSelection() PREFERENCES["background_server_in_device"] = self.popupInDriver.GetStringSelection() midiDevice = self.popupMidiInDriver.GetStringSelection() if midiDevice != "No Interface": PREFERENCES["background_server_midiin_device"] = midiDevice midiDevice = self.popupMidiOutDriver.GetStringSelection() if midiDevice != "No Interface": PREFERENCES["background_server_midiout_device"] = midiDevice class STCPrintout(wx.Printout): """Specific printing support of the wx.StyledTextCtrl for the wxPython framework This class can be used for both printing to a printer and for print preview functions. Unless otherwise specified, the print is scaled based on the size of the current font used in the STC so that specifying a larger font produces a larger font in the printed output (and correspondingly fewer lines per page). Alternatively, you can eihdec specify the number of lines per page, or you can specify the print font size in points which produces a constant number of lines per inch regardless of the paper size. Note that line wrapping in the source STC is currently ignored and lines will be truncated at the right margin instead of wrapping. The STC doesn't provide a convenient method for determining where line breaks occur within a wrapped line, so it may be a difficult task to ever implement printing with line wrapping using the wx.StyledTextCtrl.FormatRange method. """ debuglevel = 1 def __init__(self, stc, page_setup_data=None, print_mode=None, title=None, border=False, lines_per_page=None, output_point_size=None): """Constructor. @param stc: wx.StyledTextCtrl to print @kwarg page_setup_data: optional wx.PageSetupDialogData instance that is used to determine the margins of the page. @kwarg print_mode: optional; of the wx.stc.STC_PRINT_* flags indicating how to render color text. Defaults to wx.stc.STC_PRINT_COLOURONWHITEDEFAULTBG @kwarg title: optional text string to use as the title which will be centered above the first line of text on each page @kwarg border: optional flag indicating whether or not to draw a black border around the text on each page @kwarg lines_per_page: optional integer that will force the page to contain the specified number of lines. Either of C{output_point_size} and C{lines_per_page} fully specifies the page, so if both are specified, C{lines_per_page} will be used. @kwarg output_point_size: optional integer that will force the output text to be drawn in the specified point size. (Note that there are 72 points per inch.) If not specified, the point size of the text in the STC will be used unless C{lines_per_page} is specified. Either of C{output_point_size} and C{lines_per_page} fully specifies the page, so if both are specified, C{lines_per_page} will be used. """ wx.Printout.__init__(self) self.stc = stc if print_mode: self.print_mode = print_mode else: self.print_mode = wx.stc.STC_PRINT_COLOURONWHITEDEFAULTBG if title is not None: self.title = title else: self.title = "" if page_setup_data is None: self.top_left_margin = wx.Point(15,15) self.bottom_right_margin = wx.Point(15,15) else: self.top_left_margin = page_setup_data.GetMarginTopLeft() self.bottom_right_margin = page_setup_data.GetMarginBottomRight() try: value = float(output_point_size) if value > 0.0: self.output_point_size = value except (TypeError, ValueError): self.output_point_size = None try: value = int(lines_per_page) if value > 0: self.user_lines_per_page = value except (TypeError, ValueError): self.user_lines_per_page = None self.page_count = 2 self.border_around_text = border self.setHeaderFont() def OnPreparePrinting(self): """Called once before a print job is started to set up any defaults. """ dc = self.GetDC() self._calculateScale(dc) self._calculatePageCount() def _calculateScale(self, dc): """Scale the DC This routine scales the DC based on the font size, determines the number of lines on a page, and saves some useful pixel locations like the top left corner and the width and height of the drawing area in logical coordinates. """ if self.debuglevel > 0: print dc.SetFont(self.stc.GetFont()) # Calculate pixels per inch of the various devices. The dc_ppi will be # equivalent to the page or screen PPI if the target is the printer or # a print preview, respectively. page_ppi_x, page_ppi_y = self.GetPPIPrinter() screen_ppi_x, screen_ppi_y = self.GetPPIScreen() dc_ppi_x, dc_ppi_y = dc.GetPPI() if self.debuglevel > 0: print("printer ppi: %dx%d" % (page_ppi_x, page_ppi_y)) print("screen ppi: %dx%d" % (screen_ppi_x, screen_ppi_y)) print("dc ppi: %dx%d" % (dc_ppi_x, dc_ppi_y)) # Calculate paper size. Note that this is the size in pixels of the # entire paper, which may be larger than the printable range of the # printer. We need to use the entire paper size because we calculate # margins ourselves. Note that GetPageSizePixels returns the # dimensions of the printable area. px, py, pw, ph = self.GetPaperRectPixels() page_width_inch = float(pw) / page_ppi_x page_height_inch = float(ph) / page_ppi_y if self.debuglevel > 0: print("page pixels: %dx%d" % (pw, ph)) print("page size: %fx%f in" % (page_width_inch, page_height_inch)) dw, dh = dc.GetSizeTuple() dc_pixels_per_inch_x = float(dw) / page_width_inch dc_pixels_per_inch_y = float(dh) / page_height_inch if self.debuglevel > 0: print("device pixels: %dx%d" % (dw, dh)) print("device pixels per inch: %fx%f" % (dc_pixels_per_inch_x, dc_pixels_per_inch_y)) # Calculate usable page size page_height_mm = page_height_inch * 25.4 margin_mm = self.top_left_margin[1] + self.bottom_right_margin[1] usable_page_height_mm = page_height_mm - margin_mm # Lines per page is then the number of lines (based on the point size # reported by wx) that will fit into the usable page height self.lines_pp = self._calculateLinesPerPage(dc, usable_page_height_mm) # The final DC scale factor is then the ratio of the total height in # pixels inside the margins to the number of pixels that it takes to # represent the number of lines dc_margin_pixels = float(dc_pixels_per_inch_y) * margin_mm / 25.4 dc_usable_pixels = dh - dc_margin_pixels page_to_dc = self._calculateScaleFactor(dc, dc_usable_pixels, self.lines_pp) dc.SetUserScale(page_to_dc, page_to_dc) if self.debuglevel > 0: print("Usable page height: %f in" % (usable_page_height_mm / 25.4)) print("Usable page pixels: %d" % dc_usable_pixels) print("lines per page: %d" % self.lines_pp) print("page_to_dc: %f" % page_to_dc) self.x1 = dc.DeviceToLogicalXRel(float(self.top_left_margin[0]) / 25.4 * dc_pixels_per_inch_x) self.y1 = dc.DeviceToLogicalXRel(float(self.top_left_margin[1]) / 25.4 * dc_pixels_per_inch_y) self.x2 = dc.DeviceToLogicalXRel(dw) - dc.DeviceToLogicalXRel(float(self.bottom_right_margin[0]) / 25.4 * dc_pixels_per_inch_x) self.y2 = dc.DeviceToLogicalYRel(dh) - dc.DeviceToLogicalXRel(float(self.bottom_right_margin[1]) / 25.4 * dc_pixels_per_inch_y) page_height = self.y2 - self.y1 #self.lines_pp = int(page_height / dc_pixels_per_line) if self.debuglevel > 0: print("page size: %d,%d -> %d,%d, height=%d" % (int(self.x1), int(self.y1), int(self.x2), int(self.y2), page_height)) def _calculateLinesPerPage(self, dc, usable_page_height_mm): """Calculate the number of lines that will fit on the page. @param dc: the Device Context @param usable_page_height_mm: height in mm of the printable part of the page (i.e. with the border height removed) @returns: the number of lines on the page """ if self.user_lines_per_page is not None: return self.user_lines_per_page font = dc.GetFont() if self.output_point_size is not None: points_per_line = self.output_point_size else: points_per_line = font.GetPointSize() # desired lines per mm based on point size. Note: printer points are # defined as 72 points per inch lines_per_inch = 72.0 / float(points_per_line) if self.debuglevel > 0: print("font: point size per line=%d" % points_per_line) print("font: lines per inch=%f" % lines_per_inch) # Lines per page is then the number of lines (based on the point size # reported by wx) that will fit into the usable page height return float(usable_page_height_mm) / 25.4 * lines_per_inch def _calculateScaleFactor(self, dc, dc_usable_pixels, lines_pp): """Calculate the scale factor for the DC to fit the number of lines onto the printable area @param dc: the Device Context @param dc_usable_pixels: the number of pixels that defines usable height of the printable area @param lines_pp: the number of lines to fit into the printable area @returns: the scale facter to be used in wx.DC.SetUserScale """ # actual line height in pixels according to the DC dc_pixels_per_line = dc.GetCharHeight() # actual line height in pixels according to the STC. This can be # different from dc_pixels_per_line even though it is the same font. # Don't know why this is the case; maybe because the STC takes into # account additional spacing? stc_pixels_per_line = self.stc.TextHeight(0) if self.debuglevel > 0: print("font: dc pixels per line=%d" % dc_pixels_per_line) print("font: stc pixels per line=%d" % stc_pixels_per_line) # Platform dependency alert: I don't know why this works, but through # experimentation it seems like the scaling factor depends on # different font heights depending on the platform. if wx.Platform == "__WXMSW__": # On windows, the important font height seems to be the number of # pixels reported by the STC page_to_dc = float(dc_usable_pixels) / (stc_pixels_per_line * lines_pp) else: # Linux and Mac: the DC font height seems to be the correct height page_to_dc = float(dc_usable_pixels) / (dc_pixels_per_line * lines_pp) return page_to_dc def _calculatePageCount(self, attempt_wrap=False): """Calculates offsets into the STC for each page This pre-calculates the page offsets for each page to support print preview being able to seek backwards and forwards. """ page_offsets = [] page_line_start = 0 lines_on_page = 0 num_lines = self.stc.GetLineCount() line = 0 while line < num_lines: if attempt_wrap: wrap_count = self.stc.WrapCount(line) if wrap_count > 1 and self.debuglevel > 0: print("found wrapped line %d: %d" % (line, wrap_count)) else: wrap_count = 1 # If the next line pushes the count over the edge, mark a page and # start the next page if lines_on_page + wrap_count > self.lines_pp: start_pos = self.stc.PositionFromLine(page_line_start) end_pos = self.stc.GetLineEndPosition(page_line_start + lines_on_page - 1) if self.debuglevel > 0: print("Page: line %d - %d" % (page_line_start, page_line_start + lines_on_page)) page_offsets.append((start_pos, end_pos)) page_line_start = line lines_on_page = 0 lines_on_page += wrap_count line += 1 if lines_on_page > 0: start_pos = self.stc.PositionFromLine(page_line_start) end_pos = self.stc.GetLineEndPosition(page_line_start + lines_on_page) page_offsets.append((start_pos, end_pos)) self.page_count = len(page_offsets) self.page_offsets = page_offsets if self.debuglevel > 0: print("page offsets: %s" % self.page_offsets) def _getPositionsOfPage(self, page): """Get the starting and ending positions of a page @param page: page number @returns: tuple containing the start and end positions that can be passed to FormatRange to render a page """ page -= 1 start_pos, end_pos = self.page_offsets[page] return start_pos, end_pos def GetPageInfo(self): """Return the valid page ranges. Note that pages are numbered starting from one. """ return (1, self.page_count, 1, self.page_count) def HasPage(self, page): """Returns True if the specified page is within the page range """ return page <= self.page_count def OnPrintPage(self, page): """Draws the specified page to the DC @param page: page number to render """ dc = self.GetDC() self._calculateScale(dc) self._drawPageContents(dc, page) self._drawPageHeader(dc, page) self._drawPageBorder(dc) return True def _drawPageContents(self, dc, page): """Render the STC window into a DC for printing. Force the right margin of the rendered window to be huge so the STC won't attempt word wrapping. @param dc: the device context representing the page @param page: page number """ start_pos, end_pos = self._getPositionsOfPage(page) render_rect = wx.Rect(self.x1, self.y1, 32000, self.y2) page_rect = wx.Rect(self.x1, self.y1, self.x2, self.y2) self.stc.SetPrintColourMode(self.print_mode) edge_mode = self.stc.GetEdgeMode() margin_width_0 = self.stc.GetMarginWidth(0) margin_width_1 = self.stc.GetMarginWidth(1) margin_width_2 = self.stc.GetMarginWidth(2) self.stc.SetEdgeMode(wx.stc.STC_EDGE_NONE) self.stc.SetMarginWidth(0, 0) self.stc.SetMarginWidth(1, 0) self.stc.SetMarginWidth(2, 0) end_point = self.stc.FormatRange(True, start_pos, end_pos, dc, dc, render_rect, page_rect) self.stc.SetEdgeMode(edge_mode) self.stc.SetMarginWidth(0, margin_width_0) self.stc.SetMarginWidth(1, margin_width_1) self.stc.SetMarginWidth(2, margin_width_2) def _drawPageHeader(self, dc, page): """Draw the page header into the DC for printing @param dc: the device context representing the page @param page: page number """ # Set font for title/page number rendering dc.SetFont(self.getHeaderFont()) dc.SetTextForeground ("black") dum, yoffset = dc.GetTextExtent(".") yoffset /= 2 if self.title: title_w, title_h = dc.GetTextExtent(self.title) dc.DrawText(self.title, self.x1, self.y1 - title_h - yoffset) # Page Number page_lbl = "%d" % page pg_lbl_w, pg_lbl_h = dc.GetTextExtent(page_lbl) dc.DrawText(page_lbl, self.x2 - pg_lbl_w, self.y1 - pg_lbl_h - yoffset) def setHeaderFont(self, point_size=10, family=wx.FONTFAMILY_SWISS, style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_NORMAL): """Set the font to be used as the header font @param point_size: point size of the font @param family: one of the wx.FONTFAMILY_* values, e.g. wx.FONTFAMILY_SWISS, wx.FONTFAMILY_ROMAN, etc. @param style: one of the wx.FONTSTYLE_* values, e.g. wxFONTSTYLE_NORMAL, wxFONTSTYLE_ITALIC, etc. @param weight: one of the wx.FONTWEIGHT_* values, e.g. wx.FONTWEIGHT_NORMAL, wx.FONTWEIGHT_LIGHT, etc. """ self.header_font_point_size = point_size self.header_font_family = family self.header_font_style = style self.header_font_weight = weight def getHeaderFont(self): """Returns the font to be used to draw the page header text @returns: wx.Font instance """ point_size = self.header_font_point_size font = wx.Font(point_size, self.header_font_family, self.header_font_style, self.header_font_weight) return font def _drawPageBorder(self, dc): """Draw the page border into the DC for printing @param dc: the device context representing the page """ if self.border_around_text: dc.SetPen(wx.BLACK_PEN) dc.SetBrush(wx.TRANSPARENT_BRUSH) dc.DrawRectangle(self.x1, self.y1, self.x2 - self.x1 + 1, self.y2 - self.y1 + 1) class MyFileDropTarget(wx.FileDropTarget): def __init__(self, window): wx.FileDropTarget.__init__(self) self.window = window def OnDropFiles(self, x, y, filenames): for file in filenames: if os.path.isdir(file): self.window.GetTopLevelParent().panel.project.loadFolder(file) sys.path.append(file) elif os.path.isfile(file): self.window.GetTopLevelParent().panel.addPage(file) else: pass class EPyoApp(wx.App): def __init__(self, *args, **kwargs): wx.App.__init__(self, *args, **kwargs) def OnInit(self): X = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X) Y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y) if X < 850: X -= 50 else: X = 850 if Y < 750: Y -= 50 else: Y = 750 self.frame = MainFrame(None, -1, title='E-Pyo Editor', pos=(10,25), size=(X, Y)) self.frame.Show() return True def MacOpenFiles(self, filenames): if type(filenames) != ListType: filenames = [filenames] for filename in filenames: if os.path.isdir(filename): self.frame.panel.project.loadFolder(filename) sys.path.append(filename) elif os.path.isfile(filename): self.frame.panel.addPage(filename) def MacReopenApp(self): try: self.frame.Raise() except: pass if __name__ == '__main__': filesToOpen = [] foldersToOpen = [] if len(sys.argv) > 1: for f in sys.argv[1:]: if os.path.isdir(f): if f[-1] == '/': f = f[:-1] foldersToOpen.append(f) elif os.path.isfile(f): filesToOpen.append(f) else: pass app = EPyoApp(redirect=False) app.MainLoop() pyo/utils/Tutorial_02_Flanger.py0000644000175000017500000002350112652732202016133 0ustar tiagotiago""" Tutorial on creating a custom PyoObject. There are few steps we need to take care of in order to create a class with all of the PyoObject behaviors. Things to consider: - The parent class must be PyoObject, that means the PyoObject's __init__ method must be called inside the object's __init__ method to properly initialize PyoObject's basic attributes. - When a PyoObject receives another PyoObject, it looks for a list of objects called "self._base_objs". This list must contain the C implementation of the audio objects generating the output sound of the process. - Adding "mul" and "add" arguments (they act on objects in self._base_objs). - All PyoObjects support "list expansion". - All PyoObjects with sound in input support cross-fading between old and new sources. - We will probably want to override the play(), out() and stop() methods. - There is an attribute for any function that modify a parameter. - We should override the ctrl() method to allow a GUI to control parameters. In this tutorial, we will define a Flanger object with this definition: Flanger(input, depth=0.75, lfofreq=0.2, feedback=0.25, mul=1, add=0) """ from pyo import * # Step 1 - Declaring the class # We will create a new class called RingMod with PyoObject as its parent class. # Another good habit is to put a __doc__ string at the beginning of our classes. # Doing so will allow other users to retrieve the object's documentation with the # standard python help() function. class Flanger(PyoObject): """ Flanging effect. A flanging is an audio effect produced by mixing two identical signals together, with one signal delayed by a small and gradually changing period, usually smaller than 20 milliseconds. This produces a swept comb filter effect: peaks and notches are produced in the resultant frequency spectrum, related to each other in a linear harmonic series. Varying the time delay causes these to sweep up and down the frequency spectrum. :Parent: :py:class:`PyoObject` :Args: input : PyoObject Input signal to process. depth : float or PyoObject, optional Amplitude of the delay line modulation, between 0 and 1. Defaults to 0.75. lfofreq : float or PyoObject, optional Frequency of the delay line modulation, in Hertz. Defaults to 0.2. feedback : float or PyoObject, optional Amount of output signal reinjected into the delay line. Defaults to 0.25. >>> s = Server().boot() >>> s.start() >>> inp = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True) >>> lf = Sine(0.005, mul=0.25, add=0.5) >>> flg = Flanger(input=inp, depth=0.9, lfofreq=0.1, feedback=lf).out() """ # Step 2 - The __init__ method # This is the place where we have to take care of some of pyo's generic behaviours. # The most important thing to remember is that when a PyoObject receives another # PyoObject in input, it looks for an attribute called self._base_objs. This attribute # is a list of the object's base classes and is considered the audio output signal # of the object (the Sine object uses internally an object called Sine_base). The # getBaseObjects() method returns the list of base classes for a given PyoObject. We # will call the getBaseObjects() method on the objects generating the output signal of # our process. .play(), .out(), .stop() and .mix() methods act on this list. # We also need to add two arguments to the definition of the object: "mul" and "add". # The attributes "self._mul" and "self._add" are handled by the parent class and are # automatically applied to the objects stored in the list "self._base_objs". # Finally, we have to consider the "multi-channel expansion" feature, allowing lists given as # arguments to create multiple instances of our object and managing multiple audio streams. # Two functions help us to accomplish this: # convertArgsToLists(*args) : Return arguments converted to lists and the maximum list size. # wrap(list,i) : Return value at position "i" in "list" with wrap around len(list). def __init__(self, input, depth=0.75, lfofreq=0.2, feedback=0.5, mul=1, add=0): # Properly initialize PyoObject's basic attributes PyoObject.__init__(self) # Keep references of all raw arguments self._input = input self._depth = depth self._lfofreq = lfofreq self._feedback = feedback # Using InputFader to manage input sound allows cross-fade when changing sources self._in_fader = InputFader(input) # Convert all arguments to lists for "multi-channel expansion" in_fader, depth, lfofreq, feedback, mul, add, lmax = convertArgsToLists(self._in_fader, depth, lfofreq, feedback, mul, add) # Apply processing self._modamp = Sig(depth, mul=0.005) self._mod = Sine(freq=lfofreq, mul=self._modamp, add=0.005) self._dls = Delay(in_fader, delay=self._mod, feedback=feedback) self._flange = Interp(in_fader, self._dls, mul=mul, add=add) # self._base_objs is the audio output seen by the outside world! self._base_objs = self._flange.getBaseObjects() # Step 3 - setXXX methods and attributes # Now, we will add methods and attributes getter and setter for all controllable # parameters. It should be noted that we use the setInput() method of the # InputFader object to change an input source. This object implements a cross-fade # between the old source and the new one with a cross-fade duration argument. # Here, we need to keep references of raw argument in order to get the # real current state when we call the dump() method. def setInput(self, x, fadetime=0.05): """ Replace the `input` attribute. :Args: x : PyoObject New signal to process. fadetime : float, optional Crossfade time between old and new input. Defaults to 0.05. """ self._input = x self._in_fader.setInput(x, fadetime) def setDepth(self, x): """ Replace the `depth` attribute. :Args: x : float or PyoObject New `depth` attribute. """ self._depth = x self._modamp.value = x def setLfoFreq(self, x): """ Replace the `lfofreq` attribute. :Args: x : float or PyoObject New `lfofreq` attribute. """ self._lfofreq = x self._mod.freq = x def setFeedback(self, x): """ Replace the `feedback` attribute. :Args: x : float or PyoObject New `feedback` attribute. """ self._feedback = x self._dls.feedback = x @property def input(self): """PyoObject. Input signal to process.""" return self._input @input.setter def input(self, x): self.setInput(x) @property def depth(self): """float or PyoObject. Amplitude of the delay line modulation.""" return self._depth @depth.setter def depth(self, x): self.setDepth(x) @property def lfofreq(self): """float or PyoObject. Frequency of the delay line modulation.""" return self._lfofreq @lfofreq.setter def lfofreq(self, x): self.setLfoFreq(x) @property def feedback(self): """float or PyoObject. Amount of output signal sent back into the delay line.""" return self._feedback @feedback.setter def feedback(self, x): self.setFeedback(x) # Step 4 - The ctrl() method # The ctrl() method of a PyoObject is used to pop-up a GUI to control the parameters # of the object. The initialization of sliders is done with a list of SLMap objects # where we can set the range of the slider, the type of scaling, the name of the # attribute linked to the slider and the initial value. We will define a default # "self._map_list" that will be used if the user doesn't provide one to the parameter # "map_list". If the object doesn't have any parameter to control with a GUI, this # method can be undefined. def ctrl(self, map_list=None, title=None, wxnoserver=False): self._map_list = [SLMap(0., 1., "lin", "depth", self._depth), SLMap(0.001, 20., "log", "lfofreq", self._lfofreq), SLMap(0., 1., "lin", "feedback", self._feedback), SLMapMul(self._mul)] PyoObject.ctrl(self, map_list, title, wxnoserver) # Step 5 - Overriding the .play(), .stop() and .out() methods # Finally, we might want to override .play(), .stop() and .out() methods to be sure all # our internal PyoObjects are consequently managed instead of only objects in self._base_obj, # as it is in built-in objects. To handle properly the process for self._base_objs, we still # need to call the method that belongs to PyoObject. We return the returned value (self) of # these methods in order to possibly append the method to the object's creation. See the # definition of these methods in the PyoObject man page to understand the meaning of arguments. def play(self, dur=0, delay=0): self._modamp.play(dur, delay) self._mod.play(dur, delay) self._dls.play(dur, delay) return PyoObject.play(self, dur, delay) def stop(self): self._modamp.stop() self._mod.stop() self._dls.stop() return PyoObject.stop(self) def out(self, chnl=0, inc=1, dur=0, delay=0): self._modamp.play(dur, delay) self._mod.play(dur, delay) self._dls.play(dur, delay) return PyoObject.out(self, chnl, inc, dur, delay) # Run the script to test the Flanger object. if __name__ == "__main__": s = Server().boot() src = BrownNoise([.2,.2]).out() fl = Flanger(src, depth=.9, lfofreq=.1, feedback=.5, mul=.5).out() s.gui(locals())pyo/utils/PyoDoc.py0000644000175000017500000015044612652732202013577 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 from __future__ import with_statement import subprocess, threading, os, sys, unicodedata import wx import wx.stc as stc from wx.lib.embeddedimage import PyEmbeddedImage from pyo import * DOC_AS_SINGLE_APP = False PLATFORM = sys.platform DEFAULT_ENCODING = sys.getdefaultencoding() ENCODING = sys.getfilesystemencoding() TEMP_PATH = os.path.join(os.path.expanduser('~'), '.epyo') if not os.path.isdir(TEMP_PATH): os.mkdir(TEMP_PATH) DOC_PATH = os.path.join(TEMP_PATH, 'doc') DOC_EXAMPLE_PATH = os.path.join(TEMP_PATH, 'manual_example.py') DOC_STYLES = {'Default': {'default': '#000000', 'comment': '#007F7F', 'commentblock': '#7F7F7F', 'selback': '#CCCCCC', 'number': '#005000', 'string': '#7F007F', 'triple': '#7F0000', 'keyword': '#00007F', 'keyword2': '#007F9F', 'class': '#0000FF', 'function': '#007F7F', 'identifier': '#000000', 'caret': '#00007E', 'background': '#EEEEEE', 'linenumber': '#000000', 'marginback': '#B0B0B0', 'markerfg': '#CCCCCC', 'markerbg': '#000000', 'bracelight': '#AABBDD', 'bracebad': '#DD0000', 'lineedge': '#CCCCCC'}} if wx.Platform == '__WXMSW__': DOC_FACES = {'face': 'Verdana', 'size' : 8, 'size2': 7} elif wx.Platform == '__WXMAC__': DOC_FACES = {'face': 'Monaco', 'size' : 12, 'size2': 9} else: DOC_FACES = {'face': 'Monospace', 'size' : 8, 'size2': 7} DOC_FACES['size3'] = DOC_FACES['size2'] + 4 for key, value in DOC_STYLES['Default'].items(): DOC_FACES[key] = value # ***************** Catalog starts here ******************* catalog = {} #---------------------------------------------------------------------- next_24_png = PyEmbeddedImage( "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsTAAALEwEAmpwY" "AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAA" "F2+SX8VGAAAHfUlEQVR42mJkaGRABf+QaGYGK1EeMTcFPkV9QQ5BZS5mLtavf7/+fv/n3b2H" "Zx5cfv3y9S6G3QyHGT4x4AQAAcSIYcEfIGZicLSQtio3F7NwkeKSZf739x/Dv38g/B9oL9Bm" "RqD9HH8ZXvx6/u/MrRP7zq4708VwCGgVFgAQQKgW/GVgFuMWbwhXj6pQ5VFnefftPcOnH58Y" "fv37zQA2+v9/hr///wHZ/0F2MHCz8zAI8PEzPGK4/2/jhrV9b1a8rmN4y/Ad2QKAAGJmcIS7" "nFVBSHFBjl5BDi+jINPTj88Yvv/+BrTzL8RwEMkIJBn/gXl/gfS3P98Y3gIdIcggwmhsYmz1" "SPqh5qfTH7cx/AJCKAAIIGYGe0iwiPKKNuXpF2X/+vGH4fXXN2BDQYb/BQUN43+Grz++Mnz6" "8pnh1/9fDMxszGALQPgf0z+GT7+BkfCLicFYy0TzJtM1vu9nv+8AGgAGAAHEzOAADHImJqd0" "vazZXP95GN98ewsU/g+08y8wSEBW/GP4+vMbgyy7FIOfrifDv19/GW69ucPAwsMGtOAvxBLm" "/wxf/n1lYP7DyqBkqGx2+faFK/8f/78GsgAggJgZ7BhYzKTNl9qIOcg8+/QcGAQQw//+h+A/" "QEN+ff3JUOZewGCmZsJgpWrB8OjFE4Yrb64xsPNzgA0H4f/MjAyf/35lkOKWZvgu/lnr5Z4X" "K4DG/AAIICYmViZrW0kH83df3wNdDPT2P5jh/8CG/wUGwR8g/vH7J9jLLMwsDKVe+QwOUjYM" "T14/Y/jG+AMYqz8ZfgDhL8ZfDE8/P2fQ0zXRYTJkcgOpBwggZll/uVxHCVcrUNCAI48BEol/" "mP4wgCA4jP9/Zjh+5wSDiZwRgyCXAAMzEzODpaIpw4k7pxjW3FzP8OL/a4YnX54yPPv6nOHB" "58cMXJzcDB8/vfn2/cy3TQABxCLPK2/65+8fiMuhhv/884vhx7fvYF88+/ac4dnPlwxvvjxn" "eLn6DcPyqHkMknziDGwsbAwzgicwMKxnYFj0aAUDvxA/MHMwMvz8+4Ph+acXDIJaQvrvWN6I" "AAQQixCHsBQoA0GM/w8mGb//Zyh2yGVQk1Zl+P33NwMTIxMDEzMTUPNPBgEOfngaZwdaMitw" "IgPHFjaGtS83MbDzcjKwAyOalYWFgY2TVxSYYfkBAogJmARF//wDplNGRnAOPf3wDAMHGyeD" "qaoxAz8XH4MIrzCDEI8ggwAnP4M4jxjQUHaUnMrKwsrQ7d7CIMEkysDJxsbAw8HFwAG0mImd" "SRBoHhdAALEw/P//HuhCflAwHXpwjOHGywsMX75+Zbj5/DaDgogcSqb/8/83OPw5WDhQLFl9" "bT0DEw8DAz8nD8Pfv38ZeDm5GD5/+v4NFN4AAcTy+e/nl3/+/1HYe/sAw923t4D5n5vh7u+7" "DBazXBhkhKXBQcMKTDl/gb6UZBdj6PfpZlAVVgbnI6AUw+Lzyxhm3JnJICwuCAwRYBz8+Q1M" "CHwMb38+ew3KQgABxPL4xaPzx7+cNr/78gYDAycnJKg42Rg+sH9g+PD7PTDPsTIwAyNP9JcQ" "Q4NNA4OigDLDt1//GNiYmBgWX17OsODRXAZJOVEGVkZWcFn16+8vBiFefoa3N1/fBEboG4AA" "Ynpw9P72N0yvGNg4+IBZ+j+oiAZioCWsrAwswLjgZOdg4PnNydBp3cPgquLC8P77H4bff5gY" "Fl5YxrD06Xyg4WIMQlz8wPjiYeDj4maQAMYtM9CRL068OAw06TNAADH9ffx335ef72/ICMsA" "XfsXaAkjxBImEJMRWIwwMHAxcTEoC2ox/AAWYf/+sDAsu7SEYdWLhQwSsmLg4BAAGi7AzQu0" "hJtBUVie4dq1K0//nP2zD1TmAAQQM8Nzhl+f+T9+VTZQDfjw5SvDb0ZgjmUHhiYLEzDXMoPT" "O6gE/f7pKwM/mxDD9rsbGba8Xc4gKiMMTFm84FTDC8xY3OzsDGLcIgwff35mWN28dvLfG3/X" "g4pRgABiBldeN/5d/qX3XUtdSVvr1Rdgjmb+y8DEwszAAkwxbMAI5uTmYHj48w7D0Zf7GO4z" "XGMQAkYoH7Au4AYGHy8HNzBouBgkeEQZuDl4GaZOnXXg9Zw3oFrmNchsgABiglY0f1/Pf5X1" "6N3NIwZKugw8bLzA2usPuFQFZ47/jAwcPJwMLEJAy/i4gSHIDE4L4AwINEGESxiYRAUZJi2a" "eflu371qoKYHsCQMEEDM8MT8ieHbl6uftv+W/aahpqmuxs7CxfDt93dw8ICDipkVGFzAXAqk" "WVmZwWxeDh4GGT5phk8/vzD0TJx8+GLD5SKGjwwnwU6GAoAAYsSoRJkZWNmC2fIUPFQLBMUk" "ZP7+gZSwjMAimZ2NlUEYWNiJ8ggxCAOTIjMwI1y6funFgbmHFn9f/302UPc9ZMNBACCAGHE2" "B8QYFFmNWIPELCWdBKWFdHi5+ETZWdmBmYuR4cfP729f3X9x4+Ghh8d+nfy1k+EDwyWgji/Y" "jAEIINwWIAAHAxuDBKjgAsfZf7AbfwBL8jdA1jt0F6MDgAADAHKd0AXoRzn5AAAAAElFTkSu" "QmCC") catalog['next_24.png'] = next_24_png #---------------------------------------------------------------------- play_24_png = PyEmbeddedImage( "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsTAAALEwEAmpwY" "AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAA" "F2+SX8VGAAAEUUlEQVR42mL4//8/AwybxGw55ZB5+LW8VUUpAxMHNwMVAEAAMSFz+Pj5lbn4" "JUS0rGO7TCKWHhVS9fViZGKjyAKAAEKx4N+//wwfP/9iePv5L4OAlJ6+oV/nZjW3zuVcYgbq" "5FoAEEAoFvxnYGRgZARZ9I/hw+dvDN9//WeS0fOPMAiZc1LOtqaOhVOIn1QLAAIIzQImhv9A" "C0C2MDIxMvz+85fh85dvDExsvPwKZkmNOmGrTonpx4UxsfIQbQFAAKFZgDCcEUYDVfz++5vh" "15+fDDwiimpqro0rNfxnbOeTtzMlxgKAAMIIIgYGqOFAzASygBlEMwH5/xn+/vsFlP/NIK5u" "72EQNvuwqvfEfjY+WTF8FgAEEKYF0CBiALueCWIZyBJmZgZmFqByZqAVf74zMLGysSuahRSY" "JK49JW1VkMTCJcqKzQKAAMJiASRomJghljABDWViZgKz/wIj6Ofv/6DIZ/j47RfD6w9fGRi4" "xOQ13Evn6kct3Cuo6mnDwMiCYgFAAKEmUwZouDMjLPnzj4HhK9DAzz/+gelf/4AWgSIGaCkj" "EP/49Yfh05cfDPxy+ramsTP36UQsmMspoikPMxMggHD64PdfBoZP3/8xfPnxH8wG+YKFlZmB" "lQ0JQ/mMLIxgS77++scqZ+iaZJG65rS4QZwvyEyAAMKwAJjXGL4CDf4MxH+BbGZWRrAhLGAM" "soQJzAaLsUPEWYE0Kwczwy+ghnefvjMIysiLiqo7RAONZAMIIJQAAyZ7hq9f/wJd/B9sAChS" "QZgF6HomoCuZofEBTl1MsBQHKQGYgI7h52Nh4GRnZ3h55+LzR8dm7QaZCRBAqBYAFf4BamAB" "GcwMMZAZbDjE5UwwPjMshUHyDjfQMTxcHAxf3rz6cWHH5FWPjs6a8ff764tAqV8AAYRiAchl" "zMyQzAUyBG4JDAPDHGYBAxCzAfn8vJwMf779YLh5aP2hmzu6Jn9/dWUv0Kj3MDMBAgjFAnDK" "YYJZwAS3EGIBM9hnEN8ADeZjZ2BlZmV4cOHUvcubu6a9u755FdCIp+DEiAQAAgjVB4ywIoIB" "mlyZ4MkVHCxAw3mBBvNyczK8ffL0y4VNkxc+Pj537v9fH6+CggNbRgMIILQggmAGRuSyCJJ0" "2TlYGISFeBh+ff3278yGRXtu7uiY/Ov9nUNA1Z/wFRUAAYQaRFCDGYDlDogCAVCYCwlyMbCz" "sjLcOXng6tUtXVM+3d+/ESj1Ej04sAGAAEKLA3DKgxd6PNxswLDmYvjw5N6bazunzntxYcWi" "/3++3gQlOGKLa4AAYkEXAFbNDOzAjCMiwsPw78enX5e2Lth0/8CkKX++vTgNlP5GaoUDEEAo" "FrCwsDII8/MAU8c/hqcX95y7s7dvwtfnZ7YBpd7BqgtSAUAAoVjw/dPLZ7++PPt7/+is6W+u" "b1rM8O/3A1KCAxsACCAG5GYLEyuXOAMTuyZQnIuBSgAgwABgBVyq5zW6mgAAAABJRU5ErkJg" "gg==") catalog['play_24.png'] = play_24_png #---------------------------------------------------------------------- previous_24_png = PyEmbeddedImage( "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsTAAALEwEAmpwY" "AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAA" "F2+SX8VGAAAHWklEQVR42mJkaGRABf8ZGJgZmRn+/v/LzMrC6irPr+AmzS1jKsAhIA2UEvr/" "/9+7d//ePXty9vGZxy8e7f63/d9Oho8MfxhwAIAAYsSwAKiUlY3Vz1barsxczNJagFWY4d/f" "fwx///1j+PfvL8M/oAv+MwIdwcnA8PbPW4Yzd0+eOL7+aPe/Pf/WYbMAIIBQLfjLwCbLJ9cb" "pRGbI8kuzfDm61uGL7++MPz59wfstX///wN9BrQICEGAg4WTQYhPkOEN+0uGdRtWzX6+6FkR" "w3uGL8gWAAQQM4Mj3OXs2uK689N1spOZf7MxPPv8nOHnn59gw4BuBhv8hxHIYwT5AOgjoPj3" "/z8Y3n1/z8D9h4fBxMTM+LXcC623p95uZ/jF8BNmAUAAMTM4gF3OICMgOzEDaPjnr18Z3v94" "DzYWZAzMxb/+/2H4+PkTw7fv3xj+s/xnYGRhBFvyn+k/w+c/QF/+/MdgoGWocZfttvTX01+2" "gLUDAUAAMTPYMzCwsbB5p+tmTWD+w8bwHuii/0BX/v0HMhxoBNC13//+Yvjx6TtDoI4Pg42i" "BcPdF/cYPjICQ4IF6DYmoPXM/xm+/f/GwPiHmUHNSE3/8t0L9/49/HcRZAFAADEz2DGw2srZ" "LzIRspAGBQsoOP6AXf4HHBzf//1g+P7hC0OGbQqDr4kng4qEEgPTf2aGw0+PM7DysjH8Y2IA" "WvAPlPQYPv/9yiDGJcHwV/KX2tNdT1YAjfkOEEBMzGzMLhbi1qavv70FRiI4UMCuhxn+7cNX" "hiy7NAZHHTt4xD3/+pLhB8svhk//vjC8+/Oe4f2fjwwfgPgHMOgff3rGoKGlq8VsyuwPUgsQ" "QCwyfLJuQmzCDM++PYdHJjhYoIZn26IavujsCobSI1UMX3h+MzB9ZgKnLhZmFqCvmBgYGYHp" "F5jSDJj0GIT0RVxeH325ECCAWBR4FU3//PkDToqQiAVF6G9gsHxjyAa5XBth+JZrOxjKtlQx" "/OdgYhD5yc/AzMQMNvTT/88MTLzMDExA9i9gfL35/IaBT4tf9zXLSxGAAGIRYBeQAmcikPGM" "4IzM8P7NO4Ysm1QUw0HAGhjB10rOMLAwsYAcygByMEjDuqubGWrONDMw8jMxsP9lA/qImYGV" "k1eMgYlBACCAgGngvxAozBkZmcBBdOz+cYYfv34xuOk7Y+RKQU4BBiFuIQY+Tj4Gfi4+MM0H" "pOONoxlUeBQYOFhZGXg4OBk42NgZmNmY+BgYGbgAAgiY0BjeMTMz83//851h/93DDPff32J4" "yPSAYfe1/QyuWo4oFrz79h4cJMxA+P8/JKEDA4nhMNBR35i/Mghy8zP8/fuXgZ+Th+Hjh++f" "gQr+AAQQyyeGj8+//f6muP36bobnnx8zMHBxMHxm+sIQviKGYVX0UgYXdQe4Bdtu7mJo2NvC" "wCvEw8DFzsXABgwqVmBw/GD6ycAnzs3AxMQEzP2/gb7jZXj549FroAVfAAKImVGJ0eAr62/z" "yw/PAwsXDmBJBwxYThaGHxxfGbZc3cFgKm7CoCgsD7ZAT1KHgZWJjeHYm+MMHOJsDBz8bAzs" "AqwMvAIgC4FBwwIJf3F+MYYL288f/nzi81KAAGL+BIQC+iJR7z5+BebKPxAL2IDJj5OV4Qfr" "d4Zt13YzmIkZMygIywFLUwYGM1kjhp/f/jDc+nqdQVhAkIGXg5uBB2g4JzDc2VhYgcHDBy51" "j8w8Muv/0/+HAQKI6d/Zf7s/vn99Tl5MFlIoMYEDFphEgPYAg+Ej92eG+G3pDPtuHQEGASSo" "ZHnlGNiZ2cARysfJxSAADBJBbl4Gfm5uoG/lGK6dv3rn75m/u0BqAQKImeE3w9/PDJ9eK9kp" "h3/5DCwGgWUKAwcwTbMwAdM5Ezisf3P8Zjhy7wgwCXIxPP/4imHDwzUMzEIMDAJAQ0E+4OXi" "AqpjZxDnEWd4/fUdw5radd3AsmgbyMUAAQRyK8O/x/9ufBP/JKuuq2309guwemL+xcDICoxA" "YEZiBeZSbmAQMHD/Yzj1+iTDqffHGf4L/mUQ5OUHi/NxcAF9wc0gzSsOLGFZGCa1T9vycdXH" "DlB2ApkNEEBgC0Dp7cftH/v+qv/SUlfX0vj6C1jA/fsGzFBAC4DhCrKEg5WdgYeXm4GbDxjm" "QEM5WdnAYpzsbAyyfNIMzMAInjBx2sFbHXfKgObdgWRBBgaAAGKGp8EfDL++XPy87Rv/J0lV" "IzUDHlZ+hu/ACgdYOjEwMzOBLWFlZmVgA9FAl4IiVIiTn0GGX5rhyceXDF3NEzbfbL9dBgzy" "yxAnQwBAADFiq0eZHZnj5ANUisQUpfX/A+PhL7CsYmFhZuBi4wBnIgFuPgZhYBD9/v2T4cKZ" "CzcOzTyy8P/R/0uBWp8iGw4CAAHEiKs1wMDGIMhszuwjpCvsJqgjos/NxSPGwsbMx/qf+fP3" "799ev7706vqzM8+O/Dvxbzc0SH5hMwYggHBbgAxYGYAxyMAPZHGB6yNgDgWG3Bsg/wshrQAB" "BgD9qrwV+ofghAAAAABJRU5ErkJggg==") catalog['previous_24.png'] = previous_24_png #---------------------------------------------------------------------- up_24_png = PyEmbeddedImage( "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsTAAALEwEAmpwY" "AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAA" "F2+SX8VGAAAEpElEQVR42mJkmMZAGPxnYGBmZo61kLZsPb3uVMuv+b9mMRAJAAKImcGbgIp/" "DAyMTIzREQoxc825bIW41Li97v25/fLf1X9nibEAIIDwWwA0nI2FLTpKMXaeKKM027WPNxlE" "OcSZJEwkPe//JM4SgADCbQHQcHYW9uhY5cR5PP9F2O59fcDAwMrI8PnPZwYhFlEmSWMpzwe/" "7hC0BCCAsFsANTxaOWEex18+tnvfgIazMDD8BUr8+/+P4fOvL0BLRJikjKWBltzFawlAAGFa" "gGQ4+z9etvvfHjIwMjMy/P33l+Ev0PD/DCDMwPAVaIkgqzCTtAnQkp+4LQEIIFQLgIZzsHBE" "x6skz2P9x8N2/+tDBgYmoOH//4DcDnQ92A8M/xlBGGjJb6BPWEWYZIxlPR98A1pyHdMSgABC" "WAAzXDVlHutfbmCwAA1nZgC7GhQsYMgISlIQ5YxAmglo+be/3xlE2MWY5ICW3P8MtOQGqiUA" "AQSxAGp4AtBwtr884GBhZmYCBwUoSP4AffD732+GH/9+MPz4+4Ph57+fYPwLiP8BY+bjz48M" "ghzCTLKGMp4PP95/+e8WwhKAAGJkmMrAwMXMFR0HDBb2v8Aw//6Q4Q/jX4Yvf76CNX76/Ynh" "259vYEsYmICeYmJiYGZkBjuABchmZGQC5RNgSDIyiPOIMTD/+fv3xIwj2b+2/ZoJsgAggJhZ" "wlmy47QT58jzKjO/ZHjN8J/zH8OHXx8Y7r17wHD30wOGr0DDQcHDBDaQmYGFmYWBlQWIgTQT" "MzODGKcIgxSfBIMQLz8DKxsLg5SQNJOQvpDPww/3v/2//f8EQACx/F3zV3wl6/J5f/79+Q90" "xf8///7+4Nfms9KwNDV69ugFAwcrG9BgFiTDmeFsoOMZhHkEGE5vOHLp681vx4DhyfL/Pzie" "mP9//68A9LEoQACx/N/8v+4Tw0eUmOdgZK9ncmA0AgcHEyg4mME0yHCQy1mYITQ4aNiAme/y" "l6PfD3zLwpJK2QACiAVDSBvoAE+gxh+MDCygsAZawgJ0KiszzOUQw0EYFA9gmoWJFUc++wUQ" "QCzohjOkM4ByLSPjPya4y0E0C9jlLHDDWVlYgTQTAxszKzgV4gIAAYSwQAuIUyBFM8MPBnCq" "YIIFERPEJ6xQ17NBI5mVFcIH68EBAAKICUxqAnESwnBg0gaHLyRJQpIjzCJYBIMsYQP7ggWv" "DwACiAVseBwkszH8gor+BSV5UNpmgvuCBZRMwRjoaiakoALy8fkAIIBYGKKgLv+JqL0Y/oCK" "AkYwZoYFFSjCGaG+YEbkBxZG/D4ACCAWkGtBBiJXjxA+KIgghkPiAxpkUAy2hAmSZBnxWAAQ" "QCwMvzHrX3AcoKuE+giEmaAYZhk+ABCAjjpIAgCCYSgahrTF9P5ntTDK1sgNsni/PPcOxJVy" "tw6fjsEWISQkRCsJo1zdWgWmAjfHDdJnWwCxMHzG9MGXn1++P7h66xv7X2ABzfid4SfjT2Co" "MTN8B5rzCSlVgeLhFssthh8/fvxigHgaI7oBAoiRgR1rM4UXGHTyQBY72E//8YYC0DagM/8y" "3Aey0QOcASDAAN0xfmdOgZiqAAAAAElFTkSuQmCC") catalog['up_24.png'] = up_24_png _INTRO_TEXT = """ pyo manual version %s pyo is a Python module written in C to help digital signal processing script creation. pyo is a Python module containing classes for a wide variety of audio signal processing types. With pyo, user will be able to include signal processing chains directly in Python scripts or projects, and to manipulate them in real-time through the interpreter. Tools in pyo module offer primitives, like mathematical operations on audio signal, basic signal processing (filters, delays, synthesis generators, etc.) together with complex algorithms to create granulation and others creative sound manipulations. pyo supports OSC protocol (Open Sound Control), to ease communications between softwares, and MIDI protocol, for generating sound events and controlling process parameters. pyo allows creation of sophisticated signal processing chains with all the benefits of a mature, and wild used, general programming language. Overview: Server : Main processing audio loop callback handler. PyoObjectBase : Base class for all pyo objects. PyoObject : Base class for all pyo objects that manipulate vectors of samples. PyoTableObject : Base class for all pyo table objects. PyoMatrixObject : Base class for all pyo matrix objects. PyoPVObject : Base class for all pyo phase vocoder objects. functions : Miscellaneous functions. """ % PYO_VERSION _DOC_KEYWORDS = ['Attributes', 'Examples', 'Methods', 'Notes', 'Methods details', 'Parentclass', 'Overview', 'Initline', 'Description', 'Parameters'] _HEADERS = ["Server", "PyoObjectBase", "Map", "Stream", "TableStream", "functions"] _KEYWORDS_LIST = ['SLMap'] _KEYWORDS_LIST.extend(_HEADERS) _NUM_PAGES = 1 _NUM_PAGES += len(_HEADERS) for k1 in _HEADERS: if type(OBJECTS_TREE[k1]) == type({}): _NUM_PAGES += len(OBJECTS_TREE[k1].keys()) for k2 in OBJECTS_TREE[k1].keys(): _NUM_PAGES += 1 _KEYWORDS_LIST.append(k2) if type(OBJECTS_TREE[k1][k2]) == type({}): for k3 in OBJECTS_TREE[k1][k2].keys(): _KEYWORDS_LIST.extend(OBJECTS_TREE[k1][k2][k3]) _NUM_PAGES += len(OBJECTS_TREE[k1][k2][k3]) else: _KEYWORDS_LIST.extend(OBJECTS_TREE[k1][k2]) _NUM_PAGES += len(OBJECTS_TREE[k1][k2]) else: _KEYWORDS_LIST.extend(OBJECTS_TREE[k1]) _NUM_PAGES += len(OBJECTS_TREE[k1]) PYOOBJECTBASE_METHODS_FILTER = [x[0] for x in inspect.getmembers(PyoObjectBase, inspect.ismethod)] PYOOBJECT_METHODS_FILTER = [x[0] for x in inspect.getmembers(PyoObject, inspect.ismethod)] PYOMATRIXOBJECT_METHODS_FILTER = [x[0] for x in inspect.getmembers(PyoMatrixObject, inspect.ismethod)] PYOTABLEOBJECT_METHODS_FILTER = [x[0] for x in inspect.getmembers(PyoTableObject, inspect.ismethod)] PYOPVOBJECT_METHODS_FILTER = [x[0] for x in inspect.getmembers(PyoPVObject, inspect.ismethod)] MAP_METHODS_FILTER = [x[0] for x in inspect.getmembers(Map, inspect.ismethod)] SLMAP_METHODS_FILTER = [x[0] for x in inspect.getmembers(SLMap, inspect.ismethod)] def _ed_set_style(editor, searchKey=None): editor.SetLexer(stc.STC_LEX_PYTHON) editor.SetKeyWords(0, " ".join(_KEYWORDS_LIST)) if searchKey == None: editor.SetKeyWords(1, " ".join(_DOC_KEYWORDS)) else: editor.SetKeyWords(1, " ".join(_DOC_KEYWORDS) + " " + searchKey) editor.SetMargins(5,5) editor.SetSTCCursor(2) editor.SetIndent(4) editor.SetTabIndents(True) editor.SetTabWidth(4) editor.SetUseTabs(False) editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, "fore:%(default)s,face:%(face)s,size:%(size)d,back:%(background)s" % DOC_FACES) editor.StyleClearAll() editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, "fore:%(default)s,face:%(face)s,size:%(size)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "fore:%(linenumber)s,back:%(marginback)s,face:%(face)s,size:%(size2)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "fore:%(default)s,face:%(face)s" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_DEFAULT, "fore:%(default)s,face:%(face)s,size:%(size)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_COMMENTLINE, "fore:%(comment)s,face:%(face)s,size:%(size)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_NUMBER, "fore:%(number)s,face:%(face)s,bold,size:%(size)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_STRING, "fore:%(string)s,face:%(face)s,size:%(size)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_CHARACTER, "fore:%(string)s,face:%(face)s,size:%(size)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_WORD, "fore:%(keyword)s,face:%(face)s,bold,size:%(size)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_WORD2, "fore:%(keyword2)s,face:%(face)s,bold,size:%(size3)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_TRIPLE, "fore:%(triple)s,face:%(face)s,size:%(size)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, "fore:%(triple)s,face:%(face)s,size:%(size)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_CLASSNAME, "fore:%(class)s,face:%(face)s,bold,size:%(size)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_DEFNAME, "fore:%(function)s,face:%(face)s,bold,size:%(size)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_OPERATOR, "bold,size:%(size)d,face:%(face)s" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_IDENTIFIER, "fore:%(identifier)s,face:%(face)s,size:%(size)d" % DOC_FACES) editor.StyleSetSpec(stc.STC_P_COMMENTBLOCK, "fore:%(commentblock)s,face:%(face)s,size:%(size)d" % DOC_FACES) def complete_words_from_str(text, keyword): words = [keyword] keyword = keyword.lower() text_ori = text text = text.replace("`", " ").replace("'", " ").replace(".", " ").replace(",", " ").replace('"', " ").replace("=", " ").replace("\n", " ").lower() found = text.find(keyword) while found > -1: start = text.rfind(" ", 0, found) end = text.find(" ", found) words.append(text_ori[start:end]) found = text.find(keyword, found+1) words = " ".join(words) return words class ManualPanel(wx.Treebook): def __init__(self, parent): wx.Treebook.__init__(self, parent, -1, style=wx.BK_DEFAULT | wx.SUNKEN_BORDER) self.parent = parent self.searchKey = None self.Bind(wx.EVT_TREEBOOK_PAGE_CHANGED, self.OnPageChanged) self.parse() def reset_history(self): self.fromToolbar = False self.oldPage = "" self.sequence = [] self.seq_index = 0 def parse(self): self.searchKey = None self.DeleteAllPages() self.reset_history() self.needToParse = False if not os.path.isdir(DOC_PATH): os.mkdir(DOC_PATH) self.needToParse = True if self.needToParse: dlg = wx.ProgressDialog("Pyo Documentation", " Building manual... ", maximum = _NUM_PAGES, parent=self, style = wx.PD_APP_MODAL | wx.PD_AUTO_HIDE | wx.PD_SMOOTH) if wx.Platform == '__WXMSW__': dlg.SetSize((300, 150)) else: dlg.SetSize((300, 100)) keepGoing = True count = 1 win = self.makePanel("Intro") self.AddPage(win, "Intro") for key in _HEADERS: if type(OBJECTS_TREE[key]) == type([]): count += 1 win = self.makePanel(key) self.AddPage(win, key) for obj in OBJECTS_TREE[key]: count += 1 win = self.makePanel(obj) self.AddSubPage(win, obj) if self.needToParse and count <= _NUM_PAGES: (keepGoing, skip) = dlg.Update(count) else: if key == "PyoObjectBase": count += 1 win = self.makePanel("PyoObjectBase") self.AddPage(win, "PyoObjectBase") for key2 in OBJECTS_TREE[key]: if type(OBJECTS_TREE[key][key2]) == type([]): count += 1 win = self.makePanel(key2) self.AddPage(win, key2) for obj in OBJECTS_TREE[key][key2]: count += 1 win = self.makePanel(obj) self.AddSubPage(win, obj) if self.needToParse and count <= _NUM_PAGES: (keepGoing, skip) = dlg.Update(count) else: count += 1 head = "PyoObj - " win = self.makePanel("PyoObject") self.AddPage(win, "PyoObject") for key3 in sorted(OBJECTS_TREE[key][key2]): count += 1 win = self.makePanel("%s" % key3) self.AddPage(win, "PyoObj - %s" % key3) for obj in OBJECTS_TREE[key][key2][key3]: count += 1 win = self.makePanel(obj) self.AddSubPage(win, obj) if self.needToParse and count <= _NUM_PAGES: (keepGoing, skip) = dlg.Update(count) else: count += 2 win = self.makePanel("Map") self.AddPage(win, "Map") win = self.makePanel("SLMap") self.AddPage(win, "SLMap") for obj in OBJECTS_TREE[key]["SLMap"]: count += 1 win = self.makePanel(obj) self.AddSubPage(win, obj) if self.needToParse and count <= _NUM_PAGES: (keepGoing, skip) = dlg.Update(count) if self.needToParse: dlg.Destroy() self.setStyle() self.getPage("Intro") wx.FutureCall(100, self.AdjustSize) def parseOnSearchName(self, keyword): self.searchKey = None self.DeleteAllPages() self.reset_history() keyword = keyword.lower() for key in _HEADERS: if type(OBJECTS_TREE[key]) == type([]): objs = [] for obj in OBJECTS_TREE[key]: if keyword in obj.lower(): objs.append(obj) if objs != []: win = self.makePanel(key) self.AddPage(win, key) node = self.GetPageCount()-1 for obj in objs: win = self.makePanel(obj) self.AddSubPage(win, obj) self.ExpandNode(node, True) else: if key == "PyoObjectBase": if keyword in "pyoobjectbase": win = self.makePanel("PyoObjectBase") self.AddPage(win, "PyoObjectBase") for key2 in OBJECTS_TREE[key].keys(): if type(OBJECTS_TREE[key][key2]) == type([]): objs = [] for obj in OBJECTS_TREE[key][key2]: if keyword in obj.lower(): objs.append(obj) if objs != []: win = self.makePanel(key2) self.AddPage(win, key2) node = self.GetPageCount()-1 for obj in objs: win = self.makePanel(obj) self.AddSubPage(win, obj) self.ExpandNode(node, True) else: head = "PyoObj - " if keyword in "pyoobject": win = self.makePanel("PyoObject") self.AddPage(win, "PyoObject") for key3 in sorted(OBJECTS_TREE[key][key2]): objs = [] for obj in OBJECTS_TREE[key][key2][key3]: if keyword in obj.lower(): objs.append(obj) if objs != []: win = self.makePanel("%s" % key3) self.AddPage(win, "PyoObj - %s" % key3) node = self.GetPageCount()-1 for obj in objs: win = self.makePanel(obj) self.AddSubPage(win, obj) self.ExpandNode(node, True) else: if keyword in "map": win = self.makePanel("Map") self.AddPage(win, "Map") objs = [] for obj in OBJECTS_TREE[key]["SLMap"]: if keyword in obj.lower(): objs.append(obj) if objs != []: win = self.makePanel("SLMap") self.AddPage(win, "SLMap") node = self.GetPageCount()-1 for obj in objs: win = self.makePanel(obj) self.AddSubPage(win, obj) self.ExpandNode(node, True) self.setStyle() self.getPage("Intro") wx.CallAfter(self.AdjustSize) def parseOnSearchPage(self, keyword): self.searchKey = keyword self.DeleteAllPages() self.reset_history() keyword = keyword.lower() for key in _HEADERS: if type(OBJECTS_TREE[key]) == type([]): objs = [] for obj in OBJECTS_TREE[key]: with open(os.path.join(DOC_PATH, obj), "r") as f: text = f.read().lower() if keyword in text: objs.append(obj) if objs != []: win = self.makePanel(key) self.AddPage(win, key) node = self.GetPageCount()-1 for obj in objs: win = self.makePanel(obj) self.AddSubPage(win, obj) self.ExpandNode(node, True) else: if key == "PyoObjectBase": for key2 in OBJECTS_TREE[key].keys(): if type(OBJECTS_TREE[key][key2]) == type([]): objs = [] for obj in OBJECTS_TREE[key][key2]: with open(os.path.join(DOC_PATH, obj), "r") as f: text = f.read().lower() if keyword in text: objs.append(obj) if objs != []: win = self.makePanel(key2) self.AddPage(win, key2) node = self.GetPageCount()-1 for obj in objs: win = self.makePanel(obj) self.AddSubPage(win, obj) self.ExpandNode(node, True) else: head = "PyoObj - " with open(os.path.join(DOC_PATH, "PyoObject"), "r") as f: text = f.read().lower() if keyword in text: win = self.makePanel("PyoObject") self.AddPage(win, "PyoObject") for key3 in sorted(OBJECTS_TREE[key][key2]): objs = [] for obj in OBJECTS_TREE[key][key2][key3]: with open(os.path.join(DOC_PATH, obj), "r") as f: text = f.read().lower() if keyword in text: objs.append(obj) if objs != []: win = self.makePanel("%s" % key3) self.AddPage(win, "PyoObj - %s" % key3) node = self.GetPageCount()-1 for obj in objs: win = self.makePanel(obj) self.AddSubPage(win, obj) self.ExpandNode(node, True) else: with open(os.path.join(DOC_PATH, "Map"), "r") as f: text = f.read().lower() if keyword in text: win = self.makePanel("Map") self.AddPage(win, "Map") objs = [] for obj in OBJECTS_TREE[key]["SLMap"]: with open(os.path.join(DOC_PATH, obj), "r") as f: text = f.read().lower() if keyword in text: objs.append(obj) if objs != []: win = self.makePanel("SLMap") self.AddPage(win, "SLMap") node = self.GetPageCount()-1 for obj in objs: win = self.makePanel(obj) self.AddSubPage(win, obj) self.ExpandNode(node, True) self.setStyle() self.getPage("Intro") wx.CallAfter(self.AdjustSize) def AdjustSize(self): self.GetTreeCtrl().InvalidateBestSize() self.SendSizeEvent() def copy(self): self.GetPage(self.GetSelection()).win.Copy() def collapseAll(self): count = self.GetPageCount() for i in range(count): if self.IsNodeExpanded(i): self.CollapseNode(i) def OnPageChanged(self, event): old = event.GetOldSelection() new = event.GetSelection() if new != old: text = self.GetPageText(new) self.getPage(text) event.Skip() def makePanel(self, obj=None): panel = wx.Panel(self, -1) panel.isLoad = False if self.needToParse: if obj != "Intro": try: args = '\nInitline:\n\n' + class_args(eval(obj)) + '\n\nDescription:\n\n' isAnObject = True except: args = '\nDescription:\n\n' if obj in OBJECTS_TREE["functions"]: isAnObject = True else: isAnObject = False if isAnObject: try: parentclass = "" text = eval(obj).__doc__ text = inspect.cleandoc(text) text = text.replace(".. note::", "Notes:").replace(".. seealso::", "See also:").replace(":Args:", "Parameters:") lines = text.splitlines() num = len(lines) text_form = "" inside_examples = False text_ex, linenum = self.getExample(text) if text_ex == "": for i in range(num): line = lines[i] if ":Parent:" in line: line = line.replace(":Parent:", "Parent:").replace(":py:class:", "").replace("`", "") parentclass = line.replace("Parent:", "").strip() text_form += line.rstrip() + '\n' else: for i in range(linenum): line = lines[i] if ":Parent:" in line: line = line.replace(":Parent:", "Parent:").replace(":py:class:", "").replace("`", "") parentclass = line.replace("Parent:", "").strip() text_form += line.rstrip() + '\n' text_form += "Examples:\n\n" text_form += "from pyo import *\n" text_form += text_ex if obj not in OBJECTS_TREE["functions"]: text_form += "s.gui(locals())\n" methods = self.getMethodsDoc(text, obj, parentclass) panel.win = stc.StyledTextCtrl(panel, -1, size=(600, 600), style=wx.SUNKEN_BORDER) panel.win.SetText(args + text_form + methods) except: panel.win = stc.StyledTextCtrl(panel, -1, size=(600, 600), style=wx.SUNKEN_BORDER) panel.win.SetText(args + "\nNot documented yet...\n\n") else: try: text = eval(obj).__doc__ text = text.replace(".. note::", "Notes:").replace(".. seealso::", "See also:").replace(":Args:", "Parameters:") except: if obj == "functions": text = "Miscellaneous functions...\n\n" text += "\nOverview:\n" for o in OBJECTS_TREE["functions"]: text += o + ": " + self.getDocFirstLine(o) else: text = "\nNot documented yet...\n\n" if obj in OBJECTS_TREE["PyoObjectBase"]["PyoObject"].keys(): text += "\nOverview:\n" for o in OBJECTS_TREE["PyoObjectBase"]["PyoObject"][obj]: text += o + ": " + self.getDocFirstLine(o) obj = "PyoObj - " + obj panel.win = stc.StyledTextCtrl(panel, -1, size=(600, 600), style=wx.SUNKEN_BORDER) panel.win.SetText(text) else: panel.win = stc.StyledTextCtrl(panel, -1, size=(600, 600), style=wx.SUNKEN_BORDER) panel.win.SetText(_INTRO_TEXT) panel.win.SaveFile(os.path.join(DOC_PATH, obj)) return panel def getExample(self, text): text = inspect.cleandoc(text) lines = text.splitlines() num = len(lines) first_i = -1 last_i = -1 found = False wait = 0 for i in range(num-1, -1, -1): if not found: if lines[i].strip() == "": continue else: if lines[i].startswith(">>>") or lines[i].startswith("..."): found = True last_i = i+1+wait else: wait += 1 if wait == 2: break else: if lines[i].strip() == "": first_i = i+1 break ex_text = "" for i in range(first_i, last_i): if lines[i].startswith(">>>") or lines[i].startswith("..."): ex_text += lines[i][4:] + "\n" else: ex_text += lines[i] + "\n" return ex_text, first_i def getDocFirstLine(self, obj): try: text = eval(obj).__doc__ if text == None: text = '' except: text = '' if text != '': spl = text.split('\n') if len(spl) == 1: f = spl[0] else: f = spl[1] else: f = text return f.strip() + "\n" def getMethodsDoc(self, text, obj, parentclass): if parentclass == "PyoObjectBase": filter = PYOOBJECTBASE_METHODS_FILTER elif parentclass == "PyoObject": filter = PYOOBJECT_METHODS_FILTER elif parentclass == "PyoTableObject": filter = PYOTABLEOBJECT_METHODS_FILTER elif parentclass == "PyoMatrixObject": filter = PYOMATRIXOBJECT_METHODS_FILTER elif parentclass == "PyoPVObject": filter = PYOPVOBJECT_METHODS_FILTER elif parentclass == "Map": filter = MAP_METHODS_FILTER elif parentclass == "SLMap": filter = SLMAP_METHODS_FILTER else: filter = [] obj_meths = [x[0] for x in inspect.getmembers(eval(obj), inspect.ismethod) if x[0] not in filter] methods = '' for meth in obj_meths: docstr = getattr(eval(obj), meth).__doc__ if docstr != None: docstr = docstr.replace(":Args:", "Parameters:") args, varargs, varkw, defaults = inspect.getargspec(getattr(eval(obj), meth)) args = inspect.formatargspec(args, varargs, varkw, defaults, formatvalue=removeExtraDecimals) args = args.replace('self, ', '') methods += obj + '.' + meth + args + ':\n' methods += docstr + '\n ' methods_form = '' if methods != '': methods_form += "\nMethods details:\n\n" for i, line in enumerate(methods.splitlines()): if i != 0: methods_form += line[4:] + '\n' else: methods_form += line + '\n' return methods_form def MouseDown(self, evt): stc = self.GetPage(self.GetSelection()).win pos = stc.PositionFromPoint(evt.GetPosition()) start = stc.WordStartPosition(pos, False) end = stc.WordEndPosition(pos, False) word = stc.GetTextRange(start, end) self.getPage(word) evt.Skip() def history_check(self): back = True forward = True if self.seq_index <= 0: back = False if self.seq_index == (len(self.sequence) - 1): forward = False self.parent.history_check(back, forward) def history_back(self): self.seq_index -= 1 if self.seq_index < 0: self.seq_index = 0 self.fromToolbar = True self.SetSelection(self.sequence[self.seq_index]) self.history_check() def history_forward(self): seq_len = len(self.sequence) self.seq_index += 1 if self.seq_index == seq_len: self.seq_index = seq_len - 1 self.fromToolbar = True self.SetSelection(self.sequence[self.seq_index]) self.history_check() def getPage(self, word): if word == self.oldPage: self.fromToolbar = False return page_count = self.GetPageCount() for i in range(page_count): text = self.GetPageText(i) if text == word: self.oldPage = word if not self.fromToolbar: self.sequence = self.sequence[0:self.seq_index+1] self.sequence.append(i) self.seq_index = len(self.sequence) - 1 self.history_check() self.parent.setTitle(text) self.SetSelection(i) panel = self.GetPage(self.GetSelection()) if not panel.isLoad: panel.isLoad = True panel.win = stc.StyledTextCtrl(panel, -1, size=panel.GetSize(), style=wx.SUNKEN_BORDER) panel.win.LoadFile(os.path.join(ensureNFD(DOC_PATH), word)) panel.win.SetMarginWidth(1, 0) panel.win.Bind(wx.EVT_LEFT_DOWN, self.MouseDown) if self.searchKey != None: words = complete_words_from_str(panel.win.GetText(), self.searchKey) _ed_set_style(panel.win, words) else: _ed_set_style(panel.win) panel.win.SetSelectionEnd(0) def OnPanelSize(evt, win=panel.win): win.SetPosition((0,0)) win.SetSize(evt.GetSize()) panel.Bind(wx.EVT_SIZE, OnPanelSize) self.fromToolbar = False return def getMethodsDoc2(self, text, obj): if obj == "Clean_objects": return "Methods details:\n\nClean_objects.start():\n\n Starts the thread. The timer begins on this call." lines = text.splitlines(True) flag = False methods = '' for line in lines: if flag: if line.strip() == '': continue else: l = line.lstrip() ppos = l.find('(') if ppos != -1: meth = l[0:ppos] args, varargs, varkw, defaults = inspect.getargspec(getattr(eval(obj), meth)) args = inspect.formatargspec(args, varargs, varkw, defaults, formatvalue=removeExtraDecimals) args = args.replace('self, ', '') methods += obj + '.' + meth + args + ':\n' docstr = getattr(eval(obj), meth).__doc__.rstrip() methods += docstr + '\n\n ' if 'Methods:' in line: flag = True methods += ' Methods details:\n\n ' for key in _DOC_KEYWORDS: if key != 'Methods': if key in line: flag = False methods_form = '' if methods != '': for line in methods.splitlines(): methods_form += line[4:] + '\n' return methods_form def getExampleScript(self): stc = self.GetPage(self.GetSelection()).win start = stc.LineFromPosition(stc.FindText(0, stc.GetLength(), "Examples:")) + 1 end = stc.LineFromPosition(stc.FindText(0, stc.GetLength(), "Methods details:")) - 1 if end <= 0: end = stc.GetLineCount() - 1 text = stc.GetTextRange(stc.PositionFromLine(start), stc.PositionFromLine(end)) return text def setStyle(self): tree = self.GetTreeCtrl() tree.SetBackgroundColour(DOC_STYLES['Default']['background']) root = tree.GetRootItem() tree.SetItemTextColour(root, DOC_STYLES['Default']['identifier']) (child, cookie) = tree.GetFirstChild(root) while child.IsOk(): tree.SetItemTextColour(child, DOC_STYLES['Default']['identifier']) if tree.ItemHasChildren(child): (child2, cookie2) = tree.GetFirstChild(child) while child2.IsOk(): tree.SetItemTextColour(child2, DOC_STYLES['Default']['identifier']) (child2, cookie2) = tree.GetNextChild(child, cookie2) (child, cookie) = tree.GetNextChild(root, cookie) class ManualFrame(wx.Frame): def __init__(self, parent=None, id=-1, title='Pyo Documentation', size=(940, 700), osx_app_bundled=False, which_python="python", caller_need_to_invoke_32_bit=False, set_32_bit_arch="export VERSIONER_PYTHON_PREFER_32_BIT=yes;"): wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size) self.SetMinSize((600, -1)) self.osx_app_bundled = osx_app_bundled self.which_python = which_python self.caller_need_to_invoke_32_bit = caller_need_to_invoke_32_bit self.set_32_bit_arch = set_32_bit_arch gosearchID = 1000 aTable = wx.AcceleratorTable([(wx.ACCEL_NORMAL, 47, gosearchID)]) self.SetAcceleratorTable(aTable) self.Bind(wx.EVT_MENU, self.setSearchFocus, id=gosearchID) tb_size = 24 self.toolbar = self.CreateToolBar() self.toolbar.SetToolBitmapSize((tb_size, tb_size)) # sets icon size back_ico = catalog["previous_%d.png" % tb_size] forward_ico = catalog["next_%d.png" % tb_size] home_ico = catalog["up_%d.png" % tb_size] exec_ico = catalog["play_%d.png" % tb_size] backTool = self.toolbar.AddSimpleTool(wx.ID_BACKWARD, back_ico.GetBitmap(), "Back") self.toolbar.EnableTool(wx.ID_BACKWARD, False) self.Bind(wx.EVT_MENU, self.onBack, backTool) self.toolbar.AddSeparator() forwardTool = self.toolbar.AddSimpleTool(wx.ID_FORWARD, forward_ico.GetBitmap(), "Forward") self.toolbar.EnableTool(wx.ID_FORWARD, False) self.Bind(wx.EVT_MENU, self.onForward, forwardTool) self.toolbar.AddSeparator() homeTool = self.toolbar.AddSimpleTool(wx.ID_HOME, home_ico.GetBitmap(), "Go Home") self.toolbar.EnableTool(wx.ID_HOME, True) self.Bind(wx.EVT_MENU, self.onHome, homeTool) self.toolbar.AddSeparator() execTool = self.toolbar.AddSimpleTool(wx.ID_PREVIEW, exec_ico.GetBitmap(), "Run Example") self.toolbar.EnableTool(wx.ID_PREVIEW, True) self.Bind(wx.EVT_MENU, self.onRun, execTool) self.toolbar.AddSeparator() self.searchTimer = None self.searchScope = "Object's Name" self.searchMenu = wx.Menu() item = self.searchMenu.Append(-1, "Search Scope") item.Enable(False) for i, txt in enumerate(["Object's Name", "Manual Pages"]): id = i+10 self.searchMenu.Append(id, txt) self.Bind(wx.EVT_MENU, self.onSearchScope, id=id) tw, th = self.GetTextExtent("Q") self.search = wx.SearchCtrl(self.toolbar, 200, size=(200,th+6), style=wx.WANTS_CHARS | wx.TE_PROCESS_ENTER) self.search.ShowCancelButton(True) self.search.SetMenu(self.searchMenu) self.toolbar.AddControl(self.search) self.Bind(wx.EVT_TEXT, self.onSearch, id=200) self.Bind(wx.EVT_TEXT_ENTER, self.onSearchEnter, id=200) self.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, self.onSearchCancel, id=200) self.toolbar.Realize() self.status = wx.StatusBar(self, -1) self.SetStatusBar(self.status) self.doc_panel = ManualPanel(self) self.doc_panel.getPage("Intro") self.menuBar = wx.MenuBar() menu1 = wx.Menu() menu1.Append(100, "Run Example\tCtrl+R") menu1.AppendSeparator() if DOC_AS_SINGLE_APP: menu1.Append(wx.ID_EXIT, "Quit\tCtrl+Q") else: menu1.Append(99, "Close\tCtrl+W") self.menuBar.Append(menu1, 'Action') menu2 = wx.Menu() menu2.Append(101, "Copy\tCtrl+C") self.menuBar.Append(menu2, 'Text') self.SetMenuBar(self.menuBar) self.Bind(wx.EVT_MENU, self.onRun, id=100) self.Bind(wx.EVT_MENU, self.copy, id=101) if DOC_AS_SINGLE_APP: self.Bind(wx.EVT_MENU, self.quit, id=wx.ID_EXIT) self.Bind(wx.EVT_CLOSE, self.quit) else: self.Bind(wx.EVT_MENU, self.close, id=99) self.Bind(wx.EVT_CLOSE, self.close) def setSearchFocus(self, evt): self.search.SetFocus() def onSearchEnter(self, evt): self.doc_panel.GetTreeCtrl().SetFocus() def onSearch(self, evt): if self.searchTimer != None: self.searchTimer.Stop() self.searchTimer = wx.CallLater(200, self.doSearch) def doSearch(self): keyword = self.search.GetValue() if keyword == "": self.doc_panel.parse() else: if self.searchScope == "Object's Name": self.doc_panel.parseOnSearchName(keyword) else: self.doc_panel.parseOnSearchPage(keyword) self.searchTimer = None def onSearchCancel(self, evt): self.search.SetValue("") def onSearchScope(self, evt): id = evt.GetId() if id == 10: self.searchScope = "Object's Name" else: self.searchScope = "Manual Pages" def copy(self, evt): self.doc_panel.copy() def quit(self, evt): self.Destroy() def close(self, evt): self.Hide() def setTitle(self, page): self.SetTitle('Pyo Documentation - %s' % page) def history_check(self, back, forward): self.toolbar.EnableTool(wx.ID_BACKWARD, back) self.toolbar.EnableTool(wx.ID_FORWARD, forward) def onBack(self, evt): self.doc_panel.history_back() def onForward(self, evt): self.doc_panel.history_forward() def onHome(self, evt): search = self.search.GetValue() if search != "": self.search.SetValue("") self.doc_panel.getPage("Intro") self.doc_panel.collapseAll() def onRun(self, evt): obj = self.doc_panel.GetPageText(self.doc_panel.GetSelection()) self.status.SetStatusText('Running "%s" example...' % obj, 0) text = self.doc_panel.getExampleScript() with open(DOC_EXAMPLE_PATH, "w") as f: f.write(text) th = RunningThread(DOC_EXAMPLE_PATH, TEMP_PATH, self.which_python, self.osx_app_bundled, self.caller_need_to_invoke_32_bit, self.set_32_bit_arch) th.start() wx.FutureCall(8000, self.status.SetStatusText, "", 0) class RunningThread(threading.Thread): def __init__(self, path, cwd, which_python, osx_app_bundled, caller_need_to_invoke_32_bit, set_32_bit_arch): threading.Thread.__init__(self) self.path = path self.cwd = cwd self.which_python = which_python self.osx_app_bundled = osx_app_bundled self.caller_need_to_invoke_32_bit = caller_need_to_invoke_32_bit self.set_32_bit_arch = set_32_bit_arch self.terminated = False def kill(self): self.terminated = True self.proc.terminate() def run(self): if self.osx_app_bundled: vars_to_remove = "PYTHONHOME PYTHONPATH EXECUTABLEPATH RESOURCEPATH ARGVZERO PYTHONOPTIMIZE" prelude = "export -n %s;export PATH=/usr/local/bin:/usr/local/lib:$PATH;env;" % vars_to_remove if self.caller_need_to_invoke_32_bit: self.proc = subprocess.Popen(["%s%s%s %s" % (prelude, self.set_32_bit_arch, self.which_python, self.path)], shell=True, cwd=self.cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) else: self.proc = subprocess.Popen(["%s%s %s" % (prelude, self.which_python, self.path)], cwd=self.cwd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) elif wx.Platform == '__WXMAC__': if self.caller_need_to_invoke_32_bit: self.proc = subprocess.Popen(["%s%s %s" % (self.set_32_bit_arch, self.which_python, self.path)], shell=True, cwd=self.cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) else: self.proc = subprocess.Popen(["%s %s" % (self.which_python, self.path)], cwd=self.cwd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) elif wx.Platform == "__WXMSW__": self.proc = subprocess.Popen([self.which_python, self.path], cwd=self.cwd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) else: self.proc = subprocess.Popen([self.which_python, self.path], cwd=self.cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) while self.proc.poll() == None and not self.terminated: time.sleep(.25) def ensureNFD(unistr): if PLATFORM in ['linux2', 'win32']: encodings = [DEFAULT_ENCODING, ENCODING, 'cp1252', 'iso-8859-1', 'utf-16'] format = 'NFC' else: encodings = [DEFAULT_ENCODING, ENCODING, 'macroman', 'iso-8859-1', 'utf-16'] format = 'NFC' decstr = unistr if type(decstr) != UnicodeType: for encoding in encodings: try: decstr = decstr.decode(encoding) break except UnicodeDecodeError: continue except: decstr = "UnableToDecodeString" print "Unicode encoding not in a recognized format..." break if decstr == "UnableToDecodeString": return unistr else: return unicodedata.normalize(format, decstr) def toSysEncoding(unistr): try: if PLATFORM == "win32": unistr = unistr.encode(ENCODING) else: unistr = unicode(unistr) except: pass return unistr if __name__ == "__main__": DOC_AS_SINGLE_APP = True app = wx.PySimpleApp() doc_frame = ManualFrame() doc_frame.Show() app.MainLoop() pyo/utils/snippets/0000755000175000017500000000000012652732202013663 5ustar tiagotiagopyo/utils/snippets/Utilities/0000755000175000017500000000000012652732202015636 5ustar tiagotiagopyo/utils/snippets/Utilities/Incrementor0000644000175000017500000000027412652732202020051 0ustar tiagotiagosnippet = {'shortcut': u'Shift-Alt-8', 'value': u'count = 0\ndef incrementor():\n global count\n count += 1\n print count\n\npat = Pattern(function=incrementor, time=1).play()\n'}pyo/utils/snippets/Utilities/ChooseAudioDev0000644000175000017500000000037512652732202020427 0ustar tiagotiagosnippet = {'shortcut': u'Shift-Alt-7', 'value': u'pa_list_devices()\ndevIn = input("Enter your input device number : ")\ndevOut = input("Enter your output device number : ")\ns = Server()\ns.setInputDevice(devIn)\ns.setOutputDevice(devOut)\ns.boot()\n'}pyo/utils/snippets/Audio/0000755000175000017500000000000012652732202014724 5ustar tiagotiagopyo/utils/snippets/Audio/SoundPlayer0000644000175000017500000000027712652732202017122 0ustar tiagotiagosnippet = {'shortcut': u'Shift-Alt-1', 'value': u'sffade = Fader(fadein=`0.05`, fadeout=`1`, dur=`0`, mul=`0.5`).play()\nsfplay = SfPlayer(`path`, speed=`1`, loop=`True`, mul=sffade).out()'}pyo/utils/snippets/Audio/TableOsc0000644000175000017500000000035412652732202016345 0ustar tiagotiagosnippet = {'shortcut': u'Shift-Alt-2', 'value': u'oscfade = Fader(fadein=`0.05`, fadeout=`1`, dur=`0`, mul=`0.2`).play()\ntable = HarmTable([`1,0,0,.3,0,0,.2,0,0,.1,0,0,.05`])\noscil = Osc(table, freq=`[150,151]`, mul=oscfade).out()\n'}pyo/utils/snippets/Control/0000755000175000017500000000000012652732202015303 5ustar tiagotiagopyo/utils/snippets/Control/ChorusJit0000644000175000017500000000035712652732202017145 0ustar tiagotiagosnippet = {'shortcut': u'Shift-Alt-3', 'value': u'num_voices = `10`\nfjit = Randi(min=`0.99`, max=`1.01`, freq=[(x+5)*0.07 for x in range(num_voices)])\najit = Randi(min=`0.25`, max=`0.75`, freq=[(x+5)*0.17 for x in range(num_voices)])\n'}pyo/utils/snippets/Control/Vibrato0000644000175000017500000000037712652732202016643 0ustar tiagotiagosnippet = {'shortcut': u'Shift-Alt-4', 'value': u'vfade = Fader(fadein=`1.5`, fadeout=`0.5`, dur=`0`).play()\nfrnd = Randi(min=`4`, max=`6`, freq=`0.25`)\narnd = Randi(min=`0.01`, max=`0.02`, freq=`0.35`)\navib = Sine(freq=frnd, mul=vfade*arnd, add=1)\n'}pyo/utils/snippets/Interface/0000755000175000017500000000000012652732202015563 5ustar tiagotiagopyo/utils/snippets/Interface/PaintPanel0000644000175000017500000000161112652732202017540 0ustar tiagotiagosnippet = {'shortcut': u'Shift-Alt-6', 'value': u'class MyPanel(wx.Panel):\n def __init__(self, parent, id=-1, pos=(25,25), size=(500,400)):\n wx.Panel.__init__(self, parent, id, pos, size)\n self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) \n self.Bind(wx.EVT_PAINT, self.OnPaint)\n\n def OnPaint(self, evt):\n w,h = self.GetSize()\n dc = wx.AutoBufferedPaintDC(self)\n dc.SetBrush(wx.Brush("#FFFFFF"))\n dc.SetPen(wx.Pen("#FFFFFF", width=1))\n dc.Clear()\n dc.DrawRectangle(0,0,w,h)\n for i in range(500):\n x = (i * 5) % w\n y = (i * 3) % h\n col = wx.Colour((i*19)%256, (i*25)%256, (i*39)%256)\n dc.SetBrush(wx.Brush(col))\n col = wx.Colour((i*13)%256, (i*15)%256, (i*19)%256)\n dc.SetPen(wx.Pen(col, width=1))\n dc.DrawCircle(x, y, radius=(i+2)%9)\n'}pyo/utils/snippets/Interface/NewFrame0000644000175000017500000000071212652732202017212 0ustar tiagotiagosnippet = {'shortcut': u'Shift-Alt-5', 'value': u'class MyFrame(wx.Frame):\n def __init__(self, parent, id=-1, title="Frame Title", pos=(25,25), size=(500,400)):\n wx.Frame.__init__(self, parent, id, title, pos, size)\n self.panel = wx.Panel(self)\n self.panel.SetBackgroundColour("#DDDDDD")\n self.box = wx.BoxSizer(wx.VERTICAL)\n # Create objects here...\n self.panel.SetSizer(self.box)\n self.Show()\n'}pyo/utils/E-PyoIcon.png0000644000175000017500000006430612652732202014277 0ustar tiagotiagoPNG  IHDR\rfbKGD pHYs  tIME. IDATxwx\յ}QNzrBM7|Ml\$[-WtCӛ!4!c0EHOǜF)glY:yXiw>m½j>R@9Н2bW" (x*agB@>.B+^Te) C% O& @q# 栃?Ӽm{X4M 7`20m@~l`|dsss){|ӏ۶%JiXYDO&': p@g"r՗#RH$B|Bi{ɲ{-9ÿzc ]짨'}>~( sX18lB P*Ap8u}0Jl{'Aȳmm۹N5QUIy<1`|@9sd]{)Y{8_UT@?M(~Geò,rSJEB@Y<3vBA$ᜃrfoG Cyg7^3dBuj'39$B>x=c>?/_Ae}W 8M&,iZs;,RZrΝ_vySLpc#,Ȗe[xU4}m/n^JV,ᚦIbP,'c|'ZIoѧLٓ{} ?+P, ar˲!.|qs۶#!DTdY1 c0?ϙ?O?Wr"Xx0-@4fS:?q <2e0L Tp}R9c̦ dm33hOן_ ^'ӧOA 3R{B .)ɖe1IL8`77n:s0eY2oQq^( m !Ȃ PXs!xl{}{/ikkUr]AV 'k9 --a>_t:qi0c R*FyP?`YpFdYDQaX4c-;͛7$ErJ ByB @]wlyԩiӷ ill:Z4Md=lJ)g_\ TVRJH6;R޷3]TY`0xB @Ks /yKޓ7 0Ơ97|^ DEIQdbVzpp~W}ǿ}=!:sgWMM&ƦUUi5 i.<={?bcVBXt0aN?pxZ[[Ĭ85Fe92+Ja,mnn$MיeY Bh};M 8,[ *"xeXb'#gTsϛg,7hpKREtD2!zЏ-W`۶9',$D"F*[;uiwz,!cPJeYDyӦ؟hp 9DQZ? 1Ӷm.˒(2MēR96 C%BL4( LȓsN,˂$Is.E"hi --hit P|JdI%ƞ4m%z>A~WEƘ%ihg>\,K$ɘ6iӦ'766ytZg3|11Y$Q 4ˌn|w+LԴL$ !ܱ|K/lG؀+>5Mm۶EQP)HI]vao{ ]eY!ĚHĶmd~2 NjKSgI 4EQ\EISE]߉E}O=/qB:ޣ>嗟x)|+Gz(/777LҶm3K$3?q0  4JdJrN!xB n6̸ ?\HRB 0$iJ镍I5sAN8p-˲2"K=찛R#S ,ѸL ɞW蓞yY/}SZZ.c7a B 6'F81$Iǔ71&Id|-g466J-Bw|oiZ2$߷}>_80Bjcg|"I/cܥ=_ $ʖef'q$7-|zs.SJi<+ ҟ 1cٶT*0A${Í#q* cL*REѝsO v{L"$r˲dQ Qj[UUU92JkNu:{{uZ@)%eS۶-׼+jBvnd-$<DQ4[MMM pd:,vި8-`qgO$}:E {6|wN פ;'_L&9FnB`j[ı̎)Fs;~/yuw׷^H$ Oʉި5Hr9%I5 `% M)5 PAiOv7c¦e>OHR,˪c<gS;J5NIGlSu9}*!D4c( c;+%a /ٱr!tw( ~f P PjǽTbi"@)a)Ow444t~-|+_v،!|J1&xx<)N1n\eH9?VRii %mmm'IM=I ~񏝚=D`̤1*7 4~q"nBdi766>(Jm'6 cEd1槔ߌIoG D~>X"$c?'MX\WE8RrBޣ?Xc! c~9I|0EEƘq!mEQTry{#-HӍ(r~oAAiƦ\ YK] +lRM7(=1fPJetpJ)1 m9W!( tȲv'!MQ÷ahN'7pv}۶ԳTxgN-!i zI2NIDp9n1DI4KT_?BظdW/eʲwƸ7l=.Bt [q]ȶBJ k&"SB-Jc>Jizg;L2M$V˴(?oLA9\D:6Z[[V.' ٶME5nyvy?4 omiYJ ~ox# e[DQa}۶m)|g8Ja@dUU^0 s ^ o`B!e}> xlhF BDR˶zy7b9DQieOQ8YijlI2DQ}©nHk?zh:2 [QŸ ^R@_Ŝ'f*@GAx\@_9g]FTe1?j4Sv:)tL"$ɳ;L"/썝 PJalhE(?c^EF @ !!4y /ض3)[[ I~w{@lM㉐= eH$kA؃sB< |Xy-T@֥x]1@^HਖMLAom, xpο&8RJT*UCN_<>>#weYRO]Au]ojjq V"sIÛ=s~?^͠ T0 sC)}[wSu64 ^o_)j~_ݾu%6bOmko[JuQ/Zy׃qΩ l\'?9APi[3U_N Pӵ/BtYn>(iZ^@=^ʺpuJi=xW9 \L)s /?3ʺٕb Aq in ;.栊 /k|pKKq^\-D^Pxc$~ܤ 20)>/] joP P5McpE"ȫk@查m'n%Z@7CԧkZG-.Z @*8UgkgjFC o h741q ZK{uo޿V@ U#f5P<Ƙ&IR8+jz';JY#:vϽi |MTVWz~CRBfo~C>9/`.كqΕV֦ 1MS ~yV Κ p< A.ī7jY6d7Lðsv]kYO016S}4~ns>ۉz`B/᫲Xs.5oN_Nj{\nWBm5dCK'"8qb@z"@IuCkkgS nqOɪS&b^ upq66j۶(j{qn˙ {zsu_>𻽭 E Or:V>ns1A-&6 q8S*!DM|+n< +]#_.˄_ % N RTc t-|i٥mq7> ܙbG/ M?ϯ(L `.y.7S|^9h4ei`め@md_6B%*<8mOic{ {諉 r|!(=9VJ9ј! (bhjjw%L*Z[҂P6:ni=t]]v&]Pdyvò`6Aqe/lntg›{eM Fm/kiB+6r· $+nD CEj %B`Y|>"#rb>E10onݎ[߉0i $h<q $0ͺ3Ј"` o"˓lqB0@=tr}7A+x2Buq%]ߏwpم c1p 4]eYضm;!91T?1B| 0 dꟈ !a!ߐdcP($nR*H nZ͆ / JMǕ;+?RV\X]^Gp?  ۶!24~<0M_0{I򗾈|-r+ LG?%kρRR)W_\p1DIuH4,-_ D_$ >ɽq /}X,َ^dkg@ 4 IDAT`wYHAء( vc7e[]k>-ۆc =T T!0- d$!Hb3ۏߏd*է.BO|h @e}*R4$IE睅O5%#.N VYBVVZ 4þ>Qǻ)J rAOr/'GBǭv7gWwFF~>UA$ŹkNG" ̆UϦLKWƋ/֖0"gq A( 9l`&~$>)d $~u9JXq g{kE/ǯ /5S g.Pxyv16ЗR:dO,b_` ~I'U Iݐm#gjvF0_H.Qn`ju(}E$A!A(;P`u7;[hmSDc6V,`, sQ4ø[pa=?Ət .]{tMJMB@XA(V~zg`CHzbbPowټP`qXryb2nEt---8炋ǞQ(|zu475₋~PC5Y6"!7VQ}s ~`nP BǩfuX/윃%000v//?՗<!_\ J#ոzJSEpihh :г}Ϸw& 3Gm)s`{o/|>4Mú_^o}u("J |!<#hllaծ $cȺv;?ȍRBA>t lbn%1Piݼ3󳜂_.j xa,Y "~,⮎{ 4M0s||e ~?t]ǵW^ou$"shx`5ClN|d"VZ=,kIJrwF*~rŢ.Y]A!!m_K ,DJ/I"zY`0H$?}~E)s?@ a#sG^x%_ iA9q$RӲ` m(}JVinBl6,˂\&Dz!-ß_/gEZ~" rwt-~˲ 2b8fΞw6?4qú+#HdHu@CC6n܄]=Hә%2*?+[uBX1yC\p3څRNu =&d@^ҋBBS~*UK316}-9ELEע`ɢX9*3D 3va㦷 a3 7]{%#\0tV{ᅬ9180M.pmR4̾g!˲@/xqP*w]7[g U\1߾+XSC_Ƚ=IT@H_(ypkK z/Z`.^9~'2 v7"q _g1007L@1slێW˃e62o>/:M$*u$X!0E b{MJ=G+?GÂE`ީߩ8nԎn7o*|3ʁNqjg76 tfc477E 418!eBF+pf!Q߼^j :A_ XT[ /woqaD1эB(C Gaw. Bm&2e5MVvCAJo+c}l14 7 Y6pt. -\wp˗,y"=T`1~Eݸ:P FTg~IH&0^Ph/t+(=::!X4[WD/Y_m/DPJPmD cjd:0l / BU}bEO7:D__?| 9o.g_' A?dY-_h4#ٵs:W^ESS#6;{RD뫩+UR4,d݊@P-*:+9R?v?c}ˠj} z;{.2[Ѓ''TUŭ7\OC40Ms7[(us//榦)Q8h6*L W/N5sŠ/$! Ab0K+fX `CQ!^ U1bEw)uV?$a^Wu>}Dcgw.=fiȢ6j3A0z۶Y[L= (rEArvq_hB6犔dr`ގ9?cy?$:BDcQt1:e~YFGWۓXb3%Z,MH.??'f,r,ͯ}9!PڟG rcA^}PɱA9o-oPR~,6369?Ԣ)aCWדCi> yɉhUo7zz 5k)2BB9෨3K !NR]-np3^xB/ /$Ŧ.**Ya;攆?n“|󺖀RD"W.Ŭ` χ7J<_2 I-INs%J,hkkX  yQhWI Yv7XMF 7/'bn5[ _PJH&8*P2žxϏf>߸/ (^LOw:7[QB[6tZ3DQp@7Sv5RUbBP 075r.R_:ڽX3Ϣs$Ir)fx*pY9 >Oۯ(3ȒEKWO~YGxo{FT26=(W(U?dJ!?w"IБzY]K9G2-~B@@`-9 @04פ( -= ?0Z[w9 Yi,{>2cL$( )?xiAFTT1nRbSI3P)q+[p=6gsOg׿ü=lyU𛖅`?>>?x P{o1/[0Z[[JRsMkX go4M!}1?'˲3s:0.m @+sb.kίs,s0><.R4֜'(Dո3X5o~(=Oxȩ b=>(`Nc Pp7rt;R ٜ_Q0009#VϽ0Ng"q?ڟcC zVƽyK*X--\[m/[m6-v%E\{,{\UtsrkσAǩX1T_ʹsò-hi gZI抺UĒݏ@L;OUtjksBl,h4\ S903qRt|#ߓ?t NJwF"cie.1c[ƃ H\!j˽/˶* ":Ģ˯bnWV?F؈ל~44qM0u?˲ rY-"kJD">ܴͱ/)#&ZX,OY0D7f ܕeEe ]oX8^zy_M`Fc$֜;?BAvc!H\}6hm=lnO]eʼn*dCzTSW*YоN=v1_ـX~yp"Q1<w%[D%J}>rNaC0SR[TqFZSr܂ߜSOFOw'y~#s/i4 T? _@baMB0ků1^/h-IL$|U] @N`qΕxlh4i '^^MqXjSc8?K |L+^ǜtV`F;B >w9 Y kwn?1x{n.)c4DR7P qWG"3k.Zh cvGw~MǪ=84p 2v IDAT0u%7jbY;w;s&"L#$Y~_ͯ%RoDhP"PT+W ` `άX #Sit|U릉F97 GCCnqM>;߀3ιsAP4]6]EjR e'r1pER!p[pLB C$23O².DQ9M>ٝr5 9iMʥnjšs.mw5{B8ܵX]iΟ]k"#Gn+j*ཊLbh@-6|Yj}~:D,YD~ !lx}#fwv#J!XtNQB7L quz= 朵_]B(IUR}\[1<T*CM>zXD~iRFF2B:an:uM8 q_!#.? qڝω |2sKUrgE'E U VjYj\M_ r颒B!ƛٍD"٢.׵#8p_e q0m?ww^(-\W0j WȲL4_ @ T8>fL&̚xcE8|u81nvH?YX,,? ٙ:ѿbȝxO<ٙ0kzA"]ͬ4ظ 3.@"v3m7 O5NK|1Qk+!(Qd n6񂥥St8%X}|y*}>sh?'/o 3v!HB4XڍSOp_w?w?oI$ omFU @ زe~w$ M\m?.ާfg8-F4ϋɁ?df Y*n*8ĢNsйk/7ߎ8N߿-IRo.W'<]~WT2~ڿUi)'Ӗ + Moa܅t'3p^p1ne}&W}qPg![{ n64CFSE%Lԩڲe+%hD h[nd2LTjzBviϗ?jEb7`[oc.Dcq躆=Gs^nY`~_O:]{)Vگ?'3YJ&.mIRѿj}Iw~EO%k%Icy.v᫭ff'pVX2?~lz̜ۅX<бg!̚Q5-0[{ y=A R要FR\wӭ{`$I'M~>?[ME ?bYA1O7rT|,2'3N[V~] pʜBu,[N=qpͷ!ȸu8pR\{h 7?+bY~q~Jr]@SS]<P_70ڹW?'_:}̚ۅ 4]ò]yY/ x+Z[NϿ2>I&r,9k ˲ oTU5^-`ͯ ~1cqƪ 0a.4 'Rez#q Am\F糧R25/R39G\4b#q7M~[aּ.l۾ibɢ5]ko dY^C>oj_u4qw#κb__zpJ{GM SMc`c UUeYD])[䣢/9<}yIUUEo_?fGoeXҽg[ zc1TY\kYϯCx:QJ۶]) ~rν1&;N:gXSv>m3,Y8sjq 9+3Gs৹hnją\uބpsTp_>U@D|NϮvoR˽Ţ˜1&= kN_X<^~ˁ?aVGy=،s~=Skm c%<M]=q%Wko?1U;C APUq ;g)Z8f9w6 s,DYv>X{^rFAvHN7A hMM_ko@K?ǡٶϧ#9O<9UU,q se Fq?q*쎅&06 + hiql/B__ߥz_w:L?_`w deq#yM0^Á:>]9ihm +ƕ~- ŗW]3w  >06Ljtoo&t=#RƐ{~,Kw6R]>H;oMI`3ۉ,fCeԎxŗt`Alç*2- ( Hk:Z[+eW\`0QqW`>_a͸+u׍k۟S5~л}7caG5ȞPQE{.:lۆ(8C0mL I,6A eۘ;1<*?s0\w=.b7]{%>U~f\21ϵR__Eт4 0ιiD{{|~L4T`xo I" R A KR]K?B(Â,*,ڊu߄/`(kħ? %o% WLo 4ɓ&Ѳ*y"i ެb۶ S,sh L N0 A&!ọ<[TUl` 2d!' =L3$M0!N06@ @HCwXBcI0c`]jyz%,T#WU|ŷ>k=ηH!7Q M?9zi?,_yG?wpeXlEջ%\R̶b!_8cǎ)h}72n˯T*]&BH@' ct:^x_ۈ&}4Fao}.<1x֙ho/ W^T ,_Ap G&90}vvtoLW/&LrU:?euXdy\m(!(;hXiC !6nzw>v.G.Sq>܄[o J|sz̟w$zz{y1cpOnu?qO!-wQ}j+Wio7P(eyU+RH)Q(>ֈ뢮;q7`!ח]:~ȸ 9;??繰8KqQ sOD u?dtyiጲM_P߂?``.wҡy:qɞ`ORM6RnI5lB)_p%KnˮǂG}ro2K߀1~U 9DRuw|(?x`7J\tX*$v)P B) B1(iC`gJ2hcJ47eŗ^9~8VLo@TJ)ai~@@ ܹsHOb|q.E58"9%RX/`ɴְ8GX~ /,˲p +Vކ+I (n5!!=Wq{@`@G;;ھNT,*'jܘp0oI~ @Sc#~i{ -+n,_8(mͷގ+~|-4ԗ9`!T)YA;mmuX1.jkm=.8iig PRic}Gk)YHXd~J)FP@v{}I+n.8=%f펻p bQ#)!8yRwO?,0q>&fY0 = GBb"gݕR&Sf8X ˃$KsE(W(߀ιBƥWck{p?*bѿ翚/Tq\_ܢE2F" "m}_ضK)Z?۶;Ī !JƛonGKs3ۆ(DE Nals3~ēY砧T 7. -MYu}+dZꇟR&J'+1>>CΓB˲km>߾A!5SF!<σmۈJkt- qט?3gLCRS&Oµ?!r) k?祬 VB;hNg:Da%bl#ytνp]JkQa:r;.  Eu@)E J4przzz>8&cj"0#$)˵,π$ "┯|wv3f͜!D )c@Iqc199r4r˟mlcwO,Z(pt:vtt\S/R~"auΝ(F<ѲGk&"P+B_XBY3g`y v_RAi d1FqߓdCX,Oiٵ8b ضW( wnر͈cB8 <8 1Z7QLkkmFd2p 9v <9w!-Վj0U|T $!qrʏ|u?!ZǥP?@)A]g}~hֶ6\ | .v !:cmۿ7EQ~=l|yWտ'5H)qܓ0 lB@e\>;~S:5,*76xxE! Ab)hE}&@?B)hk~2FJrѧj=A<O_-;N}8p`Tn"wcŋVrG sӋ/Y|s'߄HSb /lci^DhM)%JcyI z?"` Ǜ7oq盝ե8!D2Dߗ6/ܣ?Ļtി;Tt=!t2)QW. ~W 7(5Bs0^^ cJ鈁@ı 3fL rPut(xײ8 "fLCfBXjwW>Q"Nzh"qCk_;P>躮+xX{;^)((m[FJI2@)m;m{ J+@U 1nBy66&ɼz>(u_"NS~oo5MMM_~eqPs&c߼r B)c:qnoj-{crO%:(p7n(PWm._hI:F{ێS;oS QJՈ @*U=ԗ6~GtʕRJUz8ؖ2kf'p+!e3V:4i Z,1c&0r (eBȲ,˲mn!3iĠ2?5"9qpВ%3kkimW4IQHpFؖO>ʃԲ"J9b_/cl˲")Ñz `W`)U$-z(ǵo|SB1[fvmJF@+ٳfu !ˎT RRBJJ~;[~4~?~ƒPp>Z)e}ߗmg׼ϟG !HWT*0!Vl|{ϼ757]E1RFs;Vg #u)0!|k3{%<3FhmeYHRvF!H {RyQbG{@r>_p}ߋF_P1u1]?~e[<=,˜o`҄ b!$oV.y]zv{)&G:F6D) Ι17LgϞLfsb(A`cV2GTXP P_3# Bttt3Y,W )*B+}mnYK 6!D0LYQ!B@1J)jx651ڍxDZi"`mضݿ졔 RSP2 |FJ)(u]^( ozk5ctCRJ8U4*=c R1F&O$(/DQR1ƒՂB`%{n$_%PJ⹮%3gݼ B)e1]-ỴaBerP2ؿyߘ;H</IDATz-?I㌈ɮl8_{{~_k-¶-;1x:PcQ wW2m[m\.JP͋/QRJ1 !2[ձ~M Z0F2Ƭ 6ʹs(ΌlTBaђ1f' ҦcOB>7x%v]BD bY|T_ArpB{ubѢv`LcNFZkS,J)K 1ms$+l*6m=[!RJw&EO:^M=1kڧKNXlqvg7i8ն("Ƙ]{`BO}r]QJח{1 L1oo~-MMMLkWTzk0$,֚[XhԏԷt]iMR"b򑝜YPjZkι86ڈJ~ ,29ί G#۸qSqRjar/Qqu q,,Tk3Fk` ֚B88[E9TXc$*b؁e?젘?ٲS2#}HcPJyy%3h$V$޶,nB haSN];z C87J*&@ `1H({bűPc 8OدpHĸL~`Dcɲ 0\ݠ5JQk-1|ώc\;aĵo{ZؖfZRk&WP+Hy+` e~Fo|SirűB 9B(Gw|އ ވTieoRn6*ܹsz<8s֌ oKNXT^bR] ^XXqqgnf>|`Bp1fN{xBJE.OzF){3`OsP+?'3wFJ%+)7桺LGqkZ4[IOBIQC mm`xAEPc %]7V_r.6ge;a. """ import __builtin__ __builtin__.pyo_use_double = True from pyo import *pyo/README.md0000644000175000017500000000724712652732202012147 0ustar tiagotiago# Pyo - Python DSP module # pyo is a Python module written in C to help digital signal processing script creation. pyo is a Python module containing classes for a wide variety of audio signal processing types. With pyo, user will be able to include signal processing chains directly in Python scripts or projects, and to manipulate them in real time through the interpreter. Tools in pyo module offer primitives, like mathematical operations on audio signal, basic signal processing (filters, delays, synthesis generators, etc.), but also complex algorithms to create sound granulation and others creative audio manipulations. pyo supports OSC protocol (Open Sound Control), to ease communications between softwares, and MIDI protocol, for generating sound events and controlling process parameters. pyo allows creation of sophisticated signal processing chains with all the benefits of a mature, and widely used, general programming language. Systems : OS X (10.5 -> 10.10), linux, Windows (XP, Vista, 7, 8) Python versions : 2.6, 2.7 [PYO OFFICAL WEB SITE](http://ajaxsoundstudio.com/pyo/) **Download latest binaries, source release and documentation** [HERE](http://ajaxsoundstudio.com/pyo/)! How to get pyo running from sources on OS X and linux: [INSTALL Instructions](http://ajaxsoundstudio.com/pyodoc/compiling.html) pyo was awarded **second prize** in the [Lomus 2012](http://concours.afim-asso.org/2012/) Free Software Competition. ## Radio Pyo ## If you want to listen to scripts rendered in real-time, just connect to [Radio Pyo](http://radiopyo.acaia.ca/) ! You want to have your script played on the radio ? Follow the instructions on this [post](http://acaia.ca/~tiago/posts/introducing-radio-pyo-live-music-in-python/) ! ## Softwares using pyo as audio engine ## [Zyne](https://github.com/belangeo/zyne) : A modular soft synthesizer. [Soundgrain](http://ajaxsoundstudio.com/software/soundgrain/) : A graphical interface where users can draw and edit trajectories to control granular sound synthesis. [Cecilia 5](http://ajaxsoundstudio.com/software/cecilia/) : An audio signal processing environment. [PsychoPy](http://www.psychopy.org/) : An open-source application to allow the presentation of stimuli and collection of data for a wide range of neuroscience, psychology and psychophysics experiments. ## Examples ## pyo is fully integrated to Python and very simple to use. Play a sound: ``` >>> from pyo import * >>> s = Server().boot() >>> s.start() >>> sf = SfPlayer("path/to/your/sound.aif", speed=1, loop=True).out() ``` Granulate an audio buffer: ``` >>> s = Server().boot() >>> s.start() >>> snd = SndTable("path/to/your/sound.aif") >>> env = HannTable() >>> pos = Phasor(freq=snd.getRate()*.25, mul=snd.getSize()) >>> dur = Noise(mul=.001, add=.1) >>> g = Granulator(snd, env, [1, 1.001], pos, dur, 24, mul=.1).out() ``` Generate melodies: ``` >>> s = Server().boot() >>> s.start() >>> wav = SquareTable() >>> env = CosTable([(0,0), (100,1), (500,.3), (8191,0)]) >>> met = Metro(.125, 12).play() >>> amp = TrigEnv(met, table=env, mul=.1) >>> pit = TrigXnoiseMidi(met, dist='loopseg', x1=20, scale=1, mrange=(48,84)) >>> out = Osc(table=wav, freq=pit, mul=amp).out() ``` ## Donation ## This project is developed by Olivier Bélanger on his free time to provide a fully integrated Python dsp module for sound exploration and music composition. If you feel this project is useful to you and want to support it and it's future development please consider donating money. I only ask for a small donation, but of course I appreciate any amount. [![](https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CA99DH6ES3HA)pyo/scripts/0000755000175000017500000000000012652732202012345 5ustar tiagotiagopyo/scripts/radiopyo-template.py0000644000175000017500000000363112652732202016361 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Template for a RadioPyo song (version 1.0). A RadioPyo song is a musical python script using the python-pyo module to create the audio processing chain. You can connect to the radio here : http://radiopyo.acaia.ca/ There is only a few rules: 1 - It must be a one-page script. 2 - No soundfile, only synthesis. 3 - The script must be finite in time, with fade-in and fade-out to avoid clicks between pieces. Use the DURATION variable. belangeo - 2014 """ from pyo import * ################### USER-DEFINED VARIABLES ################### ### READY is used to manage the server behaviour depending ### ### of the context. Set this variable to True when the ### ### music is ready for the radio. TITLE and ARTIST are the ### ### infos shown by the radio player. DURATION set the ### ### duration of the audio file generated for the streaming.### ############################################################## READY = False # Set to True when ready for the radio TITLE = "Song Title" # The title of the music ARTIST = "Artist Name" # Your artist name DURATION = 300 # The duration of the music in seconds ##################### These are optional ##################### GENRE = "Electronic" # Kind of your music, if there is any DATE = 2014 # Year of creation ####################### SERVER CREATION ###################### if READY: s = Server(duplex=0, audio="offline").boot() s.recordOptions(dur=DURATION, filename="radiopyo.ogg", fileformat=7) else: s = Server(duplex=0).boot() ##################### PROCESSING SECTION ##################### # global volume (should be used to control the overall sound) fade = Fader(fadein=0.001, fadeout=10, dur=DURATION).play() ### ### Insert your algorithms here... ### #################### START THE PROCESSING ################### s.start() if not READY: s.gui(locals()) pyo/scripts/html_man.py0000644000175000017500000002440712652732202014525 0ustar tiagotiago""" Copyright 2009-2015 Olivier Belanger This file is part of pyo, a python module to help digital signal processing script creation. pyo is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. pyo is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with pyo. If not, see . """ import os, inspect, shutil from types import ListType from pyo import * ####################################################### ######## DEPRECATED DOCUMENTATION GENERATOR ########### ####################################################### # 'manuel-dev' for development, 'manual' for production man_file = 'manual-dev' if man_file == 'manual-dev': man_version = 'latest sources' else: man_version = 'version %s' % PYO_VERSION print PYO_VERSION try: os.mkdir(os.getcwd() + '/doc') except OSError: pass f = open(os.getcwd() + '/doc/%s.tex' % man_file, 'w') # Header f.write("\documentclass[12pt,oneside]{article}\n") f.write("\usepackage[utf8]{inputenc}\n") f.write("\usepackage{dcolumn,amsmath}\n\n") f.write("\usepackage{html,makeidx}\n\n") f.write("\\begin{document}\n\n") def getDoc(obj): try: init = '\n\n' + class_args(eval(obj)).replace("_", "\_") + '\n\n' init = init.replace("self, ", "") except: init = '\n\n' try: text = eval(obj).__doc__ if text == None: text = '' except: text = '' try: doc_str = getFormattedDoc(text, obj) except: doc_str = text try: methods = getMethodsDoc(text, obj) except: methods = '' page_text = init + doc_str + methods + "\n\n" if len(methods): page_text += '\end{verbatim}\n\n' if doc_str == '': page_text += "\nnot documented yet...\n\n" return page_text def getMethodsDoc(text, obj): lines = text.splitlines(True) flag = False add_tab = False verbatim = False methods = '' for line in lines: if flag: if line.strip() == '': continue else: l = line.lstrip() ppos = l.find('(') if ppos != -1: meth = l[0:ppos] arg, varargs, varkw, defaults = inspect.getargspec(getattr(eval(obj), meth)) arg = inspect.formatargspec(arg, varargs, varkw, defaults, formatvalue=removeExtraDecimals) arg = arg.replace("self, ", "") if add_tab: methods += ' ' + obj + '.' + meth + arg + ':\n' add_tab = False else: methods += obj + '.' + meth + arg + ':\n' docstr = getattr(eval(obj), meth).__doc__.rstrip() methods += docstr + '\n\n\n ' if 'Methods:' in line: flag = True add_tab = True verbatim = True methods += '\n\\begin{Large}{\\bf Methods details:}\n\\end{Large}\n' methods += '\n\\begin{verbatim}\n\n' for key in DOC_KEYWORDS: if key != 'Methods': if key in line: flag = False return methods def getFormattedDoc(text, obj): lines = text.splitlines(True) text = '' title = '' skip_empty_line = False verbatim = False for line in lines: flag = False see_also = False for key in DOC_KEYWORDS: if key in line: if key == 'See also': see_also = True break elif key == "Parentclass": break else: flag = True skip_empty_line = True last_title = title title = key break if flag: if verbatim: text += '\\end{verbatim}\n' verbatim = False text += '\n\\begin{Large}' + '{\\bf ' + line + '}\\end{Large}' text += '\n\\begin{verbatim}\n' if title == 'Examples': text += "from pyo import *\n" verbatim = True elif see_also: if verbatim: text += '\\end{verbatim}\n' verbatim = False text += '\n\\begin{Large}' + '{\\bf See also: }\\end{Large}' line_tmp = line.replace('See also:', '') words = line_tmp.split(',') for word in words: text += '\\htmladdnormallink{%s}{%s.html} ' % (word, word) elif 'Parentclass' in line: text += '\n\\begin{large} {\\bf Parentclass}: \\end{large}' text += '\\htmladdnormallink{%s}{%s.html}\n' % (line.split(':')[1].strip(), line.split(':')[1].strip()) else: if skip_empty_line: skip_empty_line = False else: if title == 'Examples': if line.strip() == '': if "s = Server()" in text: text += 's.gui(locals())\n' skip_empty_line = True if ">>>" in line: line.lstrip(" ") line = line.lstrip(">>> ") if "..." in line: line.lstrip(" ") line = " " + line.lstrip("... ") text += line if verbatim: text += '\\end{verbatim}\n' verbatim = False return text def getDocFirstLine(obj): try: text = eval(obj).__doc__ if text == None: text = '' except: text = '' if text != '': spl = text.split('\n') if len(spl) == 1: f = spl[0] else: f = spl[1] else: f = text return f # Generates the LaTeX file f.write('\\begin{Huge}pyo documentation ( %s )\\end{Huge}\n\n' % man_version) f.write('pyo is a Python module written in C to help digital signal processing script creation.\n\n') f.write(""" pyo is a Python module containing classes for a wide variety of audio signal processing types. With pyo, user will be able to include signal processing chains directly in Python scripts or projects, and to manipulate them in real time through the interpreter. Tools in pyo module offer primitives, like mathematical operations on audio signal, basic signal processing (filters, delays, synthesis generators, etc.), but also complex algorithms to create sound granulation and others creative sound manipulations. pyo supports OSC protocol (Open Sound Control), to ease communications between softwares, and MIDI protocol, for generating sound events and controlling process parameters. pyo allows creation of sophisticated signal processing chains with all the benefits of a mature, and wild used, general programming language. """) for key in ['Server', 'Stream', 'TableStream', 'PyoObjectBase', 'Map', 'functions']: f.write('\chapter[%s : %s]{%s}\n\n' % (key, getDocFirstLine(key), key)) f.write(getDoc(key)) if type(OBJECTS_TREE[key]) == ListType: for obj in OBJECTS_TREE[key]: f.write('\section[%s : %s]{%s}\n\n' % (obj, getDocFirstLine(obj), obj)) f.write(getDoc(obj)) else: if key == 'Map': key2list = ['SLMap'] else: key2list = ['PyoMatrixObject', 'PyoTableObject', 'PyoObject'] for key2 in key2list: f.write('\section[%s : %s]{%s}\n\n' % (key2, getDocFirstLine(key2), key2)) f.write(getDoc(key2)) if type(OBJECTS_TREE[key][key2]) == ListType: for obj in OBJECTS_TREE[key][key2]: f.write('\subsection[%s : %s]{%s}\n\n' % (obj, getDocFirstLine(obj), obj)) f.write(getDoc(obj)) else: for key3 in sorted(OBJECTS_TREE[key][key2]): f.write('\subsection[%s : %s]{%s}\n\n' % (key3, getDocFirstLine(key3), key3)) f.write(getDoc(key3)) for obj in OBJECTS_TREE[key][key2][key3]: f.write('\subsubsection[%s : %s]{%s}\n\n' % (obj, getDocFirstLine(obj), obj)) f.write(getDoc(obj)) f.write('\end{document}\n') f.close() # LaTeX -> html os.chdir('doc/') os.system('latex2html %s.tex' % man_file) # Post-processing on html files for file in os.listdir(man_file): with open("%s/%s" % (man_file, file), 'r') as f: text = f.read() text = text.replace("</A>", "") if text.find('href="prettify.css"') == -1: st = '' % man_file stnew = """ """ % man_file text = text.replace(st, stnew) st = 'Examples:') if ex_pos != -1: st = '

'
                stnew = '
'
                text_first = text[:ex_pos]
                text_second = text[ex_pos:]
                text_second = text_second.replace(st, stnew, 1)
                text = text_first + text_second

    with open("%s/%s" % (man_file, file), 'w') as f:
        f.write(text)
        
# Clean-up        
os.remove('%s.tex' % man_file)
os.chdir('../')
shutil.copy('scripts/prettify.css', 'doc/%s' % man_file)
shutil.copy('scripts/prettify.js', 'doc/%s' % man_file)

# Upload on iACT server
print "Upload documentation (y/n)?"
ans = raw_input()
if (ans == 'y'):
    os.system('scp -r doc/%s sysop@132.204.178.49:/Library/WebServer/Documents/pyo/' % man_file)
pyo/scripts/tutorials/0000755000175000017500000000000012652732202014373 5ustar  tiagotiagopyo/scripts/tutorials/HowToWritePyoObjectInC.txt0000644000175000017500000000510412652732202021420 0ustar  tiagotiagoHow to write a pyo C object:

In mousemodule.c:

1-  Copy a similar object C source code (I think MidiNote-Notein in midimodule.c is a good starting point). 
        - For the Mouse module, you will need two base objects:
            Mouser -> Scan for mouse position and keep values in memory
            Mouse -> The real audio objects looking in Mouser for X or Y position and filling self->data.
        
2-  Find-Replace object's names.
        - MidiNote -> Mouser
        - Notein -> Mouse
    
3-  Name_compute_next_data_frame is the function called by the server's callback every buffer size.
    Here you put all your calls...
   
4-  In Mouse object "struct", you need an array "modebuffer" with at least two slots for the "mul" and "add" mode (audio or float).
    This is called at the end of Name_comput_next_data_frame with:
        (*self->muladd_func_ptr)(self);
    This pointer is set with Name_setProcMode function. All postprocessing functions are MACROS in pyomodule.h.

5-  The Mouse object must defines a static Mouse_as_number element to allow basic arithmetic operations on the object.

MACROS (in pyomodule.h):

pyo_audio_HEAD -> Create all common variables. self->data is the samples buffer.
POST_PROCESSING_* -> Handle arithmetic operations.
pyo_VISIT and pyo_CLEAR -> Free common variables.
INIT_OBJECT_COMMON -> Initialize all common variables (server, mul, add, data, stream, etc.).
GET_SERVER, GET_STREAM -> Return references...
PLAY, STOP, OUT (if needed) -> Handle starttime, duration, output channel, etc.
MULTIPLY, ADD, SUB, DIV, INPLACE_* -> Initialize arithmetic operations and set the function's pointer.

In pyomodule.c:

-   Add a reference to the new object's types in the module:

    if (PyType_Ready(&MouserType) < 0)
        return;
    Py_INCREF(&MouserType);
    PyModule_AddObject(m, "Mouser_base", (PyObject *)&MouserType);

    if (PyType_Ready(&MouseType) < 0)
        return;
    Py_INCREF(&MouseType);
    PyModule_AddObject(m, "Mouse_base", (PyObject *)&MouseType);
    
    *_base are the objects called by the Python classes.
    
In pyomodule.h:

    - Declares the PyTypeObject:
    
    extern PyTypeObject MouserType;
    extern PyTypeObject MouseType;
    
In pyo.py

    - Add the object (only the object to call in a script) in the OBJECTS_TREE dictionary:
    
    'controls': sorted(['Fader', 'Sig', 'SigTo', 'Adsr', 'Linseg', 'Expseg', 'Mouse']),
    
In pyolib/controls.py:

-   Copy the Notein class from midi.py and modify it for your object's needs.

    "x" and "y" can be used as identifier to retrieve the streams.
    obj["x"] and obj["y"]
    

    

pyo/scripts/tutorials/tutorialMakingClasses.txt0000644000175000017500000004335312652732202021454 0ustar  tiagotiago#summary This is a little tutorial on how to create your own object for sound processing.

= Introduction =

For this example, we will be creating a Vocoder effect. Beginning with a very simple class, we will gradually add features to create a more sophisticated class. The resulting class will act almost like a real pyo object.

First of all, let's create a file called "vocoder_lib.py" where we will put the classes to import in the main script.

Files "vocoder_lib.py" and "vocoder_main.py" can be found in the examples folder from the pyo's sources.

= Simple Vocoder =

There is one thing to remember to avoid weird behaviour from our class: *All pyo objects must live over time in order to be able to compute audio samples*. It's a good habit to always create pyo objects with the prefix "self" to avoid them being destroyed at the end of the __init__ method.

Start by importing all modules you will need in your class (at least pyo):

{{{
import math
from pyo import *
}}}

And here is the class !SimpleVocoder:

{{{
class SimpleVocoder:
    def __init__(self, in1, in2, num=32, base=50, spread=1.5, q=5):
        self._in1 = in1
        self._in2 = in2
        self._num = num
        self._base = base
        self._spread = spread
        self._q = q
        self._freqs = Sig([self._base * math.pow(i+1, self._spread) for i in range(self._num)])
        self._clipped_freqs = Clip(self._freqs, 20, 20000)
    
        self._src = Biquadx(self._in1, freq=self._clipped_freqs, q=self._q, type=2, stages=4)
        self._envelope = Follower(self._src, freq=5, mul=self._q*30)
        self._exc = Biquadx(self._in2, freq=self._clipped_freqs, q=self._q, type=2, stages=4, mul=self._envelope).out()
}}}

As you can see, it's a very simple class, but ready to be used! 

Let's review what happened here. First, we keep references to pyo objects given at input for later use. Then, we compute the filter's frequencies and pass the list to a simple Sig() object. We then use that Sig() object to convert floats to audio signals to be able to Clip() the filter's frequencies (filters are unstable beyond Nyquist's frequency). Once this is done, we can create the vocoder effect by applying an envelope follower on each band of the first signal, and using these envelopes as the amplitudes of the filters on the second signal. 

Now, we can use this class in our main script (remember to place the main script in the same folder as the vocoder_lib.py file):

{{{
from pyo import *
from vocoder_lib import SimpleVocoder                 
s = Server(sr=44100, nchnls=2, buffersize=1024, duplex=0).boot()
a = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True, mul=3).play()
b = Noise()
voc = SimpleVocoder(in1=a, in2=b, num=32, base=50, spread=1.2, q=5)   
s.gui(locals())
}}}

It works, but it's useless because it's very hard to change anything in the processing.

Let's add some methods to control the Vocoder:

{{{
    def setBase(self, x):
        self._base = x
        self._freqs.value = [self._base * math.pow(i+1, self._spread) for i in range(self._num)]

    def setSpread(self, x):
        self._spread = x
        self._freqs.value = [self._base * math.pow(i+1, self._spread) for i in range(self._num)]

    def setQ(self, x):
        self._q = x
        self._envelope.mul = self._q * 30
        self._src.q = self._exc.q = self._q
}}}

Now, while it's playing, we can give calls like this to the interpreter:

{{{
voc.setBase(60)
voc.setSpread(1.5)
voc.setQ(10)
}}}

We can also use attributes to reduce the live typing by adding these lines to our class:

{{{
    @property
    def base(self): return self._base
    @base.setter
    def base(self, x): self.setBase(x)

    @property
    def spread(self): return self._spread
    @spread.setter
    def spread(self, x): self.setSpread(x)

    @property
    def q(self): return self._q
    @q.setter
    def q(self, x): self.setQ(x)
}}}

Don't forget to give "object" as the parent class to !SimpleVocoder:

{{{
class SimpleVocoder(object):
}}} 

Using attributes, we can then replace our calls to the interpreter with these ones:

{{{
voc.base = 60
voc.spread = 1.5
voc.q = 10
}}}

That's it! We now have a vocoder ready to be used in our programs.

= Vocoder (with more pyo functionality) = 

The !SimpleVocoder is useful if it's the last element in a processing chain. We can't use it like a normal pyo object. For example, if we want to pass it's resulting sound to a reverb object, we need to modify the class itself to add a reverb unit. It would be very useful to be able to pass it to other objects like any objects in the library. There is a few steps we need to take in order to create a class with all of pyo's functionality. That's what we shall do now.

*Things to consider*:

  * The parent class must be !PyoObject
  * When a !PyoObject receives another !PyoObject, it looks for a list of objects called "`self._base_objs`"
  * Adding "mul" and "add" arguments (they change objects in `self._base_objs`)
  * All !PyoObject support "list expansion"
  * All !PyoObject with sound in input support crossfading between old and new sources
  * We will probably want to override the .play(), .out() and .stop() methods
  * There is an attribute for every function modifying a parameter
  * The `__dir__` method should return a list of the available attributes as strings
  * We can define a .ctrl() method to popup a GUI to control parameters

== Declaring the class ==

We will create a new class called Vocoder with !PyoObject as it's parent class. Another good habit is to put a `__doc__` string at the beginning of our classes. Doing so will allow other user to retrieve documentation for the object with the standard python help() function.

{{{
class Vocoder(PyoObject):
    """
    Vocoder effect.

    A vocoder is an analysis/synthesis system. In the encoder, the input is passed 
    through a multi-band filter, each band is passed through an envelope follower, 
    and the control signals from the envelope followers are communicated to the 
    decoder. The decoder applies these (amplitude) control signals to corresponding 
    filters in the (re)synthesizer.
    
    
    Parent class: PyoObject

    Parameters:

    in1 : PyoObject
        Audio source generating the spectral envelope.
    in2 : PyoObject
        Audio source exciting the bank of filters.
    base : float or PyoObject, optional
        Base frequency used to compute filter notch frequencies. 
        Defaults to 50.
    spread : float or PyoObject, optional
        Spreading of the filter notch frequencies. Defaults to 1.5.
    q : float or PyoObject, optional
        Q (inverse of the bandwidth) of the filters. Defaults to 5.
    num : int, optional
        Number of bands (filter notches) of the vocoder. Available only
        at initialization. Defaults to 20.
        
    Methods:

    setIn1(x) : Replace the `in1` attribute.
    setIn2(x) : Replace the `in2` attribute.
    setBase(x) : Replace the `base` attribute.
    setSpread(x) : Replace the `spread` attribute.
    setQ(x) : Replace the `q` attribute.
    
    Attributes:

    in1 : PyoObject. Audio source generating the spectral envelope.
    in2 : PyoObject. Audio source exciting the bank of filters.
    base : float or PyoObject, Base frequency.
    spread : float or PyoObject, Spreading of the filter notch frequencies.
    q : float or PyoObject, Q of the filters.

    See also: BandSplit, Phaser

    Examples:

    >>> s = Server().boot()
    >>> s.start()
    >>> a = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True)
    >>> b = Noise()
    >>> lfo = Sine(freq=.05, mul=50, add=100)
    >>> voc = Vocoder(in1=a, in2=b, num=20, base=lfo, spread=[1.2,1.22]).out()

    """
}}}

== The `__init__` method ==

This is the place where we have to take care of some pyo's generic behaviours. The most important thing to remember is when a !PyoObject receives another !PyoObject in input, it looks for an attributes called `self._base_objs`, which is a list of object's base classes (The Sine object uses internally an object called Sine_base) considered as the audio output signal of the object. The getBaseObjects() method returns the list of base classes from a !PyoObject. We will called this method on the object generating the output signal of our process. 

We also need to add two arguments to the definition of the object: "mul" and "add". The attributes "`self._mul`" and "`self._add`" are handled by the parent class and automatically applied on the objects in "`self._base_objs`".`

Finally, we have to consider the "list expansion" feature, allowing lists in argument to make an instance of our object able to manage multiple audio streams. Two functions help us to accomplish this:

  * convertArgsToLists(`*`args) : Returns arguments converted to lists and the maximum list size.
  * wrap(list,i) : Returns value at position "i" in "list" with wrap around len(list).
  
Here is the code:

{{{
    def __init__(self, in1, in2, base=50, spread=1.5, q=5, num=20, mul=1, add=0):
        # keep references of all raw arguments
        self._in1 = in1
        self._in2 = in2
        self._base = base
        self._spread = spread
        self._q = q
        self._num = num
        self._mul = mul
        self._add = add

        # list of filter's notch frequencies
        self._partials = [i+1 for i in range(self._num)]

        # Using InputFader for sound input allows crossfades when changing sources
        self._in1_fader = InputFader(in1)
        self._in2_fader = InputFader(in2)

        # Convert all arguments to lists for "list expansion"
        # convertArgsToLists function returns variables in argument as lists + maximum list size
        in1_fader, in2_fader, base, spread, q, mul, add, lmax = convertArgsToLists(self._in1_fader, self._in2_fader, base, spread, q, mul, add)
    
        # Init some lists to keep track of created objects
        self._pows = []
        self._bases = []
        self._freqs = []
        self._srcs = []
        self._amps = []
        self._excs = []
        self._outs = []
    
        # self._base_objs is the audio output seen by the outside world!
        # .play(), .out(), .stop() and .mix() methods act on this list
        # "mul" and "add" attributes are also applied on this list's objects 
        self._base_objs = []
    
        # Each cycle of the loop creates a mono stream of sound
        for i in range(lmax):
            self._pows.append(Pow(self._partials, wrap(spread,i)))
            self._bases.append(Sig(wrap(base,i)))
            self._freqs.append(Clip(self._pows[-1] * self._bases[-1], 20, 20000))
            self._srcs.append(Biquadx(wrap(in1_fader,i), freq=self._freqs[-1], q=wrap(q,i), type=2, stages=2))
            self._amps.append(Follower(self._srcs[-1], freq=5, mul=wrap(q,i)*30))
            self._excs.append(Biquadx(wrap(in2_fader,i), freq=self._freqs[-1], q=wrap(q,i), type=2, stages=2, mul=self._amps[-1]))
            # Here we mix in mono all sub streams created by "num" bands of vocoder
            self._outs.append(Mix(input=self._excs[-1], voices=1, mul=wrap(mul,i), add=wrap(add,i)))
            # getBaseObjects() method returns the list of Object_Base, needed in the self._base_objs list
            self._base_objs.extend(self._outs[-1].getBaseObjects())
}}}  

== set methods and attributes ==

Now, we will add methods and attributes for all controllable parameters. This should be noted that we use the setInput() method of the !InputFader object to change an input source (setIn1() and setIn2()). This object implements the crossfade between the old and the new sources with a crossfade duration argument:

{{{
    def setIn1(self, x, fadetime=0.05):
        """
        Replace the `in1` attribute.

        Parameters:

        x : PyoObject
            New signal to process.
        fadetime : float, optional
            Crossfade time between old and new input. Defaults to 0.05.

        """
        self._in1 = x
        self._in1_fader.setInput(x, fadetime)

    def setIn2(self, x, fadetime=0.05):
        """
        Replace the `in2` attribute.

        Parameters:

        x : PyoObject
            New signal to process.
        fadetime : float, optional
            Crossfade time between old and new input. Defaults to 0.05.

        """
        self._in2 = x
        self._in2_fader.setInput(x, fadetime)
    
    def setBase(self, x):
        """
        Replace the `base` attribute.

        Parameters:

        x : float or PyoObject
            New `base` attribute.

        """
        self._base = x
        x, lmax = convertArgsToLists(x)
        [obj.setValue(wrap(x,i)) for i, obj in enumerate(self._bases)]

    def setSpread(self, x):
        """
        Replace the `spread` attribute.

        Parameters:

        x : float or PyoObject
            New `spread` attribute.

        """
        self._spread = x
        x, lmax = convertArgsToLists(x)
        [obj.setExponent(wrap(x,i)) for i, obj in enumerate(self._pows)]

    def setQ(self, x):
        """
        Replace the `q` attribute.

        Parameters:

        x : float or PyoObject
            New `q` attribute.

        """
        self._q = x
        x, lmax = convertArgsToLists(x)
        [obj.setMul(wrap(x,i)*30) for i, obj in enumerate(self._amps)]
        [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._srcs)]
        [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._excs)]

    @property
    def in1(self): return self._in1
    @in1.setter
    def in1(self, x): self.setIn1(x)

    @property
    def in2(self): return self._in2
    @in2.setter
    def in2(self, x): self.setIn2(x)

    @property
    def base(self): return self._base
    @base.setter
    def base(self, x): self.setBase(x)

    @property
    def spread(self): return self._spread
    @spread.setter
    def spread(self, x): self.setSpread(x)

    @property
    def q(self): return self._q
    @q.setter
    def q(self, x): self.setQ(x)
}}}

== The `__dir__` method ==

We will override the `__dir__` to return a list of all controllable attributes for our object. User can retrieve this value by calling dir(obj).

{{{
    def __dir__(self):
        return ["in1", "in2", "base", "spread", "q", "mul", "add"]
}}}

== The ctrl method ==

The ctrl() method of a !PyoObject is used to popup a GUI to control the parameters of the object. The initialization of sliders is done with a list of !SLMap objects where we can set the range of the slider, the type of scaling, the name of the attribute affected to the slider and the init value. We will define a default "map_list" that will be used if the user doesn't provide one.

{{{
    def ctrl(self, map_list=None, title=None, wxnoserver=False):
        # Define the object's default map_list used if None is passed to PyoObject
        # map_list is a list of SLMap objects defined for each available attribute
        # in the controller window
        self._map_list = [SLMap(20., 250., "lin", "base", self._base),
                          SLMap(0.5, 2., "lin", "spread", self._spread),
                          SLMap(1., 50., "log", "q", self._q),
                          SLMapMul(self._mul)]
        PyoObject.ctrl(self, map_list, title, wxnoserver)
}}} 

Finally, we might want to override .play(), .stop() and .out() methods to be sure all our internal !PyoObjects are consequently managed instead of only objects in `self._base_obj`, as it is in current objects. See the definition of these methods in the !PyoObject man page to understand the meaning of arguments.

{{{
def play(self, dur=0, delay=0):
    dur, delay, lmax = convertArgsToLists(dur, delay)
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._pows)]
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._bases)]
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._freqs)]
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._srcs)]
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._amps)]
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._excs)]
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._outs)]
    self._base_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
    return self

def stop(self):
    [obj.stop() for obj in self._pows]
    [obj.stop() for obj in self._bases]
    [obj.stop() for obj in self._freqs]
    [obj.stop() for obj in self._srcs]
    [obj.stop() for obj in self._amps]
    [obj.stop() for obj in self._excs]
    [obj.stop() for obj in self._outs]
    [obj.stop() for obj in self._base_objs]
    return self

def out(self, chnl=0, inc=1, dur=0, delay=0):
    dur, delay, lmax = convertArgsToLists(dur, delay)
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._pows)]
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._bases)]
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._freqs)]
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._srcs)]
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._amps)]
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._excs)]
    [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._outs)]
    if type(chnl) == ListType:
        self._base_objs = [obj.out(wrap(chnl,i), wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
    else:
        if chnl < 0:    
            self._base_objs = [obj.out(i*inc, wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(random.sample(self._base_objs, len(self._base_objs)))]
        else:
            self._base_objs = [obj.out(chnl+i*inc, wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
    return self
}}}

== Overriding the .play(), .stop() and .out() methods ==

Here we are, we've been created a truly object for sound processing! Of course, there is a little overhead in CPU with object written in pure python, the next step is to write it directly in C. A tutorial on how to write a pyo object in C will follow.
pyo/scripts/compile_linux_withJack.sh0000755000175000017500000000066012652732202017401 0ustar  tiagotiago#! /bin/sh

# Remove build directory if exist
if cd build; then
    echo
    echo "********** Removing older build directory **********"
    cd ..
    sudo rm -rf build
fi

echo
echo "**************************************************"
echo "****************** build library *****************"
echo "**************************************************"
echo

sudo python setup.py install --install-layout=deb --use-double --use-jack
pyo/scripts/get_dependencies.sh0000644000175000017500000000350312652732202016167 0ustar  tiagotiagoif cd /usr/local/include; 
then 
    pwd;
else 
    sudo mkdir /usr/local/include
    cd /usr/local/include;
fi
sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/portaudio.h -o "portaudio.h"
sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/portmidi.h -o "portmidi.h"
sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/porttime.h -o "porttime.h"
sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/sndfile.h -o "sndfile.h"


if cd lo;
then
    pwd;
else
    sudo mkdir lo
    cd lo;
fi    
sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_endian.h -o "lo_endian.h"
sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_errors.h -o "lo_errors.h"
sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_lowlevel.h -o "lo_lowlevel.h"
sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_macros.h -o "lo_macros.h"
sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_osc_types.h -o "lo_osc_types.h"
sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_throw.h -o "lo_throw.h"
sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_types.h -o "lo_types.h"
sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo.h -o "lo.h"

if cd /usr/local/lib; 
then 
    pwd;
else 
    sudo mkdir /usr/local/lib
    cd /usr/local/lib;
fi
sudo curl http://www.iact.umontreal.ca/pyo_deps/liblo.0.dylib -o "liblo.0.dylib"
sudo curl http://www.iact.umontreal.ca/pyo_deps/libportaudio.2.dylib -o "libportaudio.2.dylib"
sudo curl http://www.iact.umontreal.ca/pyo_deps/libportmidi.dylib -o "libportmidi.dylib"
sudo curl http://www.iact.umontreal.ca/pyo_deps/libsndfile.1.dylib -o "libsndfile.1.dylib"
sudo rm libsndfile.dylib
sudo ln -s libsndfile.1.dylib libsndfile.dylib
sudo rm liblo.dylib
sudo ln -s liblo.0.dylib liblo.dylib
sudo rm libportaudio.dylib
sudo ln -s libportaudio.2.dylib libportaudio.dylib
pyo/scripts/prettify.css0000755000175000017500000000127012652732202014730 0ustar  tiagotiago.str{color:#262}
.kwd{color:#00D;font-weight:bold}
.com{color:#07D;font-style:italic}
.typ{color:#00D;font-weight:bold}
.lit{color:#00D}
.pun{color:#660}
.pln{color:#000}
.tag{color:#008}
.atn{color:#606}
.atv{color:#080}
.dec{color:#606}

pre.prettyprint{padding:5px;border:1px solid #CCC}
ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
@media print{
.str{color:#060}
.kwd{color:#006;font-weight:bold}
.com{color:#600;font-style:italic}
.typ{color:#404;font-weight:bold}
.lit{color:#044}
.pun{color:#440}
.pln{color:#000}
.tag{color:#006;font-weight:bold}
.atn{color:#404}
.atv{color:#060}}pyo/scripts/retrieve_keywords.py0000644000175000017500000000530512652732202016476 0ustar  tiagotiagofrom pyo import *

t = "PyoObject|PyoTableObject|example|class_args|pa_count_devices|pa_get_default_input|pa_get_default_output|pa_list_devices|pa_get_output_devices|pa_get_input_devices|pm_count_devices|pm_list_devices|pm_get_input_devices|pm_get_default_input|pm_get_output_devices|pm_get_default_output|sndinfo|midiToHz|midiToTranspo|BandSplit|Biquad|Clip|Compress|Counter|DCBlock|Delay|Disto|Dummy|Fader|Follower|Freeverb|Granulator|Hilbert|Input|InputFader|Metro|Midictl|Mix|Noise|Notein|Osc|OscReceive|OscSend|Pan|Pattern|Phasor|Pointer|Port|PyPattern|SPan|TrigEnv|TrigRand|TrigChoice|TrigFunc|Select|SfMarkerShuffler|SfPlayer|Sig|Sine|TableRec|Tone|Waveguide|LinTable|NewTable|SndTable|HannTable|HarmTable|Server|Stream|TableStream|SigTo|Map|SLMap|SLMapFreq|SLMapMul|SLMapPhase|SLMapQ|SLMapDur|SLMapPan|Clean_objects|Pulsar|TableRead|Thresh|SawTable|SquareTable|ZCross|Degrade|Lookup|ChebyTable|Adsr|Convolve|TableMorph|sampsToSec|secToSamps|Randi|Randh|Choice|RandInt|FM|Cloud|Linseg|WGVerb|Trig|CosTable|CurveTable|Score|SineLoop|OscLoop|Print|Sin|Cos|Tan|Abs|Sqrt|Log|Log2|Log10|Pow|Xnoise|XnoiseMidi|TrigXnoise|TrigXnoiseMidi|Snap|Change|PyoMatrixObject|NewMatrix|MatrixRec|MatrixPointer|TrigLinseg|Interp|SampHold|EQ|CallAfter|Switch|Selector|savefile|Compare|ExpTable|Expseg|TrigExpseg|Allpass|Allpass2|Phaser|Harmonizer|Record|Biquadx|Chorus|SfMarkerLooper|Beat|Looper|Percent|MatrixMorph|TableIndex|DataTable|Seq|TrigRandInt|SDelay|Mixer|AllpassWG|Blit|PinkNoise|CrossFM|Between|Mirror|Wrap|BrownNoise|IRWinSinc|IRAverage|IRPulse|IRFM|Rossler|Lorenz|LFO|MidiAdsr|Denorm|FreqShift|OscBank|Follower2|Gate|ParaTable|FourBand|FFT|IFFT|Atan2|CarToPol|PolToCar|FrameDelta|FrameAccum|TrigTableRec|OscDataSend|OscDataReceive|Floor|Round|ControlRec|ControlRead|reducePoints|NoteinRec|NoteinRead|CtlScan|MidiDelAdsr|Ceil|Bendin|Touchin|Programin|DBToA|AToDB|WinTable|serverCreated|serverBooted|Timer|RandDur|Vectral|Scale|Iter|MToF|distanceToSegment|rescale|Biquada|upsamp|downsamp|VoiceManager|XnoiseDur|SincTable|MToT|linToCosCurve|CentsToTranspo|TranspoToCents|VarPort|getVersion|pa_count_host_apis|pa_get_default_host_api|pa_list_host_apis|OscListReceive|Count|Urn|NextTrig"
t2 = t.split("|")

tree = OBJECTS_TREE
l = []
for k1 in tree.keys():
    if type(tree[k1]) == type({}):
        for k2 in tree[k1].keys():
            for val in tree[k1][k2]:
                l.append(val)
    else:
        for val in tree[k1]:
            l.append(val)
l.append("PyoObject")
l.append("PyoTableObject")
l.append("PyoMatrixObject")
l.append("Server")

with open("pyo_keywords.txt", "w") as f:
    for i, word in enumerate(l):
        if word not in t2:
            print word
        if (i % 10) == 0:
            f.write("\n")
        f.write(word + " ")

pyo/scripts/compile_OSX_withJack.sh0000755000175000017500000000065312652732202016715 0ustar  tiagotiago#! /bin/sh

# Remove build directory if exist
if cd build; then
    echo
    echo "********** Removing older build directory **********"
    cd ..
    sudo rm -rf build
fi

echo
echo "**************************************************"
echo "****************** build library *****************"
echo "**************************************************"
echo

sudo python setup.py install --use-coreaudio --use-double --use-jack
pyo/scripts/compile_win.bat0000644000175000017500000000065012652732202015343 0ustar  tiagotiagoecho off

echo *** Compile for python2.6 ***
C:\Python26\python.exe setup.py install --use-double

RMDIR /S /Q build

echo *** Compile for python2.7 ***
C:\Python27\python.exe setup.py install --use-double

RMDIR /S /Q build

cd utils

echo *** Build E-Pyo for python2.6 ***
C:\Python26\python.exe epyo_builder_win32.py

echo *** Build E-Pyo for python2.7 ***
C:\Python27\python.exe epyo_builder_win32.py
pyo/scripts/osx/0000755000175000017500000000000012652732202013156 5ustar  tiagotiagopyo/scripts/osx/pyo_cleanup_OSX.sh0000644000175000017500000001353112652732202016564 0ustar  tiagotiago#! /bin/sh

# Make sure older version are not in the System directories
if cd /System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5; then
    if [ -f pyo.py ]; then
        echo "removing pyo from /System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5"
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi 
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

if cd /System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6; then
    if [ -f pyo.py ]; then
        echo "removing pyo from /System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.6"
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

# Removed older versions in the python site-packages builtin directories
if cd /Library/Python/2.5/site-packages/; then
    if [ -f pyo.py ]; then
        echo "removing pyo from /Library/Python/2.5/site-packages/"
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi    
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi    
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi    
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi    
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi    
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

if cd /Library/Python/2.6/site-packages/; then
    if [ -f pyo.py ]; then
        echo "removing pyo from /Library/Python/2.6/site-packages/"
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi    
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi    
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi    
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi    
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi    
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

if cd /Library/Python/2.7/site-packages/; then
    if [ -f pyo.py ]; then
        echo "removing pyo from /Library/Python/2.7/site-packages/"
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi    
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi    
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi    
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi    
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi    
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

# Removed pyo in the python site-packages python.org install directories
if cd /Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/; then
    if [ -f pyo.py ]; then
        echo "removing pyo from /Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/"
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi 
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

if cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/; then
    if [ -f pyo.py ]; then
        echo "removing pyo from /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/"
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi 
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

if cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/; then
    if [ -f pyo.py ]; then
        echo "removing pyo from /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/"
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi 
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi
pyo/scripts/osx/set_variables_OSX.sh0000644000175000017500000000177212652732202017075 0ustar  tiagotiago#! /bin/sh

# Add /usr/local/lib in .bash_profile if not already done    
searchString="/usr/local/lib"

if [ -f ~/.bash_profile ]; then
    if `cat ~/.bash_profile | grep "${searchString}" 1>/dev/null 2>&1`; then
        echo "path already in PATH variable";
    else
        echo "adding /usr/local/lib to PATH variable in .bash_profile..."
        echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" >> ~/.bash_profile;
    fi
else
    echo "creating .bash_profile and adding /usr/local/lib to PATH variable..."
	echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" > ~/.bash_profile;
fi	

# Add VERSIONER_PYTHON_PREFER_32_BIT in .bash_profile if not already done    
searchString="VERSIONER_PYTHON_PREFER_32_BIT"

if `cat ~/.bash_profile | grep "${searchString}" 1>/dev/null 2>&1`; then
    echo "Variable VERSIONER_PYTHON_PREFER_32_BIT already set.";
else
    echo "Adding VERSIONER_PYTHON_PREFER_32_BIT=yes in .bash_profile...";
    echo "export VERSIONER_PYTHON_PREFER_32_BIT=yes" >> ~/.bash_profile;
fi
pyo/scripts/osx/finish_installation.sh0000755000175000017500000002062112652732202017557 0ustar  tiagotiago#! /bin/sh

VERSION=`sw_vers -productVersion | sed -e 's/\.//g'`

if [ $VERSION -ge '1070' ]; then
    echo "Install pyo on OSX 10.7";
elif [ $VERSION -ge '1060' ]; then
    echo "Install pyo on OSX 10.6";
else
    echo "Install pyo on OSX 10.5";
fi

# Removed older versions in the python site-packages builtin directories
if cd /Library/Python/2.5/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi    
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi    
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi    
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi    
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi    
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

if cd /Library/Python/2.6/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi    
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi    
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi    
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi    
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi    
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

if cd /Library/Python/2.7/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi    
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi    
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi    
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi    
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi    
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

# Removed pyo in the python site-packages python.org install directories
if cd /Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi 
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

if cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi 
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

if cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi 
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

# Install pyo in the python site-packages builtin directories
if [ $VERSION -ge '1070' ]; then
    if cd /Library/Python/2.7/site-packages/; then
        sudo cp -r /tmp/python27/* .
    else
        sudo mkdir -p /Library/Python/2.7/site-packages/
        cd /Library/Python/2.7/site-packages/
        sudo cp -r /tmp/python27/* .
    fi
elif [ $VERSION -ge '1060' ]; then
    if cd /Library/Python/2.6/site-packages/; then
        sudo cp -r /tmp/python26/* .
    else
        sudo mkdir -p /Library/Python/2.6/site-packages/
        cd /Library/Python/2.6/site-packages/
        sudo cp -r /tmp/python26/* .
    fi
else
    if cd /Library/Python/2.5/site-packages/; then
        sudo cp -r /tmp/python25/* .
    else
        sudo mkdir -p /Library/Python/2.5/site-packages/
        cd /Library/Python/2.5/site-packages/
        sudo cp -r /tmp/python25/* .
    fi
fi

# Install pyo in the python site-packages directories created by python.org installers
if cd /Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi    
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi    
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi    
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi    
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi    
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    if [ -f pyo*-info ]; then
        sudo rm pyo*-info;
    fi    
    sudo mv /tmp/python25/* .
else
    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/
    cd /Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/
    sudo mv /tmp/python25/* .
fi

if cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi    
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi    
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi    
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi    
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi    
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    if [ -f pyo*-info ]; then
        sudo rm pyo*-info;
    fi    
    sudo mv /tmp/python26/* .
else
    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/
    cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/
    sudo mv /tmp/python26/* .
fi

if cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi    
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi    
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi    
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi    
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi    
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    if [ -f pyo*-info ]; then
        sudo rm pyo*-info;
    fi    
    sudo mv /tmp/python27/* .
else
    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/
    cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/
    sudo mv /tmp/python27/* .
fi

# Add /usr/local/lib in .bash_profile if not already done
searchString="/usr/local/lib"

if [ -f ~/.bash_profile ]; then
    if `cat ~/.bash_profile | grep "${searchString}" 1>/dev/null 2>&1`; then
        echo "path already in PATH variable";
    else
        echo "adding path to .bash_profile..."
        echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" >> ~/.bash_profile;
    fi
else
    echo "creating .bash_profile and adding path to it..."
	echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" > ~/.bash_profile;
fi	

# Add VERSIONER_PYTHON_PREFER_32_BIT in .bash_profile if not already done
searchString="VERSIONER_PYTHON_PREFER_32_BIT"

if `cat ~/.bash_profile | grep "${searchString}" 1>/dev/null 2>&1`; then
    echo "Variable VERSIONER_PYTHON_PREFER_32_BIT already set.";
else
    echo "export VERSIONER_PYTHON_PREFER_32_BIT=yes" >> ~/.bash_profile;
fipyo/scripts/osx/kwdsForTextMate.txt0000644000175000017500000000300012652732202017003 0ustar  tiagotiagoPyoObject|PyoTableObject|example|class_args|pa_count_devices|pa_get_default_input|pa_get_default_output|pa_list_devices|pa_get_output_devices|pa_get_input_devices|pm_count_devices|pm_list_devices|pm_get_input_devices|pm_get_default_input|sndinfo|midiToHz|midiToTranspo|BandSplit|Biquad|Clip|Compress|Counter|DCBlock|Delay|Disto|Dummy|Fader|Follower|Freeverb|Granulator|Hilbert|Input|InputFader|Metro|Midictl|Mix|Noise|Notein|Osc|OscReceive|OscSend|Pan|Pattern|Phasor|Pointer|Port|PyPattern|SPan|TrigEnv|TrigRand|TrigChoice|TrigFunc|Select|SfMarkerShuffler|SfPlayer|Sig|Sine|TableRec|Tone|Waveguide|LinTable|NewTable|SndTable|HannTable|HarmTable|Server|Stream|TableStream|SigTo|Map|SLMap|SLMapFreq|SLMapMul|SLMapPhase|SLMapQ|SLMapDur|SLMapPan|Clean_objects|Pulsar|TableRead|Thresh|SawTable|SquareTable|ZCross|Degrade|Lookup|ChebyTable|Adsr|Convolve|TableMorph|sampsToSec|secToSamps|Randi|Randh|Choice|RandInt|FM|Cloud|Linseg|WGVerb|Trig|CosTable|CurveTable|Score|SineLoop|OscLoop|Print|Sin|Cos|Tan|Abs|Sqrt|Log|Log2|Log10|Pow|Xnoise|XnoiseMidi|TrigXnoise|TrigXnoiseMidi|Snap|Change|PyoMatrixObject|NewMatrix|MatrixRec|MatrixPointer|TrigLinseg|Interp|SampHold|EQ|CallAfter|Switch|Selector|savefile|Compare|ExpTable|Expseg|TrigExpseg|Allpass|Allpass2|Phaser|Harmonizer|Record|Biquadx|Chorus|SfMarkerLooper|Beat|Looper|Percent|MatrixMorph|TableIndex|DataTable|Seq|TrigRandInt|SDelay|Mixer|AllpassWG|Blit|PinkNoise|CrossFM|Between|Mirror|Wrap|BrownNoise|IRWinSinc|IRAverage|IRPulse|IRFM|Rossler|Lorenz|LFO|MidiAdsr|Denorm|FreqShift|OscBank|
pyo/scripts/osx/finish_installation_x86_64.sh0000755000175000017500000001423012652732202020574 0ustar  tiagotiago#! /bin/sh

VERSION=`sw_vers -productVersion | sed -e 's/\.//g'`

if [ $VERSION -ge '1070' ]; then
    echo "Install pyo on OSX 10.7";
else
    echo "Install pyo on OSX 10.6";
fi

# Removed older versions in the python site-packages builtin directories
if cd /Library/Python/2.6/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi
fi

if cd /Library/Python/2.7/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi
fi

# Removed pyo in the python.org site-packages install directories
if cd /Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi
fi

if cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi
fi

if cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi 
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    ls -1 pyo*-info > /dev/null 2>&1
    if [ "$?" = "0" ]; then
        sudo rm pyo*-info;
    fi    
fi

# Install pyo in the python site-packages builtin directories
if [ $VERSION -ge '1070' ]; then
    if cd /Library/Python/2.7/site-packages/; then
        sudo cp -r /tmp/python27/* .
    else
        sudo mkdir -p /Library/Python/2.7/site-packages/
        cd /Library/Python/2.7/site-packages/
        sudo cp -r /tmp/python27/* .
    fi
else
    if cd /Library/Python/2.6/site-packages/; then
        sudo cp -r /tmp/python26/* .
    else
        sudo mkdir -p /Library/Python/2.6/site-packages/
        cd /Library/Python/2.6/site-packages/
        sudo cp -r /tmp/python26/* .
    fi
fi

# Install pyo in the python.org site-packages directories
if cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi    
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi    
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi    
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi    
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi    
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    if [ -f pyo*-info ]; then
        sudo rm pyo*-info;
    fi    
    sudo mv /tmp/python26/* .
else
    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/
    cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/
    sudo mv /tmp/python26/* .
fi

if cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/; then
    if [ -f pyo.py ]; then
        sudo rm pyo.py;
    fi    
    if [ -f pyo64.py ]; then
        sudo rm pyo64.py;
    fi    
    if [ -f pyo.pyc ]; then
        sudo rm pyo.pyc;
    fi    
    if [ -f pyo64.pyc ]; then
        sudo rm pyo64.pyc;
    fi    
    if [ -f _pyo.so ]; then
        sudo rm _pyo.so;
    fi    
    if [ -f _pyo64.so ]; then
        sudo rm _pyo64.so;
    fi    
    if [ -d pyolib ]; then
        sudo rm -rf pyolib/;
    fi    
    if [ -f pyo*-info ]; then
        sudo rm pyo*-info;
    fi    
    sudo mv /tmp/python27/* .
else
    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/
    cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/
    sudo mv /tmp/python27/* .
fi

# Add /usr/local/lib in .bash_profile if not already done
searchString="/usr/local/lib"

if [ -f ~/.bash_profile ]; then
    if `cat ~/.bash_profile | grep "${searchString}" 1>/dev/null 2>&1`; then
        echo "path already in PATH variable";
    else
        echo "adding path to .bash_profile..."
        echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" >> ~/.bash_profile;
    fi
else
    echo "creating .bash_profile and adding path to it..."
    echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" > ~/.bash_profile;
fi
pyo/scripts/release_doc_src.sh0000755000175000017500000000116312652732202016021 0ustar  tiagotiago#! /bin/bash

#
# 1. change version number
# cd doc-sphinx; python build.py
# 3. Execute from pyo folder : ./scripts/release_doc_src.sh
#

version=0.7.8
replace=XXX

doc_rep=pyo_XXX-doc
doc_tar=pyo_XXX-doc.tar.bz2

src_rep=pyo_XXX-src
src_tar=pyo_XXX-src.tar.bz2

cp -R ./doc-sphinx/build_html ./doc-sphinx/${doc_rep/$replace/$version}
cd doc-sphinx
tar -cjvf ${doc_tar/$replace/$version} ${doc_rep/$replace/$version}
rm -R ${doc_rep/$replace/$version}
cd ..

git checkout-index -a -f --prefix=${src_rep/$replace/$version}/
tar -cjvf ${src_tar/$replace/$version} ${src_rep/$replace/$version}
rm -R ${src_rep/$replace/$version}
pyo/scripts/win/0000755000175000017500000000000012652732202013142 5ustar  tiagotiagopyo/scripts/win/windows-build-routine.txt0000644000175000017500000001504112652732202020156 0ustar  tiagotiago=== STEP 1 ===
--- Install Python (2.5 -> 2.7)

=== STEP 2 ===
--- Install Slick SVN (Slick-Subversion-1.6.12-win32.msi)
http://www.sliksvn.com/pub/Slik-Subversion-1.6.12-win32.msi

=== STEP 3 ===
--- Install scons 2.2.0 in the Python site-packages:
http://www.scons.org/download.php

=== STEP 4 ===
--- Install MinGW (minimalist) from sourceforge

=== STEP 5 ===
--- Install pthreads (just copy files from ftp):
ftp://sourceware.org/pub/pthreads-win32/dll-latest/
C:\pthreads\bin, C:\pthreads\include, C:\pthreads\lib

=== STEP 6 === 
--- Update libsndfile from http://www.mega-nerd.com/libsndfile  to the most recent version that works, 
which may be pre-release or release; currently it is the latest stable release (1.0.25). 
Do not build from sources.

=== STEP 7 ===
--- Update liblo tag 0.26 from the tarball at http://liblo.sourceforge.net (not SVN!), 
copy build/config-msvc.h --> src/config.h,
and build with this SConstruct:

# S C O N S T R U C T   F O R   L I B L O . D L L
# Michael Gogins
# Using hints from: http://clam.iua.upf.edu/wikis/clam/index.php/Devel/Windows_MinGW_cross_compile#liblo
# Modified by Olivier Belanger on september 2010

environment = Environment(tools = ['mingw'])

sources = '''
src/address.c
src/blob.c
src/bundle.c
src/message.c
src/method.c
src/pattern_match.c
src/send.c
src/server.c
src/server_thread.c
src/timetag.c
'''

cppath = '''
.
lo
C:/pthreads/include
'''

libpath = '''
C:/MinGW/lib
C:/pthreads/lib
'''

environment.Append(CFLAGS = Split('-O2 -g -DHAVE_CONFIG_H -D_WIN32_WINNT=0x0501'))
environment.Append(CPPPATH = Split(cppath))
environment.Append(LIBPATH = Split(libpath))
environment.Append(LIBS = Split('pthreadvc2 kernel32 gdi32 wsock32 ws2_32 ole32 uuid winmm'))
environment.Append(LINKFLAGS = ['-Wl,--enable-stdcall-fixup', '-Wl,--export-all-symbols'])
### -export-all-symbols or -export-dynamic ? ###

liblo = environment.SharedLibrary('lo', Split(sources))
#######################################################

=== STEP 8 ===
--- Install Directx 9.0 SDK (april 2007)

=== STEP 9 ===
--- Download Asio SDK

===  STEP 10 ===
--- Update the PortAudio library http://portmedia.sourceforge.net from SVN and build it. 
Try the trunk version first, if that doesn't work use the most recent tag. 

--- Copy ASIOSDK to portaudio/src/hostapi/asio

--- Check the pa_win_hostapis.c file and make sure that it is configured to build 
the DirectSound, WMME, and ASIO drivers:

--- Need to removed "volatile" from function definitions in MinGW/include/winbase.h

--- Build with this SConstruct:

'''
MinGW SConstruct for PortAudio
Michael Gogins
Modified by Olivier Belanger on september 2010
'''
print __doc__
print

import os
import string
import sys
import traceback

commonEnvironment = Environment(ENV = os.environ, tools = ['mingw', 'swig', 'javac', 'jar'])
commonEnvironment.Append(CFLAGS = Split('-O2 -g'))
commonEnvironment.Append(CPPFLAGS = Split('''
-DWIN32
-D_WIN32
-DWINDOWS
-DKSAUDIO_SPEAKER_DIRECTOUT=0
-DMETHOD_NEITHER=3
-DFILE_ANY_ACCESS=0
-DPA_USE_WMME
-DPA_USE_DS
-DPA_USE_ASIO
-DPA_USE_WASAPI
'''))

commonEnvironment.Append(CPPPATH = [".", "src/common", "src/hostapi", "src/os", "src/os/win", "include",
"C:/portaudio/src/hostapi/wasapi/mingw-include",
"C:/portaudio/src/hostapi/asio/ASIOSDK/host",
"C:/portaudio/src/hostapi/asio/ASIOSDK/host/pc",
"C:/portaudio/src/hostapi/asio/ASIOSDK/common",
"C:/Program Files/Microsoft DirectX SDK (April 2007)/Include"])

commonEnvironment.Append(LIBS=Split('''
setupapi
kernel32
user32
gdi32
winspool
comdlg32
advapi32
shell32
ole32
oleaut32
uuid
odbc32
odbccp32
winmm
strmiids
'''))

portAudioSources = Split('''
src/common/pa_allocation.c
src/common/pa_converters.c
src/common/pa_cpuload.c
src/common/pa_debugprint.c
src/common/pa_dither.c
src/common/pa_front.c
src/common/pa_process.c
src/common/pa_ringbuffer.c
src/common/pa_stream.c
src/common/pa_trace.c
src/hostapi/dsound/pa_win_ds.c
src/hostapi/dsound/pa_win_ds_dynlink.c
src/hostapi/wmme/pa_win_wmme.c
src/hostapi/skeleton/pa_hostapi_skeleton.c
src/os/win/pa_win_hostapis.c
src/os/win/pa_win_util.c
src/os/win/pa_win_waveformat.c
src/os/win/pa_win_coinitialize.c
src/hostapi/asio/ASIOSDK/common/asio.cpp
src/hostapi/asio/ASIOSDK/common/combase.cpp
src/hostapi/asio/ASIOSDK/common/debugmessage.cpp
src/hostapi/asio/ASIOSDK/common/register.cpp
src/hostapi/asio/ASIOSDK/host/ASIOConvertSamples.cpp
src/hostapi/asio/ASIOSDK/host/asiodrivers.cpp
src/hostapi/asio/ASIOSDK/host/pc/asiolist.cpp
src/hostapi/asio/iasiothiscallresolver.cpp
src/hostapi/asio/pa_asio.cpp
src/hostapi/wasapi/pa_win_wasapi.c
''')

portAudio = commonEnvironment.SharedLibrary('portaudio', portAudioSources)
##########################################################################

=== STEP 11 ===
4 --- Update the PortMidi library http://portmedia.sourceforge.net from SVN and build it with this SConstruct:

'''
MinGW SConstruct for PortMidi
Michael Gogins
'''
print __doc__
print

import os
import string
import sys
import traceback

commonEnvironment = Environment(ENV = os.environ, tools = ['mingw', 'swig', 'javac', 'jar'])
commonEnvironment.Append(CFLAGS = Split('-O2 -g '))
commonEnvironment.Append(CPPFLAGS = Split('''
-DWIN32
-D_WIN32
-DWINDOWS
'''))
commonEnvironment.Append(CPPPATH = Split('''
.
pm_win
pm_common
porttime
'''))
commonEnvironment.Append(LIBS=Split('''
setupapi
kernel32
user32
gdi32
winspool
comdlg32
advapi32
shell32
ole32
oleaut32
uuid
odbc32
odbccp32
winmm
strmiids
'''))
commonEnvironment.Append(LIBPATH='.')
commonEnvironment.Append(SHLINKFLAGS = Split('-mwindows -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc'))

portMidiSources = Split('''
pm_common/pmutil.c
pm_common/portmidi.c
pm_win/pmwin.c
pm_win/pmwinmm.c
''')

portTimeSources = Split('''
porttime/porttime.c
porttime/ptwinmm.c
''')

portMidiTestSources = Split('''
pm_test/test.c
''')

porttime = commonEnvironment.SharedLibrary('porttime', portTimeSources)

portMidiEnvironment = commonEnvironment.Copy()
portMidiEnvironment.Append(LIBS='porttime')
portmidi = portMidiEnvironment.SharedLibrary('portmidi', portMidiSources)

portMidiTestEnvironment = commonEnvironment.Copy()
portMidiTestEnvironment.Append(LIBS=Split('portmidi porttime'))
test = portMidiTestEnvironment.Program('test', portMidiTestSources)

Depends(portmidi, porttime)
Depends(test, portmidi)
###########################

--- Run the test program to ensure that the build works.

=== STEP 12 ===
--- create a file PythonXX/Lib/distutils/distutils.cfg with these lines in it:
[build]
compiler = mingw32

*** For Python 2.5, comment line 428 to 434 in Python25/include/pyconfig.py

=== STEP 13 ===
--- Download pyo sources from svn and build it with:

python setup.py install
pyo/scripts/win/windows-7-build-routine.txt0000644000175000017500000001521612652732202020326 0ustar  tiagotiago=== STEP 1 ===
--- Install Python 2.6 and 2.7.10 and WxPython 3.0.2.0 for each version

=== STEP 2 (should be git soon) ===
--- Install Slick SVN 1.8.10
http://www.sliksvn.com

=== STEP 3 ===
--- Install scons 2.3.5 in the Python site-packages:
http://www.scons.org/download.php

=== STEP 4 ===
--- Install MinGW (minimalist GNU for Windows) from sourceforge
--- Add ";C:\MinGW\bin;C:\MinGW\mingw32\bin" to the PATH variable

=== STEP 5 ===
--- Install pthreads (just copy files from ftp):
ftp://sourceware.org/pub/pthreads-win32/dll-latest/
C:\pthreads\bin, C:\pthreads\include, C:\pthreads\lib

=== STEP 6 === 
--- Update libsndfile from http://www.mega-nerd.com/libsndfile  to the most recent version that works, 
which may be pre-release or release; currently it is the latest stable release (1.0.25). 
Do not build from sources.

=== STEP 7 ===
--- Update liblo tag 0.26 from the tarball at http://liblo.sourceforge.net (not SVN!), 
copy build/config-msvc.h --> src/config.h,

If there is a conflict about struct timespec, remove the definition in pthread.h.

and build with this SConstruct:

# S C O N S T R U C T   F O R   L I B L O . D L L
# Michael Gogins
# Using hints from: http://clam.iua.upf.edu/wikis/clam/index.php/Devel/Windows_MinGW_cross_compile#liblo
# Modified by Olivier Belanger on september 2010

environment = Environment(tools = ['mingw'])

sources = '''
src/address.c
src/blob.c
src/bundle.c
src/message.c
src/method.c
src/pattern_match.c
src/send.c
src/server.c
src/server_thread.c
src/timetag.c
'''

cppath = '''
.
lo
C:/pthreads/include
'''

libpath = '''
C:/MinGW/lib
C:/pthreads/lib
'''

environment.Append(CFLAGS = Split('-O2 -g -DHAVE_CONFIG_H -D_WIN32_WINNT=0x0501'))
environment.Append(CPPPATH = Split(cppath))
environment.Append(LIBPATH = Split(libpath))
environment.Append(LIBS = Split('pthreadvc2 kernel32 gdi32 wsock32 ws2_32 ole32 uuid winmm'))
environment.Append(LINKFLAGS = ['-Wl,--enable-stdcall-fixup', '-Wl,--export-all-symbols'])
### -export-all-symbols or -export-dynamic ? ###

liblo = environment.SharedLibrary('lo', Split(sources))
#######################################################

=== STEP 8 ===
--- Install Directx 9.0 SDK (april 2007)

=== STEP 9 ===
--- Download Asio SDK

===  STEP 10 ===
--- Update the PortAudio library http://portmedia.sourceforge.net from SVN and build it. 
Try the trunk version first, if that doesn't work use the most recent tag. 

--- Copy ASIOSDK to portaudio/src/hostapi/asio

--- Check the pa_win_hostapis.c file and make sure that it is configured to build 
the DirectSound, WMME, and ASIO drivers. (nothing to do here)

--- Need to removed "volatile" from function definitions in MinGW/include/winbase.h

--- Build with this SConstruct:

'''
MinGW SConstruct for PortAudio
Michael Gogins
Modified by Olivier Belanger on september 2010
'''
print __doc__
print

import os
import string
import sys
import traceback

commonEnvironment = Environment(ENV = os.environ, tools = ['mingw', 'swig', 'javac', 'jar'])
commonEnvironment.Append(CFLAGS = Split('-O2 -g'))
commonEnvironment.Append(CPPFLAGS = Split('''
-DWIN32
-D_WIN32
-DWINDOWS
-DKSAUDIO_SPEAKER_DIRECTOUT=0
-DMETHOD_NEITHER=3
-DFILE_ANY_ACCESS=0
-DPA_USE_WMME
-DPA_USE_DS
-DPA_USE_ASIO
-DPA_USE_WASAPI
'''))

commonEnvironment.Append(CPPPATH = [".", "src/common", "src/hostapi", "src/os", "src/os/win", "include",
"C:/portaudio/src/hostapi/wasapi/mingw-include",
"C:/portaudio/src/hostapi/asio/ASIOSDK/host",
"C:/portaudio/src/hostapi/asio/ASIOSDK/host/pc",
"C:/portaudio/src/hostapi/asio/ASIOSDK/common",
"C:/Program Files (x86)/Microsoft DirectX SDK (April 2007)/Include"])

commonEnvironment.Append(LIBS=Split('''
setupapi
kernel32
user32
gdi32
winspool
comdlg32
advapi32
shell32
ole32
oleaut32
uuid
odbc32
odbccp32
winmm
strmiids
'''))

portAudioSources = Split('''
src/common/pa_allocation.c
src/common/pa_converters.c
src/common/pa_cpuload.c
src/common/pa_debugprint.c
src/common/pa_dither.c
src/common/pa_front.c
src/common/pa_process.c
src/common/pa_ringbuffer.c
src/common/pa_stream.c
src/common/pa_trace.c
src/hostapi/dsound/pa_win_ds.c
src/hostapi/dsound/pa_win_ds_dynlink.c
src/hostapi/wmme/pa_win_wmme.c
src/hostapi/skeleton/pa_hostapi_skeleton.c
src/os/win/pa_win_hostapis.c
src/os/win/pa_win_util.c
src/os/win/pa_win_waveformat.c
src/os/win/pa_win_coinitialize.c
src/hostapi/asio/ASIOSDK/common/asio.cpp
src/hostapi/asio/ASIOSDK/common/combase.cpp
src/hostapi/asio/ASIOSDK/common/debugmessage.cpp
src/hostapi/asio/ASIOSDK/common/register.cpp
src/hostapi/asio/ASIOSDK/host/ASIOConvertSamples.cpp
src/hostapi/asio/ASIOSDK/host/asiodrivers.cpp
src/hostapi/asio/ASIOSDK/host/pc/asiolist.cpp
src/hostapi/asio/iasiothiscallresolver.cpp
src/hostapi/asio/pa_asio.cpp
src/hostapi/wasapi/pa_win_wasapi.c
''')

portAudio = commonEnvironment.SharedLibrary('portaudio', portAudioSources)
##########################################################################

=== STEP 11 ===
--- Update the PortMidi library http://portmedia.sourceforge.net from SVN and build it with this SConstruct:

'''
MinGW SConstruct for PortMidi
Michael Gogins
'''
print __doc__
print

import os
import string
import sys
import traceback

commonEnvironment = Environment(ENV = os.environ, tools = ['mingw', 'swig', 'javac', 'jar'])
commonEnvironment.Append(CFLAGS = Split('-O2 -g '))
commonEnvironment.Append(CPPFLAGS = Split('''
-DWIN32
-D_WIN32
-DWINDOWS
'''))
commonEnvironment.Append(CPPPATH = Split('''
.
pm_win
pm_common
porttime
'''))
commonEnvironment.Append(LIBS=Split('''
setupapi
kernel32
user32
gdi32
winspool
comdlg32
advapi32
shell32
ole32
oleaut32
uuid
odbc32
odbccp32
winmm
strmiids
'''))
commonEnvironment.Append(LIBPATH='.')
commonEnvironment.Append(SHLINKFLAGS = Split('-mwindows -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc'))

portMidiSources = Split('''
pm_common/pmutil.c
pm_common/portmidi.c
pm_win/pmwin.c
pm_win/pmwinmm.c
''')

portTimeSources = Split('''
porttime/porttime.c
porttime/ptwinmm.c
''')

portMidiTestSources = Split('''
pm_test/test.c
''')

porttime = commonEnvironment.SharedLibrary('porttime', portTimeSources)

portMidiEnvironment = commonEnvironment.Copy()
portMidiEnvironment.Append(LIBS='porttime')
portmidi = portMidiEnvironment.SharedLibrary('portmidi', portMidiSources)

portMidiTestEnvironment = commonEnvironment.Copy()
portMidiTestEnvironment.Append(LIBS=Split('portmidi porttime'))
test = portMidiTestEnvironment.Program('test', portMidiTestSources)

Depends(portmidi, porttime)
Depends(test, portmidi)
###########################

--- Run the test program to ensure that the build works.

=== STEP 12 ===
--- create a file PythonXX/Lib/distutils/distutils.cfg with these lines in it:
[build]
compiler = mingw32

=== STEP 13 ===
--- Download pyo sources from svn and build it with:

python setup.py install
pyo/scripts/prettify.js0000755000175000017500000004450012652732202014557 0ustar  tiagotiagowindow.PR_SHOULD_USE_CONTINUATION=true;window.PR_TAB_WIDTH=8;window.PR_normalizedHtml=window.PR=window.prettyPrintOne=window.prettyPrint=void 0;window._pr_isIE6=function(){var y=navigator&&navigator.userAgent&&navigator.userAgent.match(/\bMSIE ([678])\./);y=y?+y[1]:false;window._pr_isIE6=function(){return y};return y};
(function(){function y(b){return b.replace(L,"&").replace(M,"<").replace(N,">")}function H(b,f,i){switch(b.nodeType){case 1:var o=b.tagName.toLowerCase();f.push("<",o);var l=b.attributes,n=l.length;if(n){if(i){for(var r=[],j=n;--j>=0;)r[j]=l[j];r.sort(function(q,m){return q.name");
for(l=b.firstChild;l;l=l.nextSibling)H(l,f,i);if(b.firstChild||!/^(?:br|link|img)$/.test(o))f.push("");break;case 3:case 4:f.push(y(b.nodeValue));break}}function O(b){function f(c){if(c.charAt(0)!=="\\")return c.charCodeAt(0);switch(c.charAt(1)){case "b":return 8;case "t":return 9;case "n":return 10;case "v":return 11;case "f":return 12;case "r":return 13;case "u":case "x":return parseInt(c.substring(2),16)||c.charCodeAt(1);case "0":case "1":case "2":case "3":case "4":case "5":case "6":case "7":return parseInt(c.substring(1),
8);default:return c.charCodeAt(1)}}function i(c){if(c<32)return(c<16?"\\x0":"\\x")+c.toString(16);c=String.fromCharCode(c);if(c==="\\"||c==="-"||c==="["||c==="]")c="\\"+c;return c}function o(c){var d=c.substring(1,c.length-1).match(RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));c=[];for(var a=[],k=d[0]==="^",e=k?1:0,h=d.length;e122)){s<65||g>90||a.push([Math.max(65,g)|32,Math.min(s,90)|32]);s<97||g>122||a.push([Math.max(97,g)&-33,Math.min(s,122)&-33])}}a.sort(function(v,w){return v[0]-w[0]||w[1]-v[1]});d=[];g=[NaN,NaN];for(e=0;eh[0]){h[1]+1>h[0]&&a.push("-");
a.push(i(h[1]))}}a.push("]");return a.join("")}function l(c){for(var d=c.source.match(RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g")),a=d.length,k=[],e=0,h=0;e=2&&c==="[")d[e]=o(g);else if(c!=="\\")d[e]=g.replace(/[a-zA-Z]/g,function(s){s=s.charCodeAt(0);return"["+String.fromCharCode(s&-33,s|32)+"]"})}return d.join("")}for(var n=0,r=false,j=false,q=0,m=b.length;q=0;l-=16)o.push("                ".substring(0,l));l=n+1;break;case "\n":f=0;break;default:++f}if(!o)return i;o.push(i.substring(l));return o.join("")}}function I(b,
f,i,o){if(f){b={source:f,c:b};i(b);o.push.apply(o,b.d)}}function B(b,f){var i={},o;(function(){for(var r=b.concat(f),j=[],q={},m=0,t=r.length;m=0;)i[c.charAt(d)]=p;p=p[1];c=""+p;if(!q.hasOwnProperty(c)){j.push(p);q[c]=null}}j.push(/[\0-\uffff]/);o=O(j)})();var l=f.length;function n(r){for(var j=r.c,q=[j,z],m=0,t=r.source.match(o)||[],p={},c=0,d=t.length;c=5&&"lang-"===k.substring(0,5))&&!(e&&typeof e[1]==="string")){h=false;k=P}h||(p[a]=k)}g=m;m+=a.length;if(h){h=e[1];var s=a.indexOf(h),v=s+h.length;if(e[2]){v=a.length-e[2].length;s=v-h.length}k=k.substring(5);I(j+g,a.substring(0,s),n,q);I(j+g+s,h,Q(k,h),q);I(j+g+v,a.substring(v),n,q)}else q.push(j+g,k)}r.d=q}return n}function x(b){var f=[],i=[];if(b.tripleQuotedStrings)f.push([A,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
null,"'\""]);else b.multiLineStrings?f.push([A,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):f.push([A,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);b.verbatimStrings&&i.push([A,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);if(b.hashComments)if(b.cStyleComments){f.push([C,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"]);i.push([A,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,
null])}else f.push([C,/^#[^\r\n]*/,null,"#"]);if(b.cStyleComments){i.push([C,/^\/\/[^\r\n]*/,null]);i.push([C,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}b.regexLiterals&&i.push(["lang-regex",RegExp("^"+Z+"(/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/)")]);b=b.keywords.replace(/^\s+|\s+$/g,"");b.length&&i.push([R,RegExp("^(?:"+b.replace(/\s+/g,"|")+")\\b"),null]);f.push([z,/^\s+/,null," \r\n\t\u00a0"]);i.push([J,/^@[a-z_$][a-z_$@0-9]*/i,null],[S,/^@?[A-Z]+[a-z][A-Za-z_$@0-9]*/,
null],[z,/^[a-z_$][a-z_$@0-9]*/i,null],[J,/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],[E,/^.[^\s\w\.$@\'\"\`\/\#]*/,null]);return B(f,i)}function $(b){function f(D){if(D>r){if(j&&j!==q){n.push("");j=null}if(!j&&q){j=q;n.push('')}var T=y(p(i.substring(r,D))).replace(e?d:c,"$1 ");e=k.test(T);n.push(T.replace(a,s));r=D}}var i=b.source,o=b.g,l=b.d,n=[],r=0,j=null,q=null,m=0,t=0,p=Y(window.PR_TAB_WIDTH),c=/([\r\n ]) /g,
d=/(^| ) /gm,a=/\r\n?|\n/g,k=/[ \r\n]$/,e=true,h=window._pr_isIE6();h=h?b.b.tagName==="PRE"?h===6?" \r\n":h===7?" 
\r":" \r":" 
":"
";var g=b.b.className.match(/\blinenums\b(?::(\d+))?/),s;if(g){for(var v=[],w=0;w<10;++w)v[w]=h+'
  • ';var F=g[1]&&g[1].length?g[1]-1:0;n.push('
    1. ");s=function(){var D=v[++F%10];return j?""+D+'':D}}else s=h; for(;;)if(m");j=null}n.push(o[m+1]);m+=2}else if(t");g&&n.push("
    ");b.a=n.join("")}function u(b,f){for(var i=f.length;--i>=0;){var o=f[i];if(G.hasOwnProperty(o))"console"in window&&console.warn("cannot override language handler %s",o);else G[o]=b}}function Q(b,f){b&&G.hasOwnProperty(b)||(b=/^\s*1&&m.charAt(0)==="<"){if(!ba.test(m))if(ca.test(m)){f.push(m.substring(9,m.length-3));n+=m.length-12}else if(da.test(m)){f.push("\n");++n}else if(m.indexOf(V)>=0&&m.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g,' $1="$2$3$4"').match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/)){var t=m.match(W)[2],p=1,c;c=j+1;a:for(;c=0;){var e=p.indexOf(";",k);if(e>=0){var h=p.substring(k+3,e),g=10;if(h&&h.charAt(0)==="x"){h=h.substring(1);g=16}var s=parseInt(h,g);isNaN(s)||(p=p.substring(0,k)+String.fromCharCode(s)+p.substring(e+1))}}a=p.replace(ea,"<").replace(fa,">").replace(ga,"'").replace(ha,'"').replace(ia," ").replace(ja, "&")}f.push(a);n+=a.length}}o={source:f.join(""),h:r};var v=o.source;b.source=v;b.c=0;b.g=o.h;Q(i,v)(b);$(b)}catch(w){if("console"in window)console.log(w&&w.stack?w.stack:w)}}var A="str",R="kwd",C="com",S="typ",J="lit",E="pun",z="pln",P="src",V="nocode",Z=function(){for(var b=["!","!=","!==","#","%","%=","&","&&","&&=","&=","(","*","*=","+=",",","-=","->","/","/=",":","::",";","<","<<","<<=","<=","=","==","===",">",">=",">>",">>=",">>>",">>>=","?","@","[","^","^=","^^","^^=","{","|","|=","||","||=", "~","break","case","continue","delete","do","else","finally","instanceof","return","throw","try","typeof"],f="(?:^^|[+-]",i=0;i:&a-z])/g,"\\$1");f+=")\\s*";return f}(),L=/&/g,M=//g,X=/\"/g,ea=/</g,fa=/>/g,ga=/'/g,ha=/"/g,ja=/&/g,ia=/ /g,ka=/[\r\n]/g,K=null,aa=RegExp("[^<]+| Even harmonics") frs = Sig([40.04,39.41,41.09,38.7]) frs.ctrl([SLMap(10., 1000., 'log', 'value', frs.value)], title="Input osc frequencies") # Amplitude and phase scaling amp = drv * 2 * math.pi + 0.5 phiscl = Scale(phi, inmin=0, inmax=math.pi/2, outmin=1, outmax=.5) # Amplitude envelope f = Linseg([(0,0),(.5,0),(1,1)], mul=amp).play() # Signal with lot of harmonics t = HarmTable([1,0,0,0,0,.33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,.2,0,0,0,0,0,0,0,.143]) a = OscBank(t, freq=frs, spread=.0001, slope=1, num=24, fjit=True, mul=f) # Cos waveshaping b = Cos(math.pi * a + phi) b1 = DCBlock(b*phiscl) c = Sig(b1 / amp, mul=.2).out() s.gui(locals())pyo/examples/synthesis/05_ring_mod_class.py0000644000175000017500000000164112652732202020370 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Ring modulators used as exciter of a waveguide bank. """ from pyo import * s = Server(duplex=0).boot() tab_m = HarmTable([1,0,0,0,0,.3,0,0,0,0,0,.2,0,0,0,0,0,.1,0,0,0,0,.05]).normalize() tab_p = HarmTable([1,0,.33,0,.2,0,.143,0,.111]) class Ring: def __init__(self, fport=250, fmod=100, amp=.3): self.mod = Osc(tab_m, freq=fmod, mul=amp) self.port = Osc(tab_p, freq=fport, mul=self.mod) def out(self): self.port.out() return self def sig(self): return self.port lf = Sine(.03, mul=.5, add=1) rg = Ring(fport = [random.choice([62.5,125,187.5,250]) * random.uniform(.99,1.01) for i in range(8)], fmod = lf * [random.choice([25,50,75,100]) * random.uniform(.99,1.01) for i in range(8)], amp = 0.1) res = Waveguide(rg.sig(), freq=[30.1,60.05,119.7,181,242.5,303.33], dur=30, mul=.1).out() s.gui(locals())pyo/examples/synthesis/01_pulsar_synthesis.py0000644000175000017500000000120112652732202021010 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Hand-written pulsar synthesis. """ from pyo import * import random s = Server(sr=48000, nchnls=2, buffersize=512, duplex=0).boot() # simple pulsar waveform t = HarmTable([1,0,.3,0,.2,0,0,.1], size=32768) # Chorus of reader indexes around frequencies 50, 100, 150 and 200 Hz a = Phasor(freq=[((i%4)+1)*50*random.uniform(.99, 1.01) for i in range(16)]) # Duty cycle control frac = Sig(.5) frac.ctrl(title="Pulsar duty cycle") # Pulsar synthesis scl = a * (a <= frac) * (1. / frac) c = Pointer(table=HannTable(), index=scl, mul=.05) d = Pointer(table=t, index=scl, mul=c).out() s.gui(locals())pyo/examples/synthesis/04_degrade_synthesis.py0000644000175000017500000000127412652732202021112 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Synthesis sound with lot of harmonics passed through a Degrade object. """ from pyo import * s = Server(duplex=0).boot() # Fadein f = Fader(fadein=4, mul=.3).play() # Waveform table wt = HarmTable([1,0,.2,0,.10,0,0,.1,0,0,0,.15]).normalize() # 6 waveform readers with amplitude variations lf = Sine([.15,.2], 0, .35, .5) a = Osc(table=wt, freq=[25,50.1,101,149.7,201.3,251.8], mul=lf) # table lookup with waveforms as input indexes t = ChebyTable([1,0,.3,0,.2,0,.143,0,.111]) b = Lookup(t, a, 1.-lf) # signal with lot of harmonics passed through a Degrade object c = Degrade(b, bitdepth=5.967, srscale=0.0233, mul=f).out() c.ctrl() s.gui(locals())pyo/examples/synthesis/07_split_sideband_synthesis.py0000644000175000017500000000352112652732202022503 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Split-Sideband Synthesis. Variation of three well known distortion techniques, Waveshaping, Singlesideband modulation and Frequency Modulation. Based on the article : "SPLIT-SIDEBAND SYNTHESIS" from Victor Lazzarini, Joseph Timoney, Thomas Lysaght Ann Arbor, MPublishing, University of Michigan Library, August 2008 """ from pyo import * import math s = Server(sr=48000, nchnls=2, buffersize=512, duplex=0).boot() twopi = 2 * math.pi oneOverTwoPi = 1.0 / twopi sinus = HarmTable() mod = RandInt(max=8, freq=.25, mul=.05, add=29.8) index = Sig([12.649, 9], mul=oneOverTwoPi) index.ctrl(map_list=[SLMap(0, 20, "lin", "value", [12.649, 9])], title="Indexes") car = Sig([150, 484.324]) car.ctrl(map_list=[SLMap(20, 2000, "log", "value", [150, 484.324])], title="Carrier frequencies") a1 = Sine(freq=mod, mul=index[0]) a2 = Pointer(table=sinus, index=a1+0.25) a3 = Pointer(table=sinus, index=a1) even = Hilbert(a2) odd = Hilbert(a3) ac = Sine(freq=car[0], mul=0.5) ad = Sine(freq=car[0], phase=0.25, mul=0.5) evenReal = even["real"] * ac oddReal = odd["real"] * ac evenImag = even["imag"] * ad oddImag = odd["imag"] * ad evenUpper = evenReal + evenImag oddUpper = oddReal + oddImag evenLower = evenReal - evenImag oddLower = oddReal - oddImag sa1 = Sine(freq=oddLower*car[0], mul=index[1]) sa2 = Pointer(table=sinus, index=sa1+0.25) sa3 = Pointer(table=sinus, index=sa1) seven = Hilbert(sa2) sodd = Hilbert(sa3) sac = Sine(freq=car[1], mul=0.5) sad = Sine(freq=car[1], phase=0.25, mul=0.5) sevenReal = seven["real"] * sac soddReal = sodd["real"] * sac sevenImag = seven["imag"] * sad soddImag = sodd["imag"] * sad sevenUpper = sevenReal + sevenImag soddUpper = soddReal + soddImag sevenLower = sevenReal - sevenImag soddLower = soddReal - soddImag mix = Mix([sevenLower, sevenUpper], voices=2, mul=.2).out() s.gui(locals())pyo/examples/synthesis/02_FM3.py0000644000175000017500000000160712652732202015771 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ 3 oscillators FM synthesis class. """ from pyo import * import math s = Server(sr=48000, nchnls=2, buffersize=512, duplex=0).boot() t = HarmTable([1,0.1]) class FM3: def __init__(self, fcar, ratio1, ratio2, index1, index2, out=0): self.fmod = fcar * ratio1 self.fmodmod = self.fmod * ratio2 self.amod = self.fmod*index1 self.amodmod = self.fmodmod * index2 self.modmod = Sine(self.fmodmod, mul=self.amodmod) self.mod = Sine(self.fmod+self.modmod, mul=self.amod) self.car = Osc(t, fcar+self.mod, mul=.2) self.eq = EQ(self.car, freq=fcar, q=0.707, boost=-12) self.out = DCBlock(self.eq).out(out) a = FM3(125.00, 0.33001, 2.9993, 8, 4, 0) b = FM3(125.08, 0.33003, 2.9992, 8, 4, 1) c = FM3(249.89, 0.33004, 2.9995, 8, 4, 0) d = FM3(249.91, 0.33006, 2.9991, 8, 4, 1) s.gui(locals()) pyo/examples/synthesis/08_bucket_brigade_device.py0000644000175000017500000000204712652732202021662 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ bucket-brigade device (BBD) synthesis. This implementation consists of two delay lines cross-feeded with an internal ring-modulator and a lowpass filter inside each delay line. The delay lines are feeded with a sine wave. """ from pyo import * s = Server(sr=48000, nchnls=2, buffersize=512, duplex=0).boot() t = HarmTable(size=32768) src = Osc(t, 100) src.ctrl(title="Input oscillator controls") in_src = src * 0.025 feed = .8 cross_feed = .99 del_1 = Delay(in_src, delay=Sine(.005, 0, .05, .25)) sine_1 = Osc(t, Sine(.007, 0, 50, 250)) ring_1 = del_1 * sine_1 filt_1 = Biquad(ring_1, 3000) del_2 = Delay(in_src, delay=Sine(.003, 0, .08, .3)) sine_2 = Osc(t, Sine(.008, 0, 40, 200)) ring_2 = del_2 * sine_2 filt_2 = Biquad(ring_2, 3000) cross_1 = filt_2 * cross_feed cross_2 = filt_1 * cross_feed del_1.setInput(filt_1 * feed + cross_1 + in_src) del_2.setInput(filt_2 * feed + cross_2 + in_src) mix = Mix([filt_1, filt_2], voices=2) output = Compress(mix, thresh=-30, ratio=4, knee=0.5).out() s.gui(locals()) pyo/examples/fft/0000755000175000017500000000000012652732202013253 5ustar tiagotiagopyo/examples/fft/02_fft_cross.py0000644000175000017500000000160412652732202016117 0ustar tiagotiago#! /usr/bin/env python # encoding: utf-8 """ Performs the cross-synthesis of two sounds. """ from pyo import * s = Server(duplex=0).boot() snd1 = SfPlayer("../snds/baseballmajeur_m.aif", loop=True).mix(2) snd2 = FM(carrier=[75,100,125,150], ratio=[.999,.5005], index=20, mul=.4).mix(2) size = 1024 olaps = 4 fin1 = FFT(snd1, size=size, overlaps=olaps) fin2 = FFT(snd2, size=size, overlaps=olaps) # get the magnitude of the first sound mag = Sqrt(fin1["real"]*fin1["real"] + fin1["imag"]*fin1["imag"], mul=10) # scale `real` and `imag` parts of the second sound by the magnitude of the first one real = fin2["real"] * mag imag = fin2["imag"] * mag fout = IFFT(real, imag, size=size, overlaps=olaps) ffout = fout.mix(2).out() # change of fft size must be done on all fft and ifft objects at the same time! def setSize(x): fin1.size = x fin2.size = x fout.size = x s.gui(locals()) pyo/examples/fft/01_fft_filter.py0000644000175000017500000000105612652732202016253 0ustar tiagotiago#! /usr/bin/env python # encoding: utf-8 """ Spectral domain filter. """ from pyo import * s = Server(duplex=0).boot() a = Noise(.1).mix(2) size = 1024 olaps = 4 filter_init = [(0,0.0000),(5,0.9337),(13,0.0000),(21,0.4784),(32,0.0000),(37,0.1927),(size/2,0.0000)] fin = FFT(a, size=size, overlaps=olaps, wintype=2) t = ExpTable(filter_init, size=size/2) t.graph(title="Filter shape") amp = TableIndex(t, fin["bin"]) re = fin["real"] * amp im = fin["imag"] * amp fout = IFFT(re, im, size=size, overlaps=olaps, wintype=2).mix(2).out() s.gui(locals()) pyo/examples/fft/06_fft_vectral.py0000644000175000017500000000161212652732202016431 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Spectral gate and blur. """ from pyo import * s = Server(duplex=0).boot() snd = '../snds/ounkmaster.aif' chnls = sndinfo(snd)[3] size = 2048 olaps = 8 win = 5 snd = SfPlayer(snd, loop=True, mul=.3) fin = FFT(snd, size=size, overlaps=olaps, wintype=win) pol = CarToPol(fin["real"], fin["imag"]) # bin-by-bin amplitude threshold thresh = Sig(.2) thresh.ctrl([SLMap(0.0001,1,"log","value",0.2)], title="Gate Threshold") # attenuation mult = Sig(.1) mult.ctrl([SLMap(0.0001,1,"log","value",0.0001)], title="Gate Attenuation") amp = Compare(pol["mag"]*50, thresh, ">") scl = amp * (1 - mult) + mult delta = Vectral(pol["mag"]*scl, framesize=size, overlaps=olaps, down=.35) delta.ctrl(title="Blur controls") car = PolToCar(delta, pol["ang"]) fout = IFFT(car["real"], car["imag"], size=size, overlaps=olaps, wintype=win).mix(chnls).out() s.gui(locals()) pyo/examples/fft/05_fft_delay.py0000644000175000017500000000246712652732202016077 0ustar tiagotiago#! /usr/bin/env python # encoding: utf-8 """ Apply spectral delays on a sound. """ from pyo import * s = Server(duplex=0).boot() snd = "../snds/ounkmaster.aif" chnls = sndinfo(snd)[3] size = 1024 olaps = 4 num = olaps*chnls # number of streams for ffts src = SfPlayer(snd, loop=True, mul=.15) delsrc = Delay(src, delay=size/s.getSamplingRate()*2).out() # duplicates bin regions and delays to match the number of channels * overlaps def duplicate(li, num): tmp = [x for x in li for i in range(num)] return tmp binmin = duplicate([3,10,20,27,55,100], num) binmax = duplicate([5,15,30,40,80,145], num) delays = duplicate([80,20,40,100,60,120], num) # delays conversion : number of frames -> seconds for i in range(len(delays)): delays[i] = delays[i] * (size/2) / s.getSamplingRate() fin = FFT(src*1.25, size=size, overlaps=olaps) # splits regions between `binmins` and `binmaxs` with time variation lfo = Sine(.1, mul=.65, add=1.35) bins = Between(fin["bin"], min=binmin, max=binmax*lfo) swre = fin["real"] * bins; swim = fin["imag"] * bins # apply delays with mix to match `num` audio streams delre = Delay(swre, delay=delays, feedback=.7, maxdelay=2).mix(num) delim = Delay(swim, delay=delays, feedback=.7, maxdelay=2).mix(num) fout = IFFT(delre, delim, size=size, overlaps=olaps).mix(chnls).out() s.gui(locals()) pyo/examples/fft/07_fft_stretch.py0000644000175000017500000000316212652732202016450 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Time stretching using FFT/IFFT. """ from pyo import * s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot() # Settings # snd = '../snds/flute.aif' stretch_factor = 10 size = 4096 olaps = 8 wintype = 7 info = sndinfo(snd) chnls = info[3] hop = size/olaps nframes = info[0] / size a = SfPlayer(snd, mul=.1) # "overlaps * chnls" Matrices of width FFTSIZE and height NUM_OF_FRAMES # to record magnitude and phase analysis frames m_mag = [NewMatrix(width=size, height=nframes) for i in range(olaps*chnls)] m_pha = [NewMatrix(width=size, height=nframes) for i in range(olaps*chnls)] fin = FFT(a, size=size, overlaps=olaps, wintype=wintype) pol = CarToPol(fin["real"], fin["imag"]) delta = FrameDelta(pol["ang"], framesize=size, overlaps=olaps) m_mag_rec = MatrixRec(pol["mag"], m_mag, 0, [i*hop for i in range(olaps) for j in range(chnls)]).play() m_pha_rec = MatrixRec(delta, m_pha, 0, [i*hop for i in range(olaps) for j in range(chnls)]).play() # Playback pointer pos = Phasor(1./info[1]/stretch_factor, mul=nframes) m_mag_read = MatrixPointer(m_mag, fin["bin"]/size, pos/nframes) m_pha_read = MatrixPointer(m_pha, fin["bin"]/size, pos/nframes) # Smoothing magnitude and angle rate of changes m_mag_smo = Vectral(m_mag_read, framesize=size, overlaps=olaps, up=.5, down=.5, damp=1) m_pha_smo = Vectral(m_pha_read, framesize=size, overlaps=olaps, up=.5, down=.5, damp=1) accum = FrameAccum(m_pha_smo, framesize=size, overlaps=olaps) car = PolToCar(m_mag_smo, accum) fout = IFFT(car["real"], car["imag"], size=size, overlaps=olaps, wintype=wintype).mix(chnls).mix(2).out() s.gui(locals()) pyo/examples/fft/03_fft_morph.py0000644000175000017500000000230412652732202016112 0ustar tiagotiago#! /usr/bin/env python # encoding: utf-8 """ Spectral morphing of two sounds. """ from pyo import * s = Server(duplex=0).boot() snd1 = SfPlayer("../snds/baseballmajeur_m.aif", loop=True, mul=.3).mix(2) lfos = Sine(freq=[.05,.04], mul=.05, add=[1,.5]) snd2 = FM(carrier=[75,100.03,125.5,149], ratio=lfos, index=20, mul=.1).mix(2) size = 1024 olaps = 4 inter = Sig(1.) inter.ctrl([SLMap(0, 2, "lin", "value", 1.)], title="Morphing (0 = snd1, 1 = morph, 2 = snd2)") fin1 = FFT(snd1, size=size, overlaps=olaps) fin2 = FFT(snd2, size=size, overlaps=olaps) # get magnitudes and phases of input sounds pol1 = CarToPol(fin1["real"], fin1["imag"]) pol2 = CarToPol(fin2["real"], fin2["imag"]) # times magnitudes and adds phases mag3 = pol1["mag"] * pol2["mag"] * 200 pha3 = pol1["ang"] + pol2["ang"] # interpolation between dry and morphed sounds mag = Selector([pol1["mag"], mag3, pol2["mag"]], voice=inter) pha = Selector([pol1["ang"], pha3, pol2["ang"]], voice=inter) # converts back to rectangular car = PolToCar(mag, pha) fout = IFFT(car["real"], car["imag"], size=size, overlaps=olaps) ffout = fout.mix(2).out() def siz(size=1024): fin1.size = size fin2.size = size fout.size = size s.gui(locals()) pyo/examples/fft/08_fft_spec.py0000644000175000017500000000117212652732202015726 0ustar tiagotiago#! /usr/bin/env python # encoding: utf-8 """ Display the sonogram of a sound using a PyoMatrixObject. A better display can be achieved by using a custom drawing. After the playback ending, call "m.view()" from the interpreter widget of the Server window to show the spectrum. """ from pyo import * s = Server(duplex=0).boot() son = '../snds/baseballmajeur_m.aif' info = sndinfo(son) a = SfPlayer(son, mul=.25).mix(1).out() size = 512 m = NewMatrix(width=size, height=info[0]/size) fin = FFT(a*100, overlaps=1) mag = Sqrt(fin["real"]*fin["real"] + fin["imag"]*fin["imag"]) rec = MatrixRec(mag*2-1, m, 0).play() s.gui(locals()) pyo/examples/fft/04_fft_gate.py0000644000175000017500000000141612652732202015711 0ustar tiagotiago#! /usr/bin/env python # encoding: utf-8 """ Spectral domain noise reduction. """ from pyo import * s = Server(duplex=0).boot() snd = "../snds/flute.aif" chnls = sndinfo(snd)[3] src = SfPlayer(snd, loop=True, mul=.5) size = 1024 olaps = 4 # bin-by-bin amplitude threshold thresh = Sig(.1) thresh.ctrl([SLMap(0.0001,1,"log","value",.1)], title="Threshold") # attenuation mult = Sig(.1) mult.ctrl([SLMap(0.0001,1,"log","value",.1)], title="Attenuation") fin = FFT(src, size=size, overlaps=olaps) mag = Sqrt(fin["real"]*fin["real"] + fin["imag"]*fin["imag"]) amp = Compare(mag*50, thresh, ">") scl = amp * (1 - mult) + mult re = fin["real"] * scl im = fin["imag"] * scl fout = IFFT(re, im, size=size, overlaps=olaps) ffout = Mix(fout, chnls, mul=.5).out() s.gui(locals()) pyo/examples/utilities/0000755000175000017500000000000012652732202014507 5ustar tiagotiagopyo/examples/utilities/06_separated_threads.py0000644000175000017500000000120012652732202021041 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Launch the audio processing in a separated thread and send events. See play_snd.py for subprocess sound player. """ import subprocess, time, random pipe = subprocess.Popen(["python -i play_snd.py"], shell=True, stdin=subprocess.PIPE).stdin # Wait for the Server to be ready time.sleep(2) # send events to the sub process for i in range(20): snd = "../snds/snd_%d.aif" % random.randrange(1,7) pipe.write("sf.path = '%s'\ndump = sf.play()\n" % snd) time.sleep(random.uniform(.2, .5)) # Stop the audio Server before exiting pipe.write("s.stop()\ntime.sleep(0.25)\n") pipe.close() pyo/examples/utilities/03_savefile.py0000644000175000017500000000071512652732202017164 0ustar tiagotiago#!/usr/bin/env python """ Generates 5 seconds of white noise and saves it in a file called noise.aif on the Desktop. """ from pyo import savefile from random import uniform import os home = os.path.expanduser("~") path = os.path.join(home, "Desktop", "noise.aif") sr = 44100 dur = 5 chnls = 2 samples = [[uniform(-0.5,0.5) for i in range(sr*dur)] for i in range(chnls)] savefile(samples=samples, path=path, sr=sr, channels=chnls, fileformat=1, sampletype=1)pyo/examples/utilities/05_high_sr_processing.py0000644000175000017500000000234512652732202021250 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ This script demonstrates how to use pyo to apply processing on an up sampled sound. Steps are: 1 - Up sampling the source. 2 - Offline processing on the up sampled sound. 3 - Down sampled the processed sound. """ import os from pyo import * UP = 8 DOWN = 8 SIZE = 512 IN_SND = "../snds/baseballmajeur_m.aif" UP_SND = os.path.join(os.path.expanduser("~"), "Desktop", "baseballmajeur_up_%i.aif" % UP) PROC_SND = os.path.join(os.path.expanduser("~"), "Desktop", "baseballmajeur_disto.aif") DOWN_SND = os.path.join(os.path.expanduser("~"), "Desktop", "baseballmajeur_disto_down.aif") DUR = sndinfo(IN_SND)[1] SR = sndinfo(IN_SND)[2] print "Up sampling %i times..." % UP upsamp(IN_SND, UP_SND, UP, SIZE) print "Apply distortion at a sampling rate of %i Hz." % (SR*UP) s = Server(sr=SR*UP, nchnls=1, duplex=0, audio="offline").boot() s.recordOptions(dur=DUR+.1, filename=PROC_SND, fileformat=0, sampletype=0) sf = SfPlayer(IN_SND, loop=False, interp=4, mul=0.7) dist = Disto(sf, drive=0.75, slope=0.7, mul=0.3) filt = Biquad(dist, freq=8000, q=0.7, type=0).out() s.start() print "Down sampling %i times..." % DOWN downsamp(PROC_SND, DOWN_SND, DOWN, SIZE) os.remove(UP_SND) os.remove(PROC_SND) print "Done" pyo/examples/utilities/04_batch_synthesis.py0000644000175000017500000000175012652732202020561 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ This script demonstrates how to use pyo to do synthesis batch generation. """ import os from pyo import * s = Server(duplex=0, audio="offline") # output folder output_folder = os.path.join(os.path.expanduser("~"), "pyo_batch_synth") if not os.path.isdir(output_folder): os.mkdir(output_folder) # output file duration dur = 2 NUM = 12 for i in range(NUM): s.boot() note = 60 + i noteFreq = midiToHz(note) s.recordOptions(dur=dur+.1, filename=os.path.join(output_folder, "file_%02d.wav" % note), fileformat=0, sampletype=0) ### processing goes here ### env = Adsr(attack=0.005, decay=0.15, sustain=0.7, release=1.7, dur=dur).play() qenv = Pow(env, 4, mul=0.8) osc1 = SineLoop(freq=noteFreq, feedback=0.075, mul=qenv).out() osc2 = SineLoop(freq=noteFreq*1.01, feedback=0.075, mul=qenv).out(1) # start th render s.start() # cleanup s.shutdown() print "Batch processing done" pyo/examples/utilities/01_get_example.py0000644000175000017500000000103112652732202017646 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ The PyoObject.get() method can be used to convert audio stream to usable python data. """ from pyo import * s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot() lfos = Sine(freq=[.1,.2,.4,.3], mul=100, add=500) synth = SineLoop(freq=lfos, feedback=.07, mul=.05).out() def print_val(): # Print all four frequency values assigned to SineLoop's freq argument print "%.2f, %.2f, %.2f, %.2f" % tuple(lfos.get(all=True)) pat = Pattern(print_val, .25).play() s.gui(locals())pyo/examples/utilities/02_midi_ctl_scan.py0000644000175000017500000000120112652732202020144 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Scan for Midi controller numbers. Launch this script from a terminal. """ from pyo import * import time pm_list_devices() num = input("Enter your Midi interface number : ") s = Server(duplex=0) s.setMidiInputDevice(num) s.boot().start() print "Play with your Midi controllers..." def pp(x): print "controller number =", x scan = CtlScan(pp, False) again = "y" while again == "y": time.sleep(10) scan.stop() again = raw_input("Do you want to continue ? (y/n) : ") if again == "y": print "Continue..." scan.play() s.stop() time.sleep(1) exit() pyo/examples/utilities/02_osc_scan.py0000644000175000017500000000125412652732202017154 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Scan Open Sound Control inputs. Launch this script from a terminal. """ from pyo import * import time port = input("Enter the incoming port number : ") s = Server().boot().start() print "Play with your OSC interface..." go = True def pp(address, *args): if go: print "Address =", address print "Values =", args print "---------------" scan = OscDataReceive(port, "*", pp) again = "y" while again == "y": time.sleep(10) go = False again = raw_input("Do you want to continue ? (y/n) : ") if again == "y": print "Continue..." go = True s.stop() time.sleep(1) exit() pyo/examples/utilities/04_batch_processing.py0000644000175000017500000000276612652732202020714 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ This script demonstrates how to use pyo to do offline batch processing. """ from pyo import * import os s = Server(audio="offline") # path to your sound folder folder_path = SNDS_PATH # path to the processed sounds folder (user's home directory/batch) output_folder = os.path.join(os.path.expanduser("~"), "pyo_batch_fx") # create it if it does not exist if not os.path.isdir(output_folder): os.mkdir(output_folder) # get the list of files to process sounds = [file for file in os.listdir(folder_path) if sndinfo(os.path.join(folder_path, file)) != None] # enter the batch processing loop for sound in sounds: # retrieve info about the sound path = os.path.join(folder_path, sound) info = sndinfo(path) dur, sr, chnls = info[1], info[2], info[3] fformat = ['WAVE', 'AIFF', 'AU', 'RAW', 'SD2', 'FLAC', 'CAF', 'OGG'].index(info[4]) samptype = ['16 bit int', '24 bit int', '32 bit int', '32 bit float', '64 bits float', 'U-Law encoded', 'A-Law encoded'].index(info[5]) # set server parameters s.setSamplingRate(sr) s.setNchnls(chnls) s.boot() s.recordOptions(dur=dur, filename=os.path.join(output_folder, sound), fileformat=fformat, sampletype=samptype) # processing sf = SfPlayer(path) bp = ButBP(sf, 1000, 2) dt = Disto(bp, drive=0.9, slope=0.8) mx = Interp(sf, dt, interp=0.5, mul=0.5).out() # start the render s.start() # cleanup s.shutdown() pyo/examples/utilities/07_scope.py0000644000175000017500000000133212652732202016477 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Simple scope example. """ from pyo import * class Scope: def __init__(self, input, length=0.05): self.input = input self.table = NewTable(length=length, chnls=len(input)) self.table.view(title="Signal Scope") self.trig = Metro(time=length).play() self.rec = TrigTableRec(self.input, self.trig, self.table) self.trf = TrigFunc(self.trig, function=self.update) def start(self, x): if x: self.trig.play() else: self.trig.stop() def update(self): self.table.refreshView() s = Server(duplex=1).boot() CHNLS = 2 LENGTH = 0.05 inp = Input(chnl=range(CHNLS)) scope = Scope(inp, LENGTH) s.gui(locals()) pyo/examples/utilities/play_snd.py0000644000175000017500000000034612652732202016675 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Simple soundfile player used by 06_separated_threads.py example. """ from pyo import * s = Server(duplex=0).boot() sf = SfPlayer('../snds/snd_1.aif') sf2 = sf.mix(2).out() s.start() pyo/examples/sampling/0000755000175000017500000000000012652732202014306 5ustar tiagotiagopyo/examples/sampling/01_sound_cloud.py0000644000175000017500000000147212652732202017502 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Exponential cloud of sounds... """ from pyo import * s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot() snds = ['../snds/snd_%d.aif' % i for i in range(1,7)] num = len(snds) olaps = 4 tabs = [] trtabs = [] trrnds = [] lfo = Expseg([(0,0),(20,100)], loop=True, exp=5).play() cl = Cloud(density=lfo, poly=num*olaps).play() for i in range(num): tabs.append(SndTable(snds[i])) for j in range(olaps): offset = j * num for i in range(num): index = i + offset trrnds.append(TrigChoice(cl[index], choice=[.5,.75,1,1.25,1.5,2])) trtabs.append(TrigEnv(cl[index], table=tabs[i], dur=1./tabs[i].getRate()*trrnds[index], interp=4)) mix = Mix(trtabs, voices=2) out = Freeverb(mix, size=.9, damp=.95, bal=.1, mul=.3).out() s.gui(locals())pyo/examples/sampling/04_live_convolution.py0000644000175000017500000000227712652732202020571 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Live convolution example. A white noise is filtered by four impulses taken from the input mic. Call r1.play(), r2.play(), r3.play(), r4.play() while making some noise in the mic to fill the impulse response tables. The slider handles the morphing between the four impulses. Call t1.view(), t2.view(), t3.view(), t4.view() to view impulse response tables. Circular convolution is very expensive, so keep TLEN (in samples) small. """ from pyo import * s = Server(sr=44100, nchnls=2, buffersize=512, duplex=1).boot() sf = Noise(.5) TLEN = 1024 inmic = Input() t1 = NewTable(length=sampsToSec(TLEN), chnls=1) r1 = TableRec(inmic, table=t1, fadetime=.001) t2 = NewTable(length=sampsToSec(TLEN), chnls=1) r2 = TableRec(inmic, table=t2, fadetime=.001) t3 = NewTable(length=sampsToSec(TLEN), chnls=1) r3 = TableRec(inmic, table=t3, fadetime=.001) t4 = NewTable(length=sampsToSec(TLEN), chnls=1) r4 = TableRec(inmic, table=t4, fadetime=.001) pha = Sig(0) pha.ctrl(title="Impulse responses morphing") t = NewTable(length=sampsToSec(TLEN), chnls=1) m = TableMorph(pha, t, [t1,t2,t3,t4]) a = Convolve(sf, table=t, size=t.getSize(), mul=.1).mix(2).out() s.gui(locals())pyo/examples/sampling/03_rec_and_loop.py0000644000175000017500000000116712652732202017613 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ This script records any number of buffers and loop them. Call r.play() (as many times as you want) to record a buffer from the input mic. """ from pyo import * s = Server(sr=44100, nchnls=2, buffersize=512, duplex=1).boot() buffer_length = 1 # seconds objs = [] def cp(): t2 = t.copy() f = Fader(fadein=1, mul=0.5).play() pl = Osc(t2, freq=1./buffer_length, interp=4, mul=f).out() objs.extend([t2, f, pl]) mic = Input([0,1]) t = NewTable(length=buffer_length, chnls=2) r = TableRec(mic, table=t, fadetime=0.1) tr = TrigFunc(r["trig"], function=cp) s.gui(locals())pyo/examples/sampling/02_live_looper.py0000644000175000017500000000166712652732202017512 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ To record sound from input mic in the buffer (4 seconds), call: rec.play() The buffer is looped with some funny parameters... """ from pyo import * s = Server(sr=44100, nchnls=2, buffersize=512, duplex=1).boot() tab = NewTable(4) rec = TableRec(Input(), tab) pit = Choice(choice=[.5,.5,.75,.75,1,1,1.25,1.5], freq=[3,4]) start = Phasor(freq=.025, mul=tab.getDur()-.5) dur = Choice(choice=[.0625,.125,.125,.125,.25,.25,.5], freq=4) a = Looper( table=tab, # table to loop in pitch=pit, # transposition start=start, # loop start position dur=dur, # loop duration xfade=20, # crossfade duration in % mode=1, # looping mode xfadeshape=0, # crossfade shape startfromloop=False, # first start position, False means from beginning of the table interp=4 # interpolation method ).out() s.gui(locals())pyo/examples/effects/0000755000175000017500000000000012652732202014113 5ustar tiagotiagopyo/examples/effects/08_vocoder_main.py0000644000175000017500000000063712652732202017447 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Main script using hand-written vocoder (defined in vocoder_lib.py). """ from pyo import * from vocoder_lib import MyVocoder s = Server(sr=44100, nchnls=2, duplex=0).boot() a = SfPlayer('../snds/baseballmajeur_m.aif', loop=True) b = PinkNoise(.1) voc = MyVocoder(in1=a, in2=b, base=70, spread=[1.49,1.5], q=10, num=8).out() voc.ctrl() s.gui(locals()) pyo/examples/effects/02_chorus.py0000644000175000017500000000144712652732202016277 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Hand-written 8 delay lines chorus. """ from pyo import * s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot() #--> Start a sound sf = SfPlayer('../snds/baseballmajeur_m.aif', speed=1, loop=True, mul=.3) sf2 = sf.mix(2).out() #<-- #--> Sets values for 8 delay lines # delay line frequencies freqs = [.254, .465, .657, .879, 1.23, 1.342, 1.654, 1.879] # delay line center delays cdelay = [.0087, .0102, .0111, .01254, .0134, .01501, .01707, .0178] # delay line delay amplitudes adelay = [.001, .0012, .0013, .0014, .0015, .0016, .002, .0023] # modulation depth depth = Sig(1) #<-- #--> Add the delay lines to the source sound lfos = Sine(freqs, mul=adelay*depth, add=cdelay) delays = Delay(sf, lfos, feedback=.5, mul=.5).out() #<-- s.gui(locals()) pyo/examples/effects/vocoder_lib.py0000644000175000017500000002341712652732202016763 0ustar tiagotiago""" Hand-written Vocoder class. This is an example on how to write a class acting the same way as any other builtin PyoObjects. """ from pyo import * class MyVocoder(PyoObject): """ Vocoder effect. A vocoder is an analysis/synthesis system. In the encoder, the input is passed through a multiband filter, each band is passed through an envelope follower, and the control signals from the envelope followers are communicated to the decoder. The decoder applies these (amplitude) control signals to corresponding filters in the (re)synthesizer. Parent class: PyoObject Parameters: in1 : PyoObject Audio source generating the spectral envelope. in2 : PyoObject Audio source exciting the bank of filters. base : float or PyoObject, optional Base frequency used to compute filter notch frequencies. Defaults to 50. spread : float or PyoObject, optional Spreading of the filter notch frequencies. Defaults to 1.5. q : float or PyoObject, optional Q (inverse of the bandwidth) of the filters. Defaults to 5. num : int, optional Number of bands (filter notches) of the vocoder. Available only at initialization. Defaults to 20. Methods: setIn1(x) : Replace the `in1` attribute. setIn2(x) : Replace the `in2` attribute. setBase(x) : Replace the `base` attribute. setSpread(x) : Replace the `spread` attribute. setQ(x) : Replace the `q` attribute. Attributes: in1 : PyoObject. Audio source generating the spectral envelope. in2 : PyoObject. Audio source exciting the bank of filters. base : float or PyoObject, Base frequency. spread : float or PyoObject, Spreading of the filter notch frequencies. q : float or PyoObject, Q of the filters. See also: BandSplit, Phaser Examples: >>> s = Server().boot() >>> s.start() >>> a = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True) >>> b = PinkNoise(.1) >>> lfo = Sine(freq=.05, mul=50, add=100) >>> voc = MyVocoder(in1=a, in2=b, num=12, base=lfo, spread=[1.2,1.22]).out() """ def __init__(self, in1, in2, base=50, spread=1.5, q=5, num=20, mul=1, add=0): PyoObject.__init__(self) # keep references of all raw arguments self._in1 = in1 self._in2 = in2 self._base = base self._spread = spread self._q = q self._num = num self._mul = mul self._add = add # list of filter's notch frequencies self._partials = [i+1 for i in range(self._num)] # Using InputFader for sound input allows crossfades when changing sources self._in1_fader = InputFader(in1) self._in2_fader = InputFader(in2) # Convert all arguments to lists for "list expansion" # convertArgsToLists function returns variables in argument as lists + maximum list size in1_fader, in2_fader, base, spread, q, mul, add, lmax = convertArgsToLists(self._in1_fader, self._in2_fader, base, spread, q, mul, add) # Init some lists to keep track of created objects self._pows = [] self._bases = [] self._freqs = [] self._srcs = [] self._amps = [] self._excs = [] self._outs = [] # self._base_objs is the audio output seen by the outside world! # .play(), .out(), .stop() and .mix() methods act on this list # "mul" and "add" attributes are also applied on this list's objects self._base_objs = [] # Each cycle of the loop creates a mono stream of sound for i in range(lmax): self._pows.append(Pow(self._partials, wrap(spread,i))) self._bases.append(Sig(wrap(base,i))) self._freqs.append(Clip(self._pows[-1] * self._bases[-1], 20, 20000)) self._srcs.append(Biquadx(wrap(in1_fader,i), freq=self._freqs[-1], q=wrap(q,i), type=2, stages=2)) self._amps.append(Follower(self._srcs[-1], freq=20, mul=wrap(q,i)*10)) self._excs.append(Biquadx(wrap(in2_fader,i), freq=self._freqs[-1], q=wrap(q,i), type=2, stages=2, mul=self._amps[-1])) # Here we mix in mono all sub streams created by "num" bands of vocoder self._outs.append(Mix(input=self._excs[-1], voices=1, mul=wrap(mul,i), add=wrap(add,i))) # getBaseObjects() method returns the list of Object_Base, needed in the self._base_objs list self._base_objs.extend(self._outs[-1].getBaseObjects()) def __dir__(self): return ["in1", "in2", "base", "spread", "q", "mul", "add"] def play(self, dur=0, delay=0): dur, delay, lmax = convertArgsToLists(dur, delay) [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._pows)] [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._bases)] [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._freqs)] [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._srcs)] [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._amps)] [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._excs)] [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._outs)] self._base_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)] return self def stop(self): [obj.stop() for obj in self._pows] [obj.stop() for obj in self._bases] [obj.stop() for obj in self._freqs] [obj.stop() for obj in self._srcs] [obj.stop() for obj in self._amps] [obj.stop() for obj in self._excs] [obj.stop() for obj in self._outs] [obj.stop() for obj in self._base_objs] return self def out(self, chnl=0, inc=1, dur=0, delay=0): dur, delay, lmax = convertArgsToLists(dur, delay) [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._pows)] [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._bases)] [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._freqs)] [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._srcs)] [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._amps)] [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._excs)] [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._outs)] if type(chnl) == ListType: self._base_objs = [obj.out(wrap(chnl,i), wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)] else: if chnl < 0: self._base_objs = [obj.out(i*inc, wrap(dur,i), wrap(delay,i)) \ for i, obj in enumerate(random.sample(self._base_objs, len(self._base_objs)))] else: self._base_objs = [obj.out(chnl+i*inc, wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)] return self def setIn1(self, x, fadetime=0.05): """ Replace the `in1` attribute. Parameters: x : PyoObject New signal to process. fadetime : float, optional Crossfade time between old and new input. Defaults to 0.05. """ self._in1 = x self._in1_fader.setInput(x, fadetime) def setIn2(self, x, fadetime=0.05): """ Replace the `in2` attribute. Parameters: x : PyoObject New signal to process. fadetime : float, optional Crossfade time between old and new input. Defaults to 0.05. """ self._in2 = x self._in2_fader.setInput(x, fadetime) def setBase(self, x): """ Replace the `base` attribute. Parameters: x : float or PyoObject New `base` attribute. """ self._base = x x, lmax = convertArgsToLists(x) [obj.setValue(wrap(x,i)) for i, obj in enumerate(self._bases)] def setSpread(self, x): """ Replace the `spread` attribute. Parameters: x : float or PyoObject New `spread` attribute. """ self._spread = x x, lmax = convertArgsToLists(x) [obj.setExponent(wrap(x,i)) for i, obj in enumerate(self._pows)] def setQ(self, x): """ Replace the `q` attribute. Parameters: x : float or PyoObject New `q` attribute. """ self._q = x x, lmax = convertArgsToLists(x) [obj.setMul(wrap(x,i)*30) for i, obj in enumerate(self._amps)] [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._srcs)] [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._excs)] def ctrl(self, map_list=None, title=None, wxnoserver=False): # Define the object's default map_list used if None is passed to PyoObject # map_list is a list of SLMap objects defined for each available attribute # in the controller window self._map_list = [SLMap(20., 250., "lin", "base", self._base), SLMap(0.5, 2., "lin", "spread", self._spread), SLMap(1., 50., "log", "q", self._q), SLMapMul(self._mul)] PyoObject.ctrl(self, map_list, title, wxnoserver) @property def in1(self): return self._in1 @in1.setter def in1(self, x): self.setIn1(x) @property def in2(self): return self._in2 @in2.setter def in2(self, x): self.setIn2(x) @property def base(self): return self._base @base.setter def base(self, x): self.setBase(x) @property def spread(self): return self._spread @spread.setter def spread(self, x): self.setSpread(x) @property def q(self): return self._q @q.setter def q(self, x): self.setQ(x) pyo/examples/effects/06_simple_reverb.py0000644000175000017500000000120412652732202017625 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Simple reverb based on Schroeder algorithm. 4 serial allpass filters --> 4 parallel lowpass filters. """ from pyo import * s = Server(duplex=0).boot() a = SfPlayer("../snds/flute.aif", loop=True, mul=0.25).mix(2).out() b1 = Allpass(a, delay=[.0204,.02011], feedback=0.35) b2 = Allpass(b1, delay=[.06653,.06641], feedback=0.41) b3 = Allpass(b2, delay=[.035007,.03504], feedback=0.5) b4 = Allpass(b3, delay=[.023021 ,.022987], feedback=0.65) c1 = Tone(b1, 5000, mul=0.2).out() c2 = Tone(b2, 3000, mul=0.2).out() c3 = Tone(b3, 1500, mul=0.2).out() c4 = Tone(b4, 500, mul=0.2).out() s.gui(locals())pyo/examples/effects/03_detuned_waveguides.py0000644000175000017500000000100112652732202020632 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Detuned waveguide bank. """ from pyo import * import random s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot() src = SfPlayer("../snds/ounkmaster.aif", loop=True, mul=.1) lf = Sine(freq=[random.uniform(.005, .015) for i in range(8)], mul=[.02,.04,.06,.08,.1,.12,.14,.16], add=[50,100,150,200,250,300,350,400]) lf2 = Sine(.005, mul=.2, add=.7) det_wg = AllpassWG(src, freq=lf, feed=.999, detune=lf2, mul=.25).out() s.gui(locals()) pyo/examples/effects/01_flanger.py0000644000175000017500000000046312652732202016406 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Simple flanger. """ from pyo import * s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot() #--> src = BrownNoise(.1).mix(2).out() #<-- #--> lf = Sine(freq=.2, mul=.0045, add=.005) flg = Delay(src, delay=lf, feedback=.25).out() #<-- s.gui(locals())pyo/examples/effects/07_simple_reverb2.py0000644000175000017500000000130112652732202017706 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Simple reverb based on Schroeder algorithm. 4 parallel comb filters --> 2 serial allpass filters. """ from pyo import * s = Server(duplex=0).boot() a = SfPlayer("../snds/flute.aif", loop=True, mul=0.3).mix(2).out() comb1 = Delay(a, delay=[0.0297,0.0277], feedback=0.65) comb2 = Delay(a, delay=[0.0371,0.0393], feedback=0.51) comb3 = Delay(a, delay=[0.0411,0.0409], feedback=0.5) comb4 = Delay(a, delay=[0.0137,0.0155], feedback=0.73) combsum = a + comb1 + comb2 + comb3 + comb4 all1 = Allpass(combsum, delay=[.005,.00507], feedback=0.75) all2 = Allpass(all1, delay=[.0117,.0123], feedback=0.61) lowp = Tone(all2, freq=3500, mul=.2).out() s.gui(locals())pyo/examples/effects/04_harmonizer.py0000644000175000017500000000074012652732202017147 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Hand-written harmonizer. """ from pyo import * s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot() sf = SfPlayer('../snds/flute.aif', speed=1, loop=True, mul=.5).out() env = WinTable(7) wsize = .1 trans = -7 ratio = pow(2., trans/12.) rate = -(ratio-1) / wsize ind = Phasor(freq=rate, phase=[0,0.5]) win = Pointer(table=env, index=ind, mul=.7) snd = Delay(sf, delay=ind*wsize, mul=win).mix(1).out(1) s.gui(locals()) pyo/examples/effects/05_fuzz_disto.py0000644000175000017500000000173212652732202017174 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Fuzz distortion. High gain followed by, asymmetrical clipping, hard clip on top, soft compression on bottom. """ from pyo import * s = Server(duplex=0).boot() SOURCE = "../snds/flute.aif" BP_CENTER_FREQ = 250 BP_Q = 2 BOOST = 25 LP_CUTOFF_FREQ = 3500 BALANCE = 1 src = SfPlayer(SOURCE, loop=True).mix(2) # Transfert function for signal lower than 0 table = ExpTable([(0,-.25),(4096,0),(8192,0)], exp=10) table.view() # Transfert function for signal higher than 0 high_table = CosTable([(0,0),(4096,0),(4598,1),(8192,1)]) table.add(high_table) # Bandpass filter and boost gain applied on input signal bp = Biquad(src, freq=BP_CENTER_FREQ, q=BP_Q, type=2) boost = Sig(bp, mul=BOOST) # Apply transfert function sig = Lookup(table, boost) # Lowpass filter on distorted signal lp = Tone(sig, freq=LP_CUTOFF_FREQ, mul=.7) # Balance between dry and wet signals out = Interp(src, lp, interp=BALANCE).out() sc = Scope(out) s.gui(locals())pyo/examples/snds/0000755000175000017500000000000012652732202013443 5ustar tiagotiagopyo/examples/snds/snd_1.aif0000644000175000017500000004441612652732202015141 0ustar tiagotiagoFORMIAIFFCOMM$l@DSSNDH          " |re^TO>:)wk^RJ8$mibH=:. vo`YL;8%%~l`d]Q<72(ol[MNO?71/}vdOAA60%&#8D>EPd}0e V+l@-3y-w-N q5GV  j  t  i  ^ ] O=_9Y}')-}d<r>p4 G b  L 9 e $Lo)1Og6V!qJ5a ^97};Hk`1z;|lZ?,,1'-<>>Nkpqu|  2BJ2+HE0%4%  byPGA3f%kZC&XYy!{9m6KH&luXqtx {k '@/-#\i[ )   { = JHM"g({ae8e#"3avgT3W)G^.2?< &   }  h2f>| gm-DYrL&"QkI9* IeH|U14n(V,BQ 7 r )s~J] !!"#$%v&8&'()@)* *+/+j+++,, ,+++++++n***b))L((*'&%$$ #N"  {E)/ f F < 1mG5ct;tPi-cmgI78ۅ8، ~+յcpӜ,]ѬNШp9ϖc7$λαααΡΊ~ΣΣΠκ]υϪ=zЦ-ї҈Գv>%=B+%ߜ^: 4_`  @ i u d j !!S!"""#7#p#$$$#$###q#g#j#\#S#e#r#t#]#N#;# ""v"'!!!3 3\S K|!l<X4Qm  Z p=^nN0](Dm [ #tL\XRNJDSSq4Wn0K%/8fB   m)d+>s N!"#$%j&f'B'(o)E)*++,5,----..1.8.----y-,,,b+++!*))s(( 'Y&%$$$#)"L! 4>I+eP-n \  l"|'X$gIVi<  yܓۘ<ىAל-օCԽӈҐѓ'ЖOω@ΝZ,͸͚ͬͬͫͥͫ͜ͱKΥ zapҼt"|O()L!Sw-Y%Ez $88-8*,`r$' 2vJ E !!n""l"# #|##$<$Q$h$$$$$$$$$$~$p$[$=$$####M# """"!!f kSkp#390r4|# ` SvB ZcDCs3.2uTI'*!:|,D34AmxXo l\ZQ= 8 )    m/ zuS(|_ !W!"|#3#$($%%Z%%& &-&h&&&&&&&''' '&&&l&%%3$$## "j!!. 5mJg!92B< t EfMJ1 2jKM@ޤ+ܐ1ڑIزRfֶRՏ7Ԓ<ө_ ҄3Ѹѐd8ІJϫϒϓφϜϢϭϼ 1T~иLѦ ҇s֡dچL޳ߗn2Ev,fl_JOLWoie f { { f ]FQ.3'-ME  ` !!;!Z!m!}!!!!!!!!!u![!E!% W `~,+j`> ZA @  DpldbLE)0lj@tZH).Cg._rt(!:& L0 - t  Z 1^I,v c#:F'UD]   >W)2IC<Z` 8s 8 R v '3aK~:VgP[ D6Yy&aV+4^ދ2|,܈?ۥYڎ?|6؍c-ײכVH#ֺ֑փi>:81/2JNXz֦%t'؆} ځۭEy-ߔIAy\B(% * (#uU/kjX4 ] m!Ai*V$6z3E}-d<=lojkhXAyNup"^b3s)5=?Ikp j  - 2 HTSq#?qG= _@_E.!  HL`{7_qFu0*n%S3XEL<W  u g p d rhnrKP {7\`=MrJ?'2i y Lo"0 v \ " 98G@NnuEU{(f$f2 5Ss3q%r"FnD wP qWL3zx|Tly##1Z3dO6aE/7P^_G,hw"X<$\M}-o w  `   i  O -p-q$Y}4q3CH5{}yOE)dc<j)dg t = " * a&c P9eRoAULw-P#@pgWZH?!<=ZK^T5yyre> 0 JD[O-=IKJy:~,zx:79;:979<9==m=== =:r6 321k,'%$! E og0=\ y#k)ZDk;Q)$m݄7u:ܝUah-6OxJ #w:= Q!^K #$<'d- .2,/4[3p0E2433+5y7@41478o78;>3<9888a740,5,/,(L(V+{+O)3*:*'P%& % N&$k,0KzG m&bX^B6"w(i)|(f)++m)m((s)2()i*E+q-b.q./1M22r3<4655%4>433Q20/0/_-+))(%##\#""!B!s P Mb`iGogKauYs5`llϛgBX#Mʢrȼu~ijũ BEt=d̨AʙuʱT;ƂUbN(úCJQʈџv"yLφ*ǒkbȗG_TlN :tg/!#]#(z/34B48;;*;7|32310I++/3%4%7 23c*1Tw\YJGprABfڏ)޲ߠGeseB}-C  +[ 3!#%(,M-?,-0-)*.o-f,`0"4666e45G75/++-*&q$(*+'p$&'&$D! !!oZ R z  , K  i f("&(%),/[2 212 3333x1121021`45K32563111F.0,,_,++,h+ ( &$O{q }HYjuF?SF۷K=7u̗~k.;ZƉs/*ŷ?Ƞwz*=8twǵƟBPФpԨӕ͖7Υƒ7˱ɻlj˙HɟUǽâϼ8Ίηȯ+^NŨ#ϝ݄FpA 6 Km!$)I,/21-/0207+*/@0.0o6;':U9;m:m631,s)*(# H"%j!Uy} * E^2qzGFm/ab Z68܁ة=ܝ7v s] ( @R$m !` #'Y)I'%&),*t(<'+..t-/ 120-%,++a)2&$&'&$%%y$#"p  2[S:* p ; "Kh t X,N 7&Gg=<#l%')-/.,,,,r+++-c.I..1F3q3024c6E4s1/170b-Q+*++)((&$!g%qB_ }j7.* Hהa0̒fpʒ%ˈVʩd` ĉ_ƛ8f´Ā^˳Ɯ'K3dž_Ǣ*Nƚ<#ŽI˾Cdw7+˟kHjijj[Ogϛ5ەw0nd/FI -|! $)-p.Z-. .-+()+.!/j37::8873.F+*(9%<#"!Z \ |_i; |cf-"!I~r.1ޗۆJ~ۇxZ:4TWP~^Nfv &gSB`#&)%=#%()(),/[/.K-,+*,(((.''&&(;)n'%|%9&H$"M!#G}$7E02 ` 8b z V 2 I"Vr#b  5CWw=O"%Q%&-(E*+l**,u--,,e,-U,-/1F113432181O0k.3-n-,+|**)#&$" g<h?)?/ x B~6#!R(Pڂ؊mպӦӘhTa>͵d(ɑȜ˳uʧ B˭ ejɜ1.=͸Ό ;@Ȳa_S{׿ȿտfoO1 $]\®ȷ̚˯Ƚʋ\Jyãʈz+UXo'iJ| &jh'#?%'*e-//T..0b0--P.A/1(3 5899986;3T/,)q&$!  2Q _lXx&zK vLݗލߨ_vIPfjpR G}mDS"$'*)*1*.,P.-P+-a/.-/0/ /a//..++-I,)((&&'&]%`$&&" @0w[b .,|*J 3s  c 3 Q-Q\rl:"z%')+T--m,+++_*)*&*Z*+,. /0\01^130.T-%,+)'&%$###K!q"[} }c0;xt\ޟ;rmԵl3҄з sJ̺|΁]ˉy ǁ5ǍD <ͮ͟a̷: Ǐ³ŬQœnȉ(8ŽA$8s>bi(œj̖/g,,xoǂ{}%/ݬ,Gs(6=,5i O Y<e% #d%t*@-5.3/,021/01/..030^03Q43366j2p00.u)%#$ HpLhG/ ,Q ( c_bsDq'}6A"gyCн<d@ڨ2X>eZv?)$p knq!$"$&)++,P,,,|+))+~++-0U222V3B31.,,)&n$g" h}!OW @Z"wwJ%3,RGlA S #HY!MT ~fyCoU"""%0())'`&'(''g))'()) ''''J' %$#!!!! !Q""!Itxs,D$ &-T{ ;~k"JoX1<"#"#s%q$#"##! !!!""" "_#I"! @  bGp>R Ua"F '^xgXhހ_<ևrѾҞF&ѡϻΛ <ȓ8 gTDɊdzdʲ}ɑ&ƬljǵŤl^əbȋ̾fŴXÖX7 @ȍsNVˣп˒JGY!e,P{Sa&4 4 f ! w0P !#d%t'(g'%{'s+)$%$&*9.1,+.x000/--J.",)(]))%E"&#%!8b]?3hY u|["m?'d34D#QG\n<1^JK4T*{ f =6%ZaR!!Y "& 'c'A'('Z'R((()(%#$8%%u#|#Y%&%&&;$####E!?</WG*g# CPy9?t^1-*sq[JG4;^S `Ef16Gq_h_ b a p9<jM)/ hh bI&r&hݾہvKԑbV- dcπ6gΊ2@vˌˈͣ.̃E+Wɫ7S^%hĬ³Dke9RĮvͯρϘ͠aВ y{pعَ?mLMU1 (6~ "%R'A&&&&K%%&\&%&''&O&V%"!Y!!(&RF3XZ0 l v HHF':U B]A`Bc^MbY83 c ?8 & vX" 9p!# R!I$#!} !o""z ""##"x"$+#o!!O"  Hy{ D;_Z; o  \  % v ]  4 u r N   a [  # V S o m P S }Z% a  3Ie$d[FcdRAaF=PE%kvu!s*hV1&ۑ)G7jN;׉^ئֵԍԤ֞ױըpպպӦgGמ:h;֐2ӌQ^օ֒ܠۮRpފA$|v*Cn**",WYU7hhj%    D  / 5#6 'On"%n^Wl L ( 3  !5#\G2%K)FH>eR= "  E [ $ z  k X   e   l Hl k  R i  P F , s U U h _  ! Z o ,-1a l9m/ fc v  {   q N  &  4 ! V ( 9 7 4/^:Az  'Y !{?h"Kcao/ZWfyZHN{]5%D;A@+.%:Tk{$T0P7h"4>h|}w]KE) c2xUx`; u]N3'! -31?FJMfs#<](Lr+?j"_ [@Gr#Ir6`2h'Rm#Ln8Sk,&BQXYr~qrdaKK;tpUM(Z5k3 xgW4eJ%{jlA0# }_@<,04#%!(:GNbn{%7Phj  # x_D1xV;{Q4{iG(qcA' 4Un &@Pe(=?:;=5@0BFFGA;;;:=28:=GITT_]eepp     ).@JX_gw    }ri_QH=6-%||x{ !"))1/2.459:7<7=;A7::=>==;=89713,1-.+/(+%(#$                pyo/examples/snds/snd_3.aif0000644000175000017500000005351612652732202015144 0ustar tiagotiagoFORMWFAIFFCOMM+@DSSNDW   #%+)45=;FEGIONRWadknvnrwtnsurxz    "*4/57976=8?AW`rwpaUL;4!(""%.-79DCFQSPPGOCG<>91,${^OB9.}lO3!' W /IG>?QRF%p]#&(![5  2~"(AX[rpeRJ+ -'%Lb{}DATu %@W;+oIy1d=KRbierjX&u H'OSSU/ zL kNI4f^QBB5&nK(uWK=2reXYWIS^gTHJWU;   v_HBF$$GRQS]R,}rI@Lghfyw\CFT=-AGBQf CtaG J1X}ooO.0gQR L v c  EZ4-.h<Meo& 'O umGVJjvY:K@;e * % H N6xZ05'c [?%YF0URl78k'2wVAn7P+3`;Vejgo'1`ub(,iR+b7UT/p$J^!Ds߿[+z݂o7+ޟu<"YoR#'tk$]  9  Ax$NyEVo{ p ( !U"Q# #$$$$$$$$3##"" !H rPFk9g3"9}&t$U +  E {  g .W  z ?qX@|Z w  ] l o m 6usD 5J}uAWN1Mx`nS6 s]kxM92 & g  S}T=@AC`x+[ n.Gݭܥۜں iקw^Ԧ5wѰϪJZp [7f*,Kvbަ݀}ێ>ڪKن*ر؜|>d־DՂ)w?#ӵNҥхa6ТϨχ<ΐh!̀R˲Lɑȼ?ǹ Ȉ]ѳ;ձ/j2ޗ߀b_~R=, _Sq )ONwMw & f !3!n!{!""y"#i$ %& &'X())*8*+@+++++v+A*))(V'&%M$"! q% Xr(k"5#]f g a \ 4`\o lG}h`_l0^? K*uod8_){G )d [|#a#ux!MR-H9#@N3a?KYOFx^ F o k y*01v:C "5#%U&(\)k*N+=,,- -]-q-b-O-T-.R//0D01;11282V2`22m2Q21292K2c223-3G3 22v2100/Y.-,++>*)('&%$L#! S u,%0!w; M6z Na}[KH@7.Cg"] "(C~%،_ֻ2՗/pӼFҦ ѠKУMϸϕς}τvσyu\cf`)Βi"|̮̋^Jt̐z\0@ʅ(ɼx'YD}"ɯr\˘˱JEԎE ߒ]&LB NAC# | UAvob ~!W!"S# ###$e$$6####$$X$%%%&s''())j**+++g+,,++**!)8("&%U#" 2 ;BHv>|D^V & PNpt x43[n|T^*tv(; I(FjrVIRk]"QEo p y  c&.!lhftl% G !"$&E')+k,-h-.Q....`.0. ---./01{2g3#34434333f3*3223:3334 4F43|22 0/u.--#,R+Z*C)f(}'&%$#"!\R8 c@ T ||b<&-:;x9wujb݆J2gڦ ?҂рC Ч^aЃ:϶@.ήΓζlΡ3xc~ϐ2Χh 8΄5Ϫ-@ϲ2΍͐sˀ9=8 B˸&8\̿H͹ΨH F׌,Hr^0 S7&0]L-   Q!a"X# #,"""""""""""""""u"s"##d##$%&I&'()P)**+9+**-))G(-&%n$Z#!j{kqE> ?\ k )  5  z GCL >.'dCVWo!TxupV.{<,:|' 8,;cyhl  U 5;drw[!#%z&'():)O)_)a)D)(('''()*,E-N. ./B/000)0i00001u12z23F333K211 0/ .--g,+*)((''M&%% #"h! IHy' 1` s 6wݏ)^٤ؼח֬HӟOH Y<)ѵюђцЕcYgк:ѣ\Я?@Ε,G\jPhrCh8?Ϭ?X2ϱm3^ ͻ͎4̓ά8ҊYԅ׹E rzi xAmG+> f!$')+.H/01235 44t44332180o/.-,z+*)('''&i&]&&%$$2#"!0 !6Ym qj91P  \ : )   F j e g  ? V J T c O3mX/7b:h=ADLEEFEC AV>=I0O]7#!vU$CjHXq^"`r%ߋDްuz5!ۭ3vؕ.fحk)0҄ԭgܓޏ^k n5xMͣ˘ɮu.ȘȿŖ\,átp̀yخݫ& 8-x8"" u!5!S2Y SSXOZ2iDxt~g} ?n?z m 14[= 9a g 9#i4#iIa*Lhu|+waeQ)lo* 3 y  [ / n v j Z ) 3(2l  $ g  v |   c E 2 k  X ,  5 M(&T;>$)-P/26/88j6p5}4o2/,*(&+#V!\Ev(m$a" N:*+# } " jb2"   s xI,yH7 S Q^2hs>Ri^/!@ ySWaz{G]iܤyڒښdVN /PbEE5jOJ;/5V{ٴ,9նӨ3C ѐ`7ԡdJ@"A0ƫEe!ςֽ. :"& #!`V { iU5HGaUot.Qq.a  (oJ+884 9B}<^\hWVc Otz / G'O{: * y o j  } I 2 !Y [7sd  d  T J 6 /- r76 $n }N+ !p> u#('-c256+8-:697420.'*(& #C %-FUN5PrJpPnYB Y zL9a + Hrb9VH ](l0V zQb,M}2^pDu ;O#(_KhW".v `>ߙ./۳ܘډG2ڱYۣj7y6~OݙuMwݼkIܸvT!؁L(բMU Le6ˤƂȽe4`o1% 'E,.U,+,3+( # Ah cqz8J5b*u-X0 A|EG) `QwJ h"A#@#=#[##!wP- R gg]QE\ 4 h Y  r + O|E~ V \  @ } a " ] ] 1 ? U < q l n_2ax5 P 3 P YSn@5Z~ @   &  b `  ` T; hx5j o$'+/2s46t66w5427/x,_)'%R"}3;w!8+F>P#2fOx C O t6QN Cd p # _b3DvKRqJm9"7' ,xIKkG K .34߾` I{B;=ܐ3SWzWb5AdgھנyҙvΧͽ`˔S6G}ŪuqMӶ}۵Wa  M $Q'](|(?(%&"F .nZXM^AyWX^Z{[i 5 Q$6 Op d2UG -(3L{d5^ P ; t 0 > m A a lvRZqs<   & (   T I    . wA 8 7  mJ 9  H O f  f }=e%!T%*/i2v4=68x8631I.{+~'$#7 ? 6 lj  :7]A^-}$ #%c } y{4"joY '/9.hTm _Wj%SzIJNpT` a e;-I$n*2 %mkۚݖۂܸ$K&*JKpN>+Gd 9?;  Q ! (  1 B 3 _  X  e N ~ N j ` < WTV v b k0+m+1r( y r *ih3 !$3%'*/2X3444 2<0.*&#f   - H p /}XFd^x{- B ; ) P } `=~UE  ( |M$1j;imEIa~Rm?U@tT<DD2>u@_b6ߩA?j]vwh_\ԕԎ!qջZm\'-cPזAix; ߾у7Кlۘ^< | 3z2!OTc  mM{+GzAnVL ;=3AW 9!uR~Zh: T 2yBq240pD$vpvl,V C ? W L \ ,  / M<7!9C\^qHo" #BJAL7iaP 9 R F Q H [  ' }  8 ~E6dFeeeP #&&(o+L-y...-+(%"vam0c ]E{ f  m0g [l3   9  c &FeU.ovmMrp@SME)]y{sdE`J߳߬yJ޷:.vlr׵؟ג[~*ӹֹՑ"0мG~.wƜļĤ|XлՔSޏc5B @\!""#%4%K!q@p $( no#n o} I r R  w N ) i |G(1`2D MC|2  dCOahMIiE z  o05Bt0-(Nzr/%jalZJ | ( (Q7% "  V i > :H>.~v8-}CwKN45^  Gi4j [ I `6'PbRH$Y@ XCT w A  , i4gPG;C" ])XGq974N"|MOn[8Ki]'Kl?g+ 9Sߣܐۻr!ӄ&JүYeԷԦӓѧeяΔ̓Nq oƥǓDA;ռS_X:# # "G#%g%i" e2W g5S6@~{6-}@"  6 k Wq X : -_|~ . cpmFxYO mvA"7%"[ X  jn#S5- ,OcK%Kd {8Fq" < p 6  4-Sr4d#* R   1 W N 4CnnQ'pUM+z10jZSa h x + ' ( | 8 C  Ibn-6D\hU  k`(5&V8*_AI %r} Xf']`q9o.CS(m{orvo B "PڇrT_3ڠl`4'ҮͷB_ɱȃ }5"+ũr̻ϬԈ3 qwK( k:!#X$&&$Q * Q>Vaa&(-!3Xsj _ A  Sj ; ^ rg4\>6 FWC^HS&A $ ~Vys32:(pJjNy M  \  3 i  S  4y0RF ,{; y!zg-~W z ' 6  " s^7&Gl} +}, Km5QM_j3=8 A~U%'B)5bU@g?MbMsL.a29Bܓ۶^$d׶ג׌3!ּpյԦҙЬ ΀@CΗ3VḐ̚и^`xNh 9 H`g){ <ce,tA*SAeywKx * @ ( L O  +E|,F w*}  )g(dz"D,2{vM 'k3C'<izI  JO!hF%'Z    Z+UBct. X i ;  ' 8 C$AT/} ?~aG.09tL e l ' a t TPmr6mx@J g KLjcS42du.(0 Y-v n )@^D.pf}$S>*Ua(*mk )2ܔG_;ݡ܏^1Q!1r'G8hϹφϭ15yd.,83 (#53%8>R0tV )^rLQy<PQ] 4 5TlJ,AQE v & S G c f n\~hKV!XUFGI{OJ9#S\gL8)42>$cmP>4#\:  S j v @ ;jQhc:^AUzrVJe& r x y 0tr+cxOq O/J : j CU9ws(w3\e<.> FNwxA@_5b#!V.6YYdpgboVWkqZl[2Ym^7GJvO"YA :dc~$ f80?~ :8[hݟh3+[)&R wdD1e 4it:9;&N&^ /9Y1 H U M M Q i F J   z m  U;OOK(Z]MjNOyNG5}B+"EUNJOK0dX- w ) n = C q = . _   p M X   d SD; BXIn&/:AFh_R)  . DL{B -mrH6R| KiL0@ w8.jTr o38h;1=7N^i%.^~&bw/,Pv#pl.G?hd :(q1=b\}x 87dOy$<`@z3L8wr!f(^rL2o{*6mL'^nGly 2 QC}S%!FC]o_Z(:{mW&5p  .   " - # r& @ly}j*W    * !ufW;Jp|`HNM4^A !t ,"2"7JVihT7V8zm}3JD"zKrd[MGHDWI}!7TFI' AyH1=WVSi-imX< w;piR[D9XUM-i`bcn@Ejau_C@3(r8B1,X!")^5K! WW6a=Tivr0t1b8V1c`;iv,@a?2e(Jt{pidA'(-*k).\tgWO=9 ~hO/oFo_E$ "-K\l}{k_C!wgX=) rdWI>/Dh}jJ$gM( 2S~%BJJM[`dTV=!{C|4Wq"*+&jdWcg{x_B6%'CXt4Oftqvkldgblku &!"%(% .<M_jx~~sgcTPELJST][chmnmkagdjou~wsusxlobcYVFB51)"!%*.8>EMLRLMHHNPORRU\WVSNIBA@@AFIKLQT]\caecbfae^f]d\^\VV  !)(,97,2D;77HCCMMJNSZMY[b_egeoospxy{}|~}w{yrtkpmihcda__YYVWOVKUFMEHCA>;=:96122,,#)$#! pyo/examples/snds/alum1.wav0000644000175000017500000016247212652732202015215 0ustar tiagotiagoRIFF2WAVEfmt DXdata<(Dr;:;Pgg_.TxRLU-^͞`ϜK}zYSc}VF&h ƌ0sWtчƚ3U.?X?ʞ},3ܶŊt(ͫu+峚=0ĉFE`ۏ[G㷸Ө̤+py}-(߹Q׵K̻ZR½hܘ)ԗ!{ʭV F (k#;2'"+ >!ٓ#o7($#9-P,\(&:2*? =1x5EO%(#E k8Z;Y! &YK:V@Bz<05ˬb,sO M< D (%48,k Q!+! sE'J # , 4&!-7 5/U5wB9%'! H s  & r?$ R $!F18"B#{.X_}eI W-fa;Z4 PmPoaYq]yeAbxKexqf u) X4Ml  , m3@KR h<1q {|R"/ku!2$ ,:`?] v 0ng C:;1Lj޸ F}'p6y } |N;SP U pXUUM flX!+&; (^S/ +c? 'W/2='f%k(LWDx#j,I x&$<.B w[`7}::$'%:$z "*d)oz)] *-7(S5d|X%32'` e Xv e_s i #3NhVI >xx{Y< H%L ` E1K  9%< /O ~ !J lgg F ,r^>S b E N e  /  " ,1t  s 7X  ' = 5 9P Q_ B.   +GU :  Rjx  8! ._x|YDb%US2y/  " ` y  +| D'B k,>F WM l oo;#))' \ M_)Q ` d dw#uJ46GlZgb~jngTK;^0Ul!g Y.I)M%|O*: (]{:u).+ p_; + F ] +s+/n" J2]NS 2 e  &$E*-'wLRt^9!J5  hF i  q ,gj1A, ; * 3+O6h, Ae86= 6+&/j%|BQAP^(1 5   q _= q'5 , D=j  R ! H v   Tq  MT F))  5 : X bgCb-$gd3hKG996;uziC&N{-;>C @8v f]2ahzl N  / dWm$n K.L7G(BZRW.k1/ i yC & TLniC-Q^"=jVS~E} [c4&tA $  myT  i ^  e )  "nC+ ; 0w^^|~O K*iq 7 `w  } |   G " V i (;K*l/^VQ2]%QWk LXBgZM4c=ZE?y l9  .pZ)f"QX  hF2sM6  B 3] _mPYx " @ . KVh94KhZh4av G|j8=S _ Whd#7)x~1P<si 8aG`!vSv9*el\2>qjuuJ(NF11m!hZ2nRC& 4 G a /  _  [4c ^i  O&sR Y Y! G L 4 zgp h GU , B ?v { S   0 - O kcZv/=D:^=jm$NJx-gq{^^f,#=*nJ:|j[Hb+)?N{Y86i%cMvzJY3#Qg2:7d+|/]2JT.hG##LGAhS9&\2~>Ui.^ 'n o!?ya,k fs/X4LDC>kewR:LQOx5pPK!t_`~YFtkM+m) H+q2<JH=yp^3[p  ~  KX'cw"0a;v~ O|^$'8zZ"f6vo AqvKm8gLZp%t[7(;T`@Ms;V sjr "Lxxa bY|N9cT1/Oe{y8vF'/MnuxS32X^4Unh:? O<zA/hTfJJbU`5giY'N~I\j]A]M+E C>vp'IY^@=RJ~^p/wGm))b}DGrmzZ2#K36oSl7O,SEY"3|!<_SuWo(F2P7CO(=,"&7h<m<NK=m5oE)y Q`c\IQT8[3cUy{B9f.s_Q <aXL e&*9jJNv4U1e}%vs` 4msuo+R2bpG2G+vf  6?>lH "f($;2~Pm#>GTd7v2I_a-o}eM:vypIJmUna2 |?3-?1KP se{ N_4pW++{-|'Y | uI%+O] jO 5? aj/)^$IKgtg6 o ^<"0]C bum*)_56VdsB3LkOv_v)==$CH'-7l^ R|Oc>Y=T1_^Q-*I\tO O:Tz8PrM>cD$<~We+Om0HVtl[@o~\2;y6aum{&5rEipc`^pwLTtOa-JS&UCUS&"Bn aN_)`Pt;ZtRR O)$Fx~sSt`{H=a}fu=[ .XjVX5 !RQ(8azyhhd?%. +a|t`N;$X%M~t^QYvD6T7?!i3![}E ]Q.NszV FzUV-,bvH&(^v^N7 !O- dS]ib\uNH6 V^TR0|o^SN; &! 6[{s?l?(+Tptg'+ WH/GIFewtmx/kA`rndvh3R9(.IG""TvUzwrdVUk&Q[ =[tjG:MdmkG-w|{d"  +`|} *j8b}Z2!(=EQYN@A: !@>04GD5 =JLI1! J~v~iMNQPVqgayrY@AEA9-%9YY}jpr\ADUbT:9J; uiG+"(GNQ^xlIC>) *JZdfw~zw)BTR>$!3Kp ,' 87rK1  ,Tcj 0XWQI>'vmvhbV<9EL2j^[G1($')7Voo^pfM7!&=G=3;Zvwizvw{r ,MZbq}vopz}~~4AHh|fC5Jxu{}g1(##}rjj}~ijrujZUZMrsuxkbjtvgWZYSMdv $*/9Mbt{ur~pb^]^L* $-5H]wraRA4)!=fymo~ 9Tv[Y`]? 17DPakty}|}~cUPK@=GL;+8MWL3! 2IG,~aF41! -JexrR5)1) $Aaz '/9;@?EOXQ:(  "@PTTH0#4K_ildXTI@Gaxwqpt|~wyGSLVl{{jeQ?'  NhS8% %?dzoa_WPF:3.<>>42-)*! vpv$5JWav '-,#  (,2@Pen} \E81( $,'  +, mbek][IFNZZQB:<>?@?>HRdt{|{xh[\ckdZX[[YXVWX`oxoaVTWSTWVS[hh_UF:8>DC@;63334'" "$ +/&#/;CHKVdlou #!&&!!!" !%9Nbc[Y[akjihn{~wrnjjljg]ZRJBC==61&}tqpnppgdfipz~}|xtw|&/032BOVZfrvwrms|~|zmdZYo{j^R>. "     #*)*(.1*'!%*)*#     %+$"!3BNNIOZlu    &'!!     ~~~~{vzmfks}zrpmfc_afb^VRSVSQSVYcejpqwz{sk]^bffd]__Y[[]kkmoonn| ':=@DENU]csurqi`befdfmiaYUULF=@CF=;=86/-134%$$%(,4911001+-)020-,$   {vrwvrw{     %%!$-494)(-5315@Q]huy{x~}yuqvy~}}tv{}toe\VM?95,&%*0010,-'%            "(3FKVY\X^eu}urhfeea]]]]]\\YY[W]beif`^UTY\a]ZYQE;8=9549<A<898=42(     ywoinw $.067FMX\]]VXUYYTZXZUYfhnuzyyzyzpfYMHJMQPRQULJ?99991/0.')%%$ !$& !   ~zskjjkiknsnrsqsog^_bjisruz}zwojeknqsokjjgeccgaZWV[]_Z[]fgjszz{~     "(),,1000)((,1-(*)(,*#    wsqrlg^ZVRQOFB?91+"!     &)/1-..269AGOUZ^jnvwwyzxrjfgc[PG<3)&+%%*)--)""  '%)&'))/.),78;621756<CIONSRYWU[^_]cahekjec^ahmssqlec^ZWVRIHDKIILLJKEC:92-)+%  |wuonkd[PJGCC@;<7377:>@:<;;720-338>FKTSTSSW]ckpplfhlkqtw{      ~{xtsppmfkldfmjgaZSOKHDCB?<??;::8//.343.+&       "'/2;@BGGGHFGDDB:858?CHKOROKHHJLTV[`[[Z`dfmoppopsw~}{}{wuposwx{{{xtpjginooplpolmkg_UOC@:63/&$#{yztyx~|}ytrqqqqkmrpvuuyxzuttz  ~|zxprecb[\YTTMICB731,($$!     !%$"%$%   (00/-)('(-39878ADHROUX]XTWY[aaeigdehqvw~xtnkihfa\ZXUSPQLHHE@=<40+'*&)'%$$  zvrniga_ZYZX[[YUQNJFDEKHKIOMNLMNOLOIIMRSMNLOMQOMNIJLJEB@?96555;99652,3110345:::8=BBDJIFE?<:6568C=<;47//,)&$"%%$)*$"!   !$*)(*)(--*.59::996654;==89;9:560*,*-,.,*$&$&&%$"    !" '$$&&$&)*,)-.(*)*$&$& "%(*$&%              !"!!!%$)*&)%)*)),-*).)(*,*,-*)%% !   !&).,.-,*.-.,-2105569;===>9;89>AADGINMNRPROMRQMSQQSVTVV[YZYZYZZVVUWQQMSPNMOHFGA<;8611--/-,-.%%" !     !$))*'*(/,.2555569=?=>=?8615--/,.)()--/,30201-1268>=BB=>>@BAGEFIIJJJHKNPRWUZ[\_]`geijkhnjikjhkiijknnnqsqrruxz}}~yzuxqqtpooqqwvvsuvvwursuvvvy~~}~}~  !! #$$%#$$#%#%#$$% ! $$"$! !#$#!#$ %#$%('('-&%$#     #$%$#-(('-/,-+0.+-+,0015478=<8;=<<@A?A@ACFHHHILQPQPPOUTSTVSVXYYYSQPPMMLHFDDCAD@A=<935/0-('$$              $$$((-.245847<=<A@DGIIHGIHHIHJLMKMPPQOQPRPSTVTYX\]a]_defecfdihnnkqruuyxx}}}{~~}|}}xxvutqpnmilmhhfdb_ba`]_]]\][YYWZSVTUTTQQPLHIHHGIEDBFE>A<==79854/01/1+,,(-&*##&##! $%%"(),*11/43448:79<=@E?FGHNHLLMLLQOUUWYTZXWZ[aa`ddimihmmmpqquszyy}{{}~yxxy~uuxyxyyyxxvutqpqrrkiihidf_b]]XYWXYVTTPKIDDA<<<9885440503444.2/20,000-+1,00-.1000045439798@?@DEDHIICJGHIHMGMMLLKNOROTUUUSUYXYXZX][b`eeegnpprxx~~|}yxvuoqlnliiceeea_\]]]XYXUUOPMMHCEEECAECDEDIEDHCEIHIHHHIHIGJGIMKNLLLMFJHGMMLPQQPVXWXZ]\\\^``eaddcjgnlmrqtvxzxyx~}}|}zsqqmmhjhfc`eaaa``b`\aa]\]\XXYYX\]]\aa\]\\a]]X]\\][]\\^\\_[`^`a`a`fcedefhhiimmihmmqppqrputz|}~}}|~}yyzxytvtuuoqrpqllnmlmilmigjihedfdddeededdhieeheihdehediimqmpqrutusvyw~}|}|zxxyvsuuvqpqnmkmliihiiheeaaa\\\]XYY\]XX^\]\\^_^``e`b`dfdaddeehmjmlmlquyxy}}|}~}xxvtupqqqlnkljid`b[^\YXZXXXUTQPQLKJKIHHHJHGIHECEDEHEIHGMNLLPLRQPOQTUTTTVWZ\\]]]`edehijhhlqnmmqututyzy|}~}}yyyxyuztpqlmllhjecfdda\]]XXTVTPLMLMGJCFGEEDA?EEA@@@@@E@DEDDDEHHHGDIIDCIDGNGMLMPPRKQQMQOPQOPTUYXYVWYY]]]\_a```aaedfhihmmlmnppqqvttyxy~}|~|y|y{wvttuqqmplihiiidaa`\`b`\]][]XUTUQOQLRKMHHDEDF?@A@=<;8:441//,.+(),)'$%#$$# % $ ! !! $#$$$$$##&#$#)$')'(),.1+01000435547898<<=<A;@@BCE?EHHHIHGJLMKLMPLLMLQPKPLQTQOROQPPQLQOQKROQQQOPMPLMLMMLKMLMQPONKNFMILNGIICDEE@@<<<;9987944431--''&$     !  ! $# #&#$   !! $ !  $ ! !  ~~~~~}z{zzzzzwwvqrsqpqqsqrnrnnrnmprnlsnrqrrrvvzzy{z~zywurssqronnnijkmigffgacfbbeca]b]_]^]_Y^]ZYZZZZYZVZUZUY[YYYZ]^_]^^acbaefg`giijjjjijijinkolpmnrrprsrtwqssqutuuvvzy{|~}~}}~~~zzwvuwwtrsutrrrqsnnqnomjnjojjifffdbbbc^]^XZZYYWVQQRQNMOMMNMIMOMNMNMNNNLNSLJNMNKLOINNMNPOUUQWVQRVVUZVUZXZ^]^bbc^`bcafcefffffeghjnijnmtrrqrrvwzzy{zzy~{y{~~~~}}}~}}zy{xzwv{yvuxuwqqsqnmsmolkiikfeacabbba_a^^X[YY[XWUVURPOILJNMNMMNMJJJJIDKHFFEEAFFHGDFEJIJHNNJJIIKIJHJJEDEFFEFEEGEIJJIIJIJINRLMSQVUWVZYZXZZZ_]acabagekijmonnqsqrwuwy{{zzvyzvwy{zzu{{yz{y|y{zzz~y}~~~~~~~~}}~}~~}{}z{zxz{zzuvrssprnoinkigdffgabb]`]YZ[UWUVQRRVQNPSRRMNNMMOMNNIJJIIKJHGIEEEFEFFDFIFEFEEEFKEEEGIIFFHOIJEHJIJJJJIIKMNNMMOLOMQNMQWTUVY_]^^]cbagdgfekiknnnqrsrqsqsuwuwvvv{x|y{zy~~~}}{zzvuvwvvrnmmkjjiegefh`fabcb\_]_]ZYZX[ZUZVYUWUUVRQRPRQQOQRQRRPRNMOPMSMNLMNMNNMNOLNMNMNMSRQRUUUWWUUVZWZUZ[ZY]^]acafffgejjiknoqoqsuvu{yzz~~~}}~~}y{y|yzzyuwrqnronnnolnomkjjhliikejjigjfffaababcbac]^^_^^]]a_\_]_acabbb^aacabgabbeagijjjjnnmnssrvvu{z}}~~}~y|yvzy{uwuwuvwuvswrqrrsposmnoljjkjkhkikejikfegijfffjijjijonsmnrpxqvvvv{vvyzywz}{y~~~}~~~        !   ! $#&"%'%$$#'(%$('$)#()&(-')#%"!#$!$$$$% ! !     !#$ %#$$'(-((((-,1+,0.,+-,,,1-+0,-,,+,+,+,-*)+.+('.(((')(#(#)#%$!#!#$      !!#$%$$$&)'()+,,,-0,*.,041/44447:6:79987889897898888898897984355344545000,,--+,(-(&&'$($$#& "%           $$((('(,+-+1/0103546244489878:794987:38587958345544459334643884:794544444401345311/000/1,0+11*-,,,((+()+)'()#$%'!%! !  !  " !%# $%$%#$#&$"((%('(((,)+-,++01425498;9<<<<=<<A;B<@=?AA@A@@ACEDE?AECEDCECIIHHEGIGHHHIJLMLLMLKLMLILHHICIHIHHIGF>F@@?B?AD@A@A<<=<<<987:87445344410/,-,,,-+-'('*'#(($%#!# !  !"    $('%"%$%#--'-'(-0/1+1/0044453498<8<><<=@@@ED?EECDE?ECDECEDIHHHKMHLQQKMLLMHMKMMMLLRPMLMLQLKROIIKHNLMLHDHIHJGJGIHDHDEEABED@A<<;@<<=<78854304644/10+1+-,-*-1+(-+),+-',,('*+),-*()&)(+,()(((()#(($#%#$$$#%#%!$ !%! %#$#$$$%$#%#')')-,+,,,-/,0/46004454453948488889886:87>7=7897=;==;==<@<?AA?AED?AICEDECBCE?DECFDEDDDCDDEEBEDFCECDADEE@@A@?A;@AA<==;88>;8975783544434545310000/0,/0./00/,+,-+1-0+,--+,,()#)(#($$$%  !!  "##%%#$#$#)'(())&()+--+-10/535497578989=<=;=<=;=<@A?<AA@DEEDDHEDHHHHMIHHMKMLMLQPLLRPKRPOPQPPMQPPPROQPQOQQQPPQKLKNKNMKMHLIIIHHHIGEIGICED@DA@;@@==<<<889897:8837543144/6353410/20/,,,),')'(%(')#($#!%#$$#%$%#%$#$ $$$#%$'')(+-,1+,,1/,100345353692678888949877=<=<8<<?=A;@@A@A?FDCDIECJHHIGJLKNPKMQMKRKQPMLPPMLMQLLOQNPKLNLMHGIHGIGIEECBDDA@@A@@B:>;>?;==9:993589246353050001100++,,-(')$(%#($$$ $       $ % "%#&('(('((-'(+,,,,+,-+0,/,2+1,+10..,0/-0/0-/,,--/,0,+-+'*(((()'#%#$##%$ !                                                  !  "%#%#($$#$%$$#(((($((()#$()##)#)$'*')$&)#)')((')'')')((')#$(((#$()$$$"%%$#"# !!   !!  ! !#%'*"$$$'$$%#')((((''((.(+-,+)(+,,,,-+-,+-+/--,+,(-+-+(-(*-,,-+-,,+-+*')(#('$%#$#! $!# !!! "!$##$%$%$$  !# !!% $$##$$$%%#%$#%#)(')&),,,-(,*,,(-,+-*.*-000140/1430001/530554/5/400/1/100/0,001,/,,-+--(+)&(((((*$(&)'%&%#$&"!"!#!#%#$$$$ $$$ !  !   #$$$%$'(#(()(+)',-,+00-/1/1035/544445494934499889797988;988987898989575444/00/00100001/100.1000+01/-,0/,-+.,+-,('(()&.(&$)('()#%$% $  !!#$$$! ##%$$#!$ #$#$ %$  !! ! $#%$$$$#%%")'(())'(),,'((,+-,,,+,,/0,01/010/0450341354/1404000525310130444000131+000000/10+1130/1.-00/1+,+,--,,*,,-,,-,'(,('()(#('%'%#%#%  %#!$$$$%')($()-')')')(',()*.+(,,',,)+()')'#(')$#$)$%"%$#%$$"$$*"$%$$##$%$$#%%!#$$&$#$ ! ! " !!    !$%#%##$&$#$$$$!#$$##)('$$)()#))')(('((()',(')+--'(+-+,,1,++.+-+0,1+-+1.--//1-/51/00/2,+0/1/0-00*-+.+-'(,(,+,-(((((('(($#$'%$#($%"!$ %  ! "                          $ ##&#$$)#%%$#$$! ! !                     pyo/examples/snds/alum4.wav0000644000175000017500000027514412652732202015221 0ustar tiagotiagoRIFF\zWAVEfmt DXdata8zlC PS,#jV[ Шނ_$7q٣.ղ]"~nV2Sl'Ō Ǿ!Ű%pc Ës-˳)MV3缊lbd %ͬO쨗y %ַл1!TR Ԑ}ַ؀^ը\4ՄπՁgw-;ާmׄLٽ*v.,0wքӁұV؅EPlޏ#`C 2 0 9  }B0c~5knRK+;I  nUjJj01# 'H%!kK9W  ] Dlu!$ [ _D d>]DD\D!#3%G%=$?#"o ,4N"gy 8 b I(VoY #z0 ttLo}~E QO~| zte_qj.N ?Pk8P xe  ? c He'({+XB&` x7 ? 4 wKA Mv g>`/@CqM hc9T Eh~ n Ds8k HF D f"$;%"gQ  p:(YulV]}| 1FSd _ Nq@3W]}TYa +~#28 ,K5">qqHCEGHi=F }(+ kao hmN 1VK J1 ) G+,<5 4 n!$7 Jl 9 x J  ' m $(&{O ~? et"X!'/,16T5.)">B"U('0x"'695-  & 28+-4MKe g$ e %ls^.Dqn n{&~,$%v`m!oD& /0 "x!x ;  qr=N ~  a`P!<$D7 q y e1 05`#v28. %K [ n '$0S<9( d+>>89") @  ; $ L_CRNr g- (3 ?}1 u#($(&I5S;fv s$$h fz;- .H>[ DB~R&?>q .Cv   \q XYN6 v !U+7"s dttyK3 9 :v  x gm 9f& 'E!Z  z z41?MG:4aB(l  U ?u  ,N8+:( F &'** %Bs @Te ]V s fAe&0d H vr)-2t)U!(#B{4wY WEM`%;O>_ Fv*x3L Y ]T '!e\W=  b [VX^ 6u ? f eT7  ]O2j!+*P; P++  r h[ x  bY3Z! 7# Jpk$K%!@ )_0?/-.'Er @ F(Mzb*Na|QA(B- 4 E<h2bY B%+ yB hG 8 ,O f_mZ [  g  ^ F8 <O!$No| Wm&E 2  !JOm]W _ U ! "rI^ 0H !Y>P/ e<0  rUc+V/vj\)D;p$Y_nX$?!87 i[]6+l4.2Vt hW 8]_ / va'HeN<$k F5K|  8" 5 Cz \E h Zl)Z!! *W1 r A Z ] ]X4X4k^X62&MhGP sEjy3pA a $F2a,"T:O  , K ?kwa W UXxZ  .  ` $ tJ y z r |c&q<! _[ VCj! ` V VWC~ :] w E Q 8wASX1lCus!* u j(I 462|P4Cv$@C}E[ +45V!<2E4>&\ ,g C "!R(p[}DfI |%~3(\{#<"gO&8Bcq!So>} 4pUQw  $@32ujU\x0A')^UxCy%J#[ l,P 0zzb6Vj .;Os3gsjs#4;@ry^|k] G[r*gQmCRnlwSC0a! FTGT fs o|/3dAMYki{|cGl{zW ]? 0M/-]Us@xO0V0>w<P3+Wp?XbxPl4t xj%M4]S1_[}z 0\(J`4x[?:.-@aBVHus[<"I$@MJ=swS|f =fxD2 yY0%Zn[1kVjTogc Itb`?]!o ;^| =8WzTW/KsT7!11 "rn\\P">K7c61t|rndry/U$E/YT; $+Khbs%r_u]'LirXs1T# JGG~vVl\SDsVj2!*+ ? 3h9K~86b*a05hZBVFsVJ@:fL#B}JWr Ye_%yple5`,85j}Ol"NAsk6e^w_I:_3w3w\h!=xF.Y|;$1j1;;v"S1wLC+1hNcJR!K_E:<)M/.&=f\[/zC?eTE%emO31CxG0;c|cFCAG5dyc*2]}oXY>oh>"}E.7$/\(W\>`#fO_NOpZZE!zmadukK=fg!!U7xfH?.`wE:+:H~;cGtJD;0!xY(B~slEP4b!HAI`{ |T hz Y vtnOM eZU[ Gd'MXGX7%=!2. H\3m<.~^]q%Tk2<- _K.=9Q"a'g1[ ZcxyN. `Z:}!rqW-4Oxi 1`$;&zUq};Ns!>Q({um;Vc~$a<jC PlTek}k9-;<%_8 y,o7<LPuV+[vdYcG}1z N!7(0emg`_X=576=Lfzst%P^\V |'Z8Nio|}MUPjM|   ='?JQuPO LdNe6D3FO;Y<v[M? HW/0X;H35NxdA;d^3'@k%|"57> 3we2OWh21hJc+} R_0M Nr,rkBm6n3 @u#Qk1?h'&X<Eef/f& PhkCm_YXWY_R .KQe9 nYJte#'=E$+Ff~vb`pu P%z2bsk[p}|\'KZBX"6P\O-{<)6_emQ Xtg5v#2EbC;VxrItgM+Fn: 8i Mj-.Pqxqj_3j#@Ri='%.:Ve\;J6(!ov'>J_m{tnQ!a?3+*@Zaopgqv1<0q`w"Rt_=57(=k4rrV4m) h: 3kho~_7;|Abp#]A:B]r^]cU;&;y9a+ \.7/"@dHoJ!6XGky; 3x+ChmW0bG?7@FG*xV%;k*+:]#Y*#M}YG0.~*,Sopu[?8+~; eg&@k$NhwigbFyU< 3Iqqc^VN:;d*,+$>i|w"KmXhqN-l`^t&9OlpxqrxZ  " Jt{J* )JnzfK=6<=?qB  ,k19@h!aLMUSZb[G# V&&Hr*Fbovnb\av|}T$jO-&HTp[Z[9qA'UI ;cqy9o6gtEj"j$@i=Sk;Vkswxrk]VI;---,%( tlfmn^QJKL=iM=1FTo/RzVxP{lZC)fc`p}In;G]]dddj\I&l5 |hUEMSi~|w}.fmP.wnpu6f'Icwx]3`K6 ='.?I_|.GPA&mXC<6(""6CCE<==6DRmuK(vhpgoupa\Zhv 'E_mS5!6W{  {J !"! 6QttV6L~S)Uh"X<NV[WOA4t5NiXNUc2Z~)=JIEDJCDCDB6666DQQY_fs4PkxxqkN.fJ0}pSMMT`~ !0(56EPftD"/Jf 4BP]c^cjde[ejqxr\<tC}h[LMUZhn~!5CQ`eg__RB7." !/D_rfC/oaTUMLNSb}LUZSOMML@1#xkVG;, .:Xi %ycPB@<:BGVVdlqxxs\G;- ,4IOWi#Fg#|~|}~vuoj`M?xrdcckpdjky#%"$$$#$$k]OA4$-@Vr %0@DT\gpuv~vvuvv|}}~vg[F9) $1?FFLU[hvvvup`UD1$jd]VPOAA;BMPejx$8G[[bgb[M>*jdUPOJ94&&4AOcz$9?MTTSTS\STME?8:01$xqqjsxyxw %##$$     $:>NTRabhpooiYULN>?820+++)92202+prpr%#$$  %++1099DNKUMEG91,#$#$  #2@M`p|uohbSF83#,#)3**$ $+28?>GNRUSZ\[YbigpovvphiZSND9*p]OA<::BBO]r~+27GMLU`hbaihig[TL@2)   #+209GMTTTSTUMLLMMMMLMMET[S[\hwu}uh[[TNSMSE?9+ ~ywyyql\\V]edw *:8?GK\ahvw}vv|wobL@9* ~sie]VNVWcrx %  #*30913*#y~ywxy#28?FTZjnowupbZTE9+ yjVVOHC@PMW]cz$?Mivo`NF2)$~ypyqrrqqsqx *$#$"+#%#$$$#$# *8?NLLNE@8# ycUIB4% +-5AIO^cwxykcdejc]]WNPHGQV\\ebdlpxxjqjldVVWUV]^ceikrxcVJ:+&!  !+4BOVdjxqqe]OB4- %4;AINWdblqqrwrqkjkcc]PHA5-&!'&&% &4;HO\qq]IB-%   %.;@BHNOOPT^^ddc]]]VV]]W[WOH:/&$! &-4;;BHOVdkilpxz~~x~yywrrjjeddd\^\kkpy~~xqlc^\VNOVWW[]edkirkjqediejbrxkpj]eVNCGI;;2<4+43;PN]kyxriVH5%  -$4<APTeqqdV@5& '-:BBAHOPHIHA;4,-&&  '3:JN]jxsc\QA;4$   ',344443;4-% {ttnmlu   &,4AOTeqxrdb^GH<,&  %&4;BBHIHUPOHGH;C94'   .-;9:BBNPU]\ced\]VH;4,&&   &-:APUX[V^\]ceb]VPGHCB;2-%   &%'&''&%&,-.-425,.,----53-+&&&      { '--2443:;;2:A4;4.3&-4& {{tnmemus{&-5A@JGVVVQH@<3-$  zukgefg_^gfmmk{z    {stttmmllmutz  |z{zur|ztf^YPLC=<<7<=657656=7566756.60.)0.0)')')("!)'# !" "!" """'*!(" ""!)(!"!!" ""!"!!" " " # "!"("(#((()(("!!!)!!"!!!)!)'"!)'(*()''"(*('((*'))')" ((!# # )()!#(('()')'*()&"(!!!!#! " """""" !""'"!" ""'"!)'"'((*(()'0.0//00./0(/./0.6//0.740.066666667675==CDCDDDCDCDCECCDCDCEDB>DBDKDBDDDEC<><=E=C=<>=CCDDDCEDCCECCEDCEBD=DDEKJDCDCCECD;DEDD<===<<5>64>;=67<><=<===>DCD<==575>65<67;7==57=D=<7C=7<=>C<=<>C<>C;>6><=D=CD<=EB==76<7586655705.7/0./6.70477.//00'0///0//('*./)((/0&00.)/0'(*)'(0(!)('(0(()((!*"!"(" !"""!"!"! """#!#!((!!(())('()((*(')')()')/)(((((! "() #'""'")'(# "(!#("( "')'# #! "#'"!(')"!!((')!*( !!)!(!"!"!#! (()./0(*(((()((! "!# !""" " !!!" "!"" "   ""  ""!(! # "!#(!! #!"" !!" !""!!!# !"()'(("") "'" ""!"!"!!) )!!()("((()((.0/(0..1/.///0/0.6005/60561/'/00/.1/4/05/0/-76657>475676///.7..1')//.7..675//0/.70./7./60/558<==<===E<>=DILJKIKCKJLILKJDCKKJCKJKPQRKJSQRQQRRISPSPZQPRJQXYRWZWZQ`WWaWY^YX`W`___`_X]_`^_`_^a________`_^Y`X_X`^`XYWYWYWRYXWYYXRYXYXXXQYYWYXXYQYRXYQYXQRWYRXWZPYYRPS_WQYSPYWZWYYWRYWYPRXQRQRRPRQKQRKQQRPRQRWSQPRYRQPRYWXZXYXXXXXYWXXQY_YRPYYWXZ^_ZXXX``_]`_Y__`XZXXWZXQY^ZXXYWX_Y___f_Y__]g^`_gefegffmlmlnmkgfnlfnlmmlmemgffkmnmenkgmfegff_eeg_fegegg___^YXXZWY_^XXX_`WXZWYYQQXPKLJPSRPSQPYQXXRQXXYWRQXPRQRRYPRQRQSPYPSQRQPRRPKRQRPXQXSXXR^_YXYW_XY^YX_YQYWYX__XZXWXY`^`_^`XX^___g__ffdmmmnflnrnlnnstllstur{{z{z         &'%.+---5352;43;:<AABAHC@B@AJ@C@HHCGJGJIHOOONOPONQOVNPVOWNQOOOPONWUUXVVVUWU]]]\U\^\^[V]]]]^[]V^\VU]VVVWUUWVUVXNOOWPNNOPGJHNOHIHGJ@BA@C@ACHB@AHAC@AAB;;B:@C::<935;425+..-+.&,.+'%'&'%&'&! % !     '$!$ &'&& %&'&& & '%&&'&&& &-%'&%'%',&',&-&'&,&'%%&'&$-/-,.-3-,435,43<:344;:2<;:;9C9;BAIHHIGHIIGHIIGJOGOIHNWOPPUVVUV^]V\\]]W\^\]]_ccc^\dbdeccddcikldkckriljrrpzwyy~y~~x~~~~~~zxvxyyywyxyxxxz~x}xxxwzxwxxzwxxy~ywxxxxxxxywy~~~~~~~xyywyywxyywrwyxyxqrxxxspsqjrprjkkjjjkliklijlkkjcdkkiddilidljkcdkcdccdecddcdceccecd]]cddd\^c\]]\e^\]ce\]]dbfbeiddcekiddkjkjjkrsqxkqrrqjisqqrprqryqrprpqrqyqrrqqqsqkrrqxrprqzwjrpqsjprwrrrjkkjqsjkckjjrjjkckdddc]dkdcddcdec\]]]^VVUVVVVPVVOPONPPNQOOGIIHNNOIOHIOHHIHCHGIGIBB@ABB@:<:BB9;;9;;34354+.-,--%-.$'&%&''%&&'-+-&,'%'&&%'&'%&&&&%           ''&''     &%&'%%.,',&'&%'--,.+-&'&+.&,'&%--+34444:3-5-,.+;.+5,3;435::4524;::<AA;AABI@C@BABII@BIHHAJGBHBB9BA;;AAJ@BIGBAACBABABAGBAJPNIGHJAAIIHHGBIABHAJHHH@JH@BAIBAA<9;;;4;24-/2534444pyo/examples/snds/ounkmaster.aif0000644000175000017500001001430012652732202016313 0ustar tiagotiagoFORM AIFFCOMM@DAPPLAMIIprivpbcr?SSND p     4 41-4;XCMS([!L#<&2H @<PZeS#i.ea]Z[r@iV`EWTWQ`P82EJ! ;9F!i.aHvLPhdXVX9<V1+@&(B@ SS#-+*o}sovVBlHVRP7P:L4n?W.9.]RnAql{}Yau?kehoQQikZ[vugvu< /80G(9QO<O\F@0'5 6JTb5U5T9faIab2cT.N"K@,+C[irofv2\4@cwm+2(* siGb,*. !| , rSHuulzbQudaS1LX#2(v1^V9v|zbs|a9 !!9vugyTVh+FFBOgF9e5IX]i*WW@Cq`eqW;v,80^R8\OKcq\)2 &sn$1$qH#3'7GkD`Q48Cv >okHh(--*{O,SzY"r:pwT"7Wc"qhu ,tw92ftX m. %mzBt*{HS'xy6y*c1FwyTgeLeKyU L`B7Z"NW~d  | +RB;(>) l ( G !  m E ` / E _  ' ^>= O"AE3fQM YzmW##,*xs( :WV*eytDu2 2X{} F $ s h T u " )   1 A  n % L ] l i r W ;FBOW;L;Fpkp:?'t/x__3S?RhAJv!Bz&Q)'E[Nvl_i `3UqPT~<rh &   y y  3  t h|.` $h v  & [ S  L7.%v4j_Ju'/i$JL|$*jv>Y~qBt751 Q!9 {"gQ?* NW JH!<Da-o\  e C  k o 5 v  a a \ v $jc }   u A Q  }  -7Q{)80 p!l}sLqz.Ml 6-3 d$$r @ P'4& ;q;\H Qcw,IBJRQ:jS W t = ; k G#X < a ! 7 ) A U L b { Q5wYC 1MkvuOo? /)sOlV޴ڜjܞDQ=hnlyo(}%KOKBqAu: ? =Svf-3JR8y | D \  h  I t r   / { P }  T h <Gzj -jVe>cD[.+IU)b>9>>M (ۥd.(!mg+m x3 E '<; 7j=['QJ:B<&<  M  t y 6L'rY-r^A>5 P.Kqi~ w A N o h<9edwYP_6-&#wo'ݳض`YۯWH Xنb; mI(XEC_Narnt2]%jH}!1 D . % s #  X.m d -<u*c    `9-zc&G={g߿I-ځ<ԟ3{_^\)5},-6\sS X ) 8 O T 7 l f | *:bo(r{i:%Z*!   B ~  $v~B ^@RJ  `'l7um:%/oս۪/3ӰځܼKۨwAv 7^[P$<mm6u4E(5- #  7i FJ  0 -AB bsEi#k^6B s "Q q  u 2  x O > ' u ? ) k T^\8H ?k{  m >7rjK$ oۻ0\҂ٰۙrӖةMvW0g-F}:wwKy  p S  n P 4 & Cy +03 {{$Tg.}h  w >  C  J  : F J p  v  $   x 2  #1rKnz5]@jY|;ӫ ԾPOMR]0B"9\*i   W f /  QYK *r : D   a 7 ? ~ 6 -  x = _ D d  " A : 4 ~ } FJuZ%dխsm|5!ԳݍUy\t?c +uNw KY nO!_ d  K  3a  a|a;{(9'$3(  R { 0 @ < S  f " ) > ! ~ , <   -Pvv@&_ {CJUUvpDQ!Uӊ.ՠהwL=pgpgBw  *x( -YS  K  ( 1 ? f ! * e{'z]  W G 7 ! J <  hk F  r  >  \xYvX< w;٢۔P~g"712\\{$`[KE(*   _    , - + ;a%   ]  /j  W  4 v ' w t   m  S  ,  |4OZA]v.y(/PvՇkߖR8uWfMk B5053[  q q z   B H ]lyb%YUc   E M $  )  = @ 8 n f 8 * h e 2 f 7 u 2  ` h  : x ,Hav& v;ݎgߕEٗP$9+|Knazyn{pjj'y]   F> A N % q CHx& + J k N C & w G t t Q  u   g +  $  A > cg{}E6Zoh I/wiqH]"~ [ H  d  3 h s fl"-DK Gx*oZf//B`.Xw HXVFY1:|e ۬ڮ:Kڿ޵exp/ g2#=e-a7[q `$]2Y2*k  T  l ^}<H*@%qk>-`;?v^HMa~o&}k7=Yܓײ%9ߙ+ٽَ"- ==ti2(G9 tl [jk6>  Y j R %    ]MhRe/jhFؽݺx?ْ KZُ.PeGl  | E5P Qz<O$   r^%^p y   N  ) q  : j @ P (  |+  N & | : i  q~ $RCncDUFxR%K^0 )(xi{9[ 79P6Y t  BLJ 0 2  a ?x|\` Q&F֋) ԂmMz]W=<P/7  h'r7.( < d  /   i! ~( I=Jd7@r0h y =h$]%~y4/s\oI:  l - '{iWm p h qv  Z j jbORXcJ*;^gZv4_ӡ>J׽;$ڮAZ2 +  Nx  iL    Z26v<f=H);  #VdӰڠ޼hϳjG?f/=Ryqb4LD2zp _ _#cqa?8+3u[#>  }  u i 2 ^(xtizOs3v[LI e :OD=| X" A/  Q 1 G]ۙЎH'(t'ٛCsn.Y91 b.  Q  Za)b\ QLQxr + Y @ 7Z}9V܇Γ@T`iۻMpn*#) @u   h "  ' | 9Wz "mR")  9 Y4y ~^9ݳ Sՠ@iVa,`'     , |% ?w <!M""B!z } 2G-hn! }Ѥݒ1lձR'| o>IcD{ E N  Z ci  . Y(!! J% XUWw#6Yؔѫo#9@GB?   =  Zh fl#70#7%%&q$e!k V +(Ү޿-!G{!I.e ' y m X;  ?ABU}#I%$ ( 7   &GD)9Ѥԗocֈbj:qk9 c  0T Z#7%M$< !  LJ"2|t$OݜZu,k|>3 T._% 3 W !AD"6!fK1 By)"VUaApembׅtKTLq  g P z=" '-Y!f"!F *W9PE->ڏ1B͈6<7δϛb4G/`&E: r w<   $F|K  qs!2#%# \ O JL ^]I ʈd̠Y{USwh}I J H ~ Z }"$^$&(Bo(&"I Ff/!ۖ]ϓ֝hɒ! Vnȃ#ևxlWk C\"r.A!+/%N'N&'*A+r)&6":_<H 'O>kj9ٯ$ؐqބ߉˼۔DŽ݇ȵ'YuSVv, -   0T#A(.*k*DJ+./-_M)s # x}) rb4tq4|@v]$ݟrV C y+ >Za"}&(J+0#-4#4 1-($, W 2#)m" tԑׁe;8eKҹ+^LC˔8QO) X g +  ?y P$(3."4':")b? +d@)>&;G"61w[+|<%eAE* & G| N8̼ѣA7޿* Ħ^͚h;Y1{ u  qK[LgJ, 6i&*-/":1.$3%)3#2"Z0J"g0"/+t(9$%(#"4 q/  E:"<<ҙ'¶TW``㼪ș[Ԅ߁xYJ4  */ uMj6|Z cI|!#[#o#"\% Yn1_d#-<%&]& (P![(&="xkF[M-0 \ )oR Sհ0xͼy.5)gR ] c F jb[ (   wgx[}Kf3`XqD@xf\ "$ ^&R"h)$,#i,",]!:+)&,!~w Tb a aI$v {@4 П*DY3 j Zw6Kj<UC  7b%oH t r_"  : l * H`h|?$ZsHWCd "n#$%Xl$,"N! $nF 6 | Y3JNޮSΥʷ£AG3ykC?"ɇUؚclH[I qK & f~ 0 d_,6;v|N+ O Wi"  z4- 2 8w'z C `  g * pHK$yM(coIb-z$e=h H 3 }`k PTaQ(ׅđLv}ξ5(jƸiҗg p y w > ?xj +- KZ 8q$ " _ 99a 45 i 0P0.Qgx|*G C!!"#]##&G"K"s"!"n! N  Bz=Jk߿6Ľ)޶üOp"2ʞ*ֲdͰX% r 5 d]3g  9]KjY x1 %c&$:w 6/:fCE8  D 4D|&## "r"6###R$w##  6s+eR  7  + rMWEڦ.(%BQԢȄ1ѤF^S"3v R E ]bke4\ 2\ g5x< a6 I_d8@nDv&Z<$>Px  5 i h.p; eh!$?$%g%&$#D!c dNn-0nJ|(  tY L F T d  ^\_D\;i fK)")N#.$m1#2f# 2"2!\1/I+8&# |=|Yi w  Z9o}\?rGpr;{yw cU߆R֣ڻՁǃ`Ni, E֗9?Ůս U}i1ipC;r O  8| }^ z XWY(@(U<%;CQg%9iE^P  4 /  j] ^ 4 -#^*3?\/4=(*7/@)4H-7*LH65L(>d/B. k+N!!  ? z    yR 8*w9fY[ߋ؟H́;ȵձ*/țʅq ՔwDt Dhi|s3/kD%JuJ .e w*j  0|! P;x,x@v&WQh j a  6 %{6(@,g!/"k1 0.c,'y)i_&h#x%lDEbxLAL}7 o  tvNwܬlѷƶϽɕ^lkH$ɦ ՍX<pK> K%5 IU}So YYR  hk _'j )RRSs'2FH2w+: s r n dAj$(+!i/6#3$5z#x5. 2E0. p+N(]$@qZl[T0_- ) x 3iEX:to$ޖ%hsTty*6ƥ!@lc`ӛy-0w<a3UF| 13  "o ca ~g3G 'p@PY;Bv > X  &#Z %)/-wn04/:/.-$+`(d;#hE    0 b  )wGfe?xŽn_aߢέӼ^˚ UD7r  W ]<yY~.kH=H w$ .i 5 tC~n ?l  %O9qFu"&R)A*~,./[.U+'r$l! g ^  2&yqO[m ݣϔbԥlRI,{D̠wŠ0&U    H W *&C  a <IX!K!S  4T T4@)t"cSF7  [| j7  X2 "$%(CI*#+'++T)p&y#w{! ? 2 HBQa&Tϛ2ſMuCo!}Dl 3 v  / ! K{E aSe Ibb> V  o ` > ;"7I= Ed.tmL0%Img!L#.e$l%)v%M$#29I= ! <8 !9c9٪ !νOιc=5Ѯ0a b tAA\o  X[O  N8 Q*g /Wryf Y Z ^%,@/+^VA2Q3!#&0##X"y G\p R zk"TҿϝćS<¤[~ FmpZ,:ߧA    ^_v \ O|Q46 :* iOUuuIoB  x <> s I R n:  "d4" C5)  H ]yoGۤܗMѹj$Iƨ쟺D=׉Eab/4Sxw & _ 5 Sz .+ v6E# u0  327Y (6k )L[Al  A m_e~8MF=$+6d 4I `C <] 9N݋Շʨ Oɖ]Ɖ>yǰǼ4bZV&iSr,gT9e+@ l D:*& 7\O KZ2{   7 7 I  W `[ G~rx'4H0Dl?s%   , s 06?a۠SкŒrӭFќ̴x]rs[BG S$ A ~ yX F e;"VR 2  ] Y##$?%fg%J#bdy n sn  9 +6 s  VF1j  gR4^JЪw絫_=׬IQḐk҈5ܔ$a  ZR?!   )o 1 l CI rkq4@]& Q Y 8 _p ;H G    P3EJ\jyU{J   : ;S L  Y i &CPGivNC$=.9g5h!(~;"H CM<reu^vF  (   `  I X   S`3AE:QQO W&jjJ8PWsxu ˶~aԬ ٴPܛom"O  3oh} }  X3>b hY iJ+ 1; pWAs/i+b cx,jC83 {   {zy'F>h |-W -պԬe}ƃ4^K0 O 6 U Q Vt\= r    ya  ?  j Gi{ ^ g q  lG. C q A P   ];8"  IjQxsx-՛ .42K U L y5 j JsmJ%|/ ; i W x! u ; ` RwkRrNr?z~4 7%m<<"z u w . r( 7_ 'QC<wbF9$k Z   u]o\     > ) gR|k?"Xn"z=unNl Kqq!;Vloou k  qXEuI% L  v^!Q ]^7(`Yo Q D-"Z$&K$!E;  !MR f S {  LW B#{Sr :xŤߴJɌ:lۚ8Bt y* R  D k5L/q  a~`W t",")!7 : B$Q<     !  T <,yY{ܵٞͱч?ܥƩÞXvR;s  @ A8 = XC;%u  ^(  qy o; h- ! 3 I #  W  <I&aJS<fa^j>l('u1 'lO=URP|lU K*,  u F?YWPC0 a:j3v9qA.BNЗԡxܚƆo &\$)J Ty q O  6 Q ? FU_ ]Cz; q"!] 4P  m o   y    Yc $^8pg 4^tY`&ZS \ C$Kg_FW tm {,|w g&wS,ޕжҧ |]PC$ș G, ,'  n  Ze^K qXh C"j$^_$   &[   -= l4@mus Kf\>Z]M/B 1n^8 H )s1 ~ 9 - E $^t  D51PM"6BmԣA1؉&ۯjXVެKfq 8 q   d FT r>m:l  H/%!$s %#4 W   gs@ R  1o ] $i KO/7 x3=H@Zբۯh  a F&|+/m/.,M' " ieZ5 t {S#g?ӌWbzڮҏѵe٭GϺY >$w  J ) _ \F _ iD3  #e&&#i& %Ow 2X$p   ,  `  d L kB,uV\xI GuVRywj'.pj     +[ e1i+ [(C4?N4[@G_ ٙ>݉ l`l^5 p , $ . Js& V]` M$V) Z*+,G*9%X WD%l:[,ًӆ Oڇ߁rsOQ/fr-'_gH8 E H0q5x L  n!# ""$N_$? ?js {  Mm!H r 8  ' g oG2 ao{~ZR2lI'[]FH{G I@{2G/V7TQ?"(wY.[iEjX|6 ZL8"q[9  Ze#(+F,i)%{ !KlLq\k"%DkѠИĴJʺ\Hʔ!3t }2 s6?cQ 62 i `H#$U$T&X%l!z  9. J"gv  E W ; 0 o ) } h A . M\7 6e8^5gkR2J!-9Qv#`I TxI=G 1*[ib J"|@QE]#/Sul]U0݉# YH *W ) W! _'0+.,W+' ?# JIr *e(_Ϟv{ݯdztԩ܆ŽqW_h 5  d7/lU:l v -  kt!#>"vD$N%!  7t1}D k[`B e n n  D  j @DY6h  K    Sm%X!/X\<>,K +P""`@K`5Gr*Rm <-|'eNKTg;j I)]lCkBgI|QK{ I(\hA!$r&)%~"3 z ]9/)Q"+a@~޴e龶P &шxA 6 h<` e  s]    v (j^u.~k  XOG7wsDf/=x D @ [ + I1t77c\]m9B)d2E2bX.4(wa a.lLru04vDWUm%V.{#2l#1{wH 05rDk E ps]h{=&Zw{yfXܔ @G!KZ@{>  ^9[ ; MAJ #VD#X$V&# P T| 0  n ~ ~ L}$j AtF`)g l } w - y!   q QbV!`e1 (k 5KxẀ@*ڿE5TiY j M WN%lHQ* ;"b#".'[7(C( :3 ?'{%b)qƺc82pIK  ( 5h;xHG$4 O v*'r5*=*@Y&@ "=953*; S>pgr8Ť}m ߗưi> R M E_ .]L)?CC H1'+%2*;+.@/(@%?9. Ll" ϶+}Y)ˀyJZz? wj +TNF6;GJ" )&#$/*k9>+>F)?'}@!"<4 ')$ wB{Ԭϓ1ʖ1 _^ݺ 1 %v T& 7(m Wp )'r4*;)>&H># =R7,o=&HcR~Ȕs;G^(yc JL~-FlQV:pqR %!"-X'66* <($>U$b=::I1 [%{w v*{OՑȠߝyˤ}6\(^T A uqw- 4lP)4u49 )$!/%7R%;#˜1/`& ' FA Hkdm^3@4hdO!,v'^6/)H;'> %t>!gg+MZsʺĿ߅=s=@Žϝv>P 7  9 L%UDX c/; ~K'%)"2';((?$?!=7v.#r6WcV5}ҁӯAԡŧC@"6XGK[ VBs   '_yc W H/#Ou-p$6'%-?!>ut6+x!9|IԺiē%ͮ?~q˥ՒQ V ! 1 )^avK(&&w $ !-%5'1;0&>&,?w#T>#7t$- #V  d&iL"ÇޟЇ1 x f~o\ n K/) ?1$8Z#.:r!; /;6,#bd }a(̘˾ڻDfpߨ*< Օ3 x k Xr  <4 | < ZYlT$<+L0x!1253*+ a#yx-?۱_z'ˆ>*OQ3rΈKץh] { or~! ms   E  odq- 68tΚÀ͟ǵ36L_o`3 {7[ 3N  Q1 Ky6@4kv* A"$ #a&n*cn*'2# bW n `kl`BK(֝D̩ߖ˼%ˎŸwwc-Y :p"c L0#,l + !35$!p%%@j"   @WpGB;Rqه޷#SΣݎ!Q v 5p%|R 3r|%E1(/+//,5)*&h +!u=[ mk!ٰa}< xuXѾ v VB*xc a # w nM p _DQ` z#*_a.:z255/O*: x#!;TVy!+ȼe= 1 i &OAXEyyM#+0|3d66u1+ %v)'W + j;r^Q`Ϲ+ H 4-e h@b } H L\m,%i,1i4eV6.50 )$"Ss eLF8,2~aaބ  ? 3J 06U* Ww |Q$R- 4!z8c 9i96jf. $ &XؗFͰۈ.ّb]Ջ E>iF +-I &#P$ 3-} <35 y9 :/5,$" L0=vφ̧ď忕μ<ņ"M# w :   Q%{E eG 3!j,V"6l%<$D>/"x>%;Q3: u(Km*kؘŶS ۂ~؀㋿_)_ od*,,( AP]$A/+ ur'?,GX.X142-( # E,Q mjt-יc߾KNʙ]迺 Ɖ͂Ez, } 7e + ,  "'OR A> _'G,U.0D312,8 %))H MJPԫl%ڸ兿v<@ =  nN:j   D e`} 7 U URw"(,#/2%3G/^)b #"~? Jfc=ذCF|3ʼol k k S ]0Vm  L0,0f ]I T7 > G %)_,n/&0.n;) #< [Sߎ(W϶Ĵ12ڑJن M K I 4  c!i'"D+.1^1.i( d#evz 2U^ϔ‡65ñ=XqgΡV 3 e A S .  Z b  f E I`9$81(+W-f/?.* $^@%E"&9 9*`VݺJ³vh@Y3Σ @  g"l  k 0 >3   v B %i$)+.1?/* $1%lMnw,8|<©ݞ[QNٸ VB% 'U H e Q7`x] k"#(s*z,@K./ ,^ ' !,5W FoL޷ 'pݍhZùī=Ї@ y}e2"SM u4{J O#"%$6i&ud))l&K" p ^ KcHЪĜԀ&ۺ9hl7#S,x9 gSB /=gD@x } bb qd',h/8342O- '}o  /*oAς٠+ȹ9^ghĭ|Ҹ h#P3 2%  ; lw 'mc L3 r!3$'+//,)) &n " /`Ka؊H.]#eJ *D l FUJ ^ Vg"P$n&]*+ (b%% # / R- ?di,ڋж!*ׅ'$‚Ѐe>tm 7 5?/3&"=4Bi . a"D#&N''c!$ "v !D | VtӽƀἼئji=vؚWJ᯷_Bi$Y P+l ,by %io8~g! a+%9)f,.x0>/d+ 'a "? xr. <׏̩ϥU: jP䫷 ͻ LW 1E;o #6(+. //- ) %T 5T4ӆӉgف]ƷbX@ݛJx{g*|8 5?UZ; "B'}+{.cq0<,0.e+ 7&!h9 C*وёԛnqW62AМ /xVM 1a TKo b 1$ *=:-/12%)00, ( $%J J$\Պlsnk(•kYcb%c5B9 '4 6o}A oFG _!&X*+--I/q.#|+'j # !p`ҦImǹRvݦ,jN "X1 dR; |c^<l~ Gj$(*,-O+$(. $z 0P f6^҉)̹m/#lṫ}J ;jI$ qIS jYY  Q%x(w9*j, -=* & "4Wp -XDyޝmCCRϲ|ඵ' ,a) 9X RB7 ` B 6# !X S Qj  ,$'6*,+( m& "Qs^yާn L@8鶯²BFC<ّ *e qAu mb q d  7 kk g"&),N-AW+X)A %!'g OaSdӶm5NڷF90ܡk2?~ s 5 h Y t ZFO S!%'*7;+)h & # / f3CbP9R޼N!E׽0@ ɶ%8Ʋ ID7j/ i\u T e O>k !s';P*N+-NZ,* &~ "vRkVA'V4ںTʽ ƻގ@ĸH볿~4 R@ O  F6f )i b ) !YY&),i.<-* ' $C S tJZ Xo!< M҅@&ݾ xČ (- ijq OgOb@jvZm !'k*,).-n+E 'A #I (={sg c/-XӽhͿཿ1ջ}v^ȩZ՜ N\A b \)) .QKK,<z %  '),0$*1422@. C) $b L!LܞKqȾܥK"ެ L g/ :H\hdd rN7  l^z8p bl%*-.R/.[+H K' # 8 L8 &"-97؂8 nVϺ )bfm(tc? H# {oY$X6"D/ G%%\+D1;46|75Z0s +? .%//wAyBcN؀[yZZ;쳙 1- >egy S+;  hB  aS " 9$~&'|(*f;*7' #r h>$ ^ G8q6GjܥdQ;ź;OYh}*eb E,+mzDF'3 e").k-/rc00, ( z"}$+ ReB.܊}⍴뀼cw 'Ve// Y5 _) H  +t i#(h*^--T,& (Z $!=$ u(8ՖöRDômܼQ  7sODMa ^~Ko$ X g - } "Woa a#O'j0)@+_,?*6 & b""Ryg wkv ٪|ȻTތ11ĸԨ \I%d pjW E, > O )7 w AWn {!3%M',(R)b'V #2y" 6  TN d2ϸ٥;ξ ooS-  +A _! ' 9%v)~*'+P+5(2 #S.h@J 7W0ٷ/(   T `DK$whw "u O#gJXУJڵۚD 2«ϵ   2 e R 3hu h  fJRogI#CM$#o `  }: !  ]h@ PTyc J!J6Gk YVՊ#g {j - M q  f ;g 1<L~UM1W S -Tcv'j  >S) z8  vX7 w^\ a~e^츖߹teKr o O x ; \LZOTY X 4. &.'6o,_ Q 1~ X ! @ J@ [d6[f6EZĈȹչaښskA7֮- wl > w c0B-p [[ l  ?2U   a kO  n g7e^M/@   r B~YO ^cr6yQ~J 3mrٗe aPX;  n , ` [6Im-a 1F + b ! ` C{ a  !w=   *5 WcX |P6Z,%-;A7    X !qX97fԾħ+Qam0Npԛg  7P  UC aIirraR Z a u( zg $rJt V|& j  0n 44'j  V   m T*hDWb>ƧʈVּմi,8K}Gi C: v -mH~y0rI zh \b H/'N4 FhKmi6@  jFa   -  [kQZ! ѵJdYWӰbo'L)M# VQ $ Q Ap{V +I> 1    + gk)EF *GH\o6w!^ R !:Ro|$ C_ p 4  / aGx|٭L<"ϵn`Jβ뮾H 5 # Y =C + -H| z hY - I unh 02Xv/{~!}3Tcnt[   ? j  5T@_ G+ I{<ӡѵ^E<瀹m] $< Q,Jq z{FH8Q<A   k! ! v0H YVQ7^~]>  u]?GXd8JW  <  z" hQ$   (2p . FErH-L۷æΈ[+4`s|Ό I YP < O(K x|o  B=!P W +pL vczy Y? *2]uc  Y& O fc 1  )auUYn<8̦XϪIs iE2c a dG   (z- r H!Q!%!! .; B@)m   lNJa,ByD  yA _ ) %dGvR &o] 2=H &V<~̯9ulջ˲̽|[e  j!T  sj&) H` H' n "y"## d?en/ g}{I4 u\KDwd| 6 < XC=   =  <' +'  Rz5nQoiMpA?1%f=XFl%fFbo`!YW$co_wx<ogE sI~¶XŷX<; ۹!%z A  1 o`!,vHcW s O  K  fr   0 2O\}|   8   r  / U > c?9#$!fւ7ňك $  {: X ] >A . # U , {$ P^e;~"= &`)i]+$ *[(%"  ,6,J(* ?`=%-ZcĿַKUy-:xrv 5@vO SO, 8M| ?~ l $ yLK^ ![%~  up  SgFr XwOi-M OJ " L   P tS    k  $A t  - ] N > 'm Y J|kX# 8Da7gS:LZCr5"\ A^4+R Obhn!hr&ep/$RַܗX01FI{ 3]  T8 ' el,j Y  $@'?)#,N,*&" Z Zk<* C2{{ձI4Ů\;~x B9u F\>< v iw   z| . eY H g r= ; =fMd> W svI'M - d n | ? O      4  G } t "  |nZ$l9Sg2 6 P]S)(cSc^L )U#K/iE?t%3"c=VYߦU! -g5p>ZL2i[ e[#  q o2G4 e& !I#q)$b%"%4" ' |m YpLjP8"۵`Zo:<ӈUY qq  , ' B  G{h]&(  6f  E5V{SZ  / )   5  F0 X Vt!Iv.PM, H'!Yxx"oG@/\-{f Z ?c1rfE% V8t n-r ;e?|Ej6̘VȔy̧˘>Νߪ:^   N'   T eT3 U  zt#%cu%0N#}t" y \^m I-޸đɮ,֮r U^yW r  l  $ C , <* Al^ n<#.N GD3aR^iy; g w[ ] ME  W  1  q   r d;qp_+~;>|T zWa)8[W`HYzQ:}SQ7?R`l#U`Fڂ9weR8} a Bt %()m*{)' %p "];Shh  H| )l,'ҿ"da)2 ᯺Q( T( :  bs ? k#-6,mFn   ] F e  K B V & tt:s HQU71d  x9B : /d:A &    ' vP?B7&qh YV+y= @mL=LvAV-Wck@]ci[`*TԊ>o=\*2 @< e  ACo6u]   x  }61>akfXϽk&3y9ű!ݜ$* b O=6 d [  S5sF (S @ tVx `IiYk 4"/|wgMuBsd% +o>h'N~rv #' ; Jh 't_4<,[z[.9SvOB7% mK@32.`'0Sd{B(] Z #nU iG Qd5 Nt ֮ǷČɲB"4E5IԔ -X Bt  )   - { 3 t L"r ,|7C  | b1Ly   I N J  n7Q48oim[Xt4R?{E{\hKF<<'7d-LReD@l7 MZ@SqB+eup.X8-Zw*ف)5Oz+1 T q$% #$# P! ~9g# Z rL4}]~տu3TW(Rd=c76  L 7 { Z  ] ' qX < i.)@K$~ r iEA  N )+Y=t2    I Z E M$ LQI|ih 2 b q \0 _ 7Py-jXdkB /rp#K~}/$XvI1+VAs)7F6R~l)R3~sJ`ilkJ vD@PjE L I  5 ;yJqh'-CTkD09ʗ>Ѐ̆lܑl7+  )  u ]H  ; 1 (  7KSOH! ##&/&`$!2  ~" h)h ]_*Vү}C~MX!0 U G r [ ?  " "   H  @w5 ' V O:@%e  M g V 6  a  < Z  # K D U k Q H rAXJGiLPޠu?٥ږ4@) '8 zNmA `  E#IzqO OQ-U֜ݨVm ~3'cXq QIZ[gg-}   Z  , 7 r %\B  3j@rZY!3`0@8, yeEd\u==KM5HR;K\e93RH'FUSR[k #q  7    W [3cUz[; - e Qw F= )   {4 ``9   mGh   w  k  5 L 2  [~t+O9kIKR I ) @ &q yB, ^c |  m eD3:+ W  Wm Jg#m~;E {bCYCQgc?5HVxoE\ K q?Wfc d \[  O y$enzfX+.޷” ęCpn! K  lg u -,iP6K   8  My # 9 ) W } Z t d F  Nj_pd@E;Q,oYr޳o,c i 6!!"oi"" !A D4 iLX^OzX w//T$8!!1mׯ U ?l =   M+>c x ui -  )  G K/   2 n T  j < m rk 7s(;jRP7CRZ B+ [xN '!!( k# i bu;h$R "'kVaO۴Ȗ"ɭ̑ZKTgf / u ?    w m h& " ^j     -Pd#Kh+ L  TaB5oKTܡ7HDfLG3) I $ w   R _W U '  !j}!n P9 v,a iEDlGjFVOcҝFӸh]r2 %   t g )   D   5 =   % @C = \ic*L %oJ'p1݇5g|DP  B ' l/ @_ 6jg0b3~xY@! # 7>/y-{bV.xdowA B >   "  5 5~ ;?@|I   q?<HnK7o|OBchKx Hy@ 4b62Y4BU;5w)ceb)=Mhj1U 272.!0v(;IqI nC-/0K1R;eG6qI] Ut{c(_%8vM=dpGp1AA` 9g4;6Go8D9hGK[KE1 xQ0i+S41ugv/,%TX%SN-bhE,296|n/*p:nfd&#y6S@'.. JV7w <YqUK+cHh<\ ZRhmw'p},//*4Vcnh$Q{ BkAjop Sgc_[Eqz$ho!Mh   rm}X|_i)OTM;9udL?)J 1'e;. ^S&cuLLV=D77>;&Vw9R-zDz,huu[r' SfcAL=DjHO4P(lMP\p@=U)IA2GfA-~OA /_K3#gN93R3#ZcYRxAa3"Hk;YyF`Vn08 #vKY : )nu||&d"g#p_mfI13 ; =\8;NCVR& cAm"7J"Ci:k0yxQS*B)B4F*bHzc:[jQ-jIt`Q"o1G.G<yy .Gi(7<`=#"quwFPBRAfu)pp''S"8A\gk^aySf 0`'9(O _7uHSR8"c% 4)x1BoSQC3BkJ `8Z#nD4#A'PLWR';-Iuk PuPPj4VL? 4 '7H! _m9[ XfiINru0K:pu`L 7iR_wgNdgn3X3X O f-HS~rYwz0A0dt~^:7xO,Sf(Y_&ip|#[%ntjz"A0 W qa@knVkZ !XlX\J\ 26+XZjXDHY)zmN%9=MmNA9/K~so@$!Oabxq-h r'!L`4(F1Zgq-k`([?Wa@zF}^ 'P#^oZIrJ g010a}Q12JVueyQSJ0!.$ **8bJ;JvI{f.Z1.Z(8B__fwpXh TvXrPX<2Wsv{fw_pGc*X1a=BQI~W+ z y"1 1r~C@3KI_3K w.,oskzfiQhq;9;o=V$$ $La;@o1a^9\;. ! 9cJ;GG@BG..K3zM"Qki$oJ[(9Zk@xe`#^0R* H#P`LXo0!o4hq*V9r8e@y}}-8`;nTWccBZM}nzP<*y9Wr(<X7$O';2~YO^?=vO;h:H80O`o'# YRRzg A6uVYjA+_6(+0!-J"|-=#Q6mCf[@An QzubQV_nXt3f#W?Lr jp+b,ORqA3B q,"1YaYuZa=*7" \%W:= kWR;r'Igjroj 844zaLQuXH#B$Ob8ShSiIkzy. yx^ukzWnogir[^bkVaLLk, "$*(@ < .BI"WP%[C9 $B"2\.  JfT!_Ks_<!1BxgO4PH$+C'g87Iv[vSP;W(HQSF( ;xr1n1S#('Hbn32<y+!(<ZGJ8@akl%Q ~G3"CJ8^`QW$(O++B!<+1$?B8vY{q v'HYrAfS,LB -^;%R ~|qgf|[fiQ]u~gx , 48,F8I- O4H,7H,ffgZWK'HWSO4cqK-q]1:2:YKR9_i_nY[qwqgq~[pwmOn z);^#a7%?rAcDhPc{agKy+!8[k0O9a~0j8kBHiY4v? YFZ-?^*PL0~ ocxSxnyk{03**%\x{g B+ ^!(axQehg87?xB7Hg nnuCi !8(2IoJoh"3C3(C3 ZbC;(!1Z%cXSv@GI.1QB  knFCIL<[2a[<PLCVQ1[ueHrn}Cg  n= 3Ssr3eBo +qKnQ{!}IqBCSXck\CD}yu^;'Zi(- V(g<HbPVQ9-I'(4;'(aS X@F-i$W*WV[*B?I4q#BO!#C2  V; Y nRR=*{vy1v{{qS`1) % xtK# VgEcRi_Nj[_TFW[F^sJpu g#C=[<?)j 1v[NiG/@x;Y ={1 zj.4dS)|:N+[XYmrS;ru /E:jCjj&P7͓ߴʧ,1ޤ"ߵǥ:cf;Ol*del W  ZiQAaX q   "#>_   ^T !tN1{Rft0.rMupl1h5Iy$(z %"f*+P{MT  % s4[F   H5  6 3  e n(Y2g<R  nVՔ۸|RB*҂;nk".,f]gk݋%C} qZg i 9 9 J E  mH < 9XM[ U c9Q$VIygj8Mv@hbe nG   1     P P H    wn %  XG h! ! ! qrm oG 6%~ ( 7  S x D  8 Z bi]~t!( {(qoPXpI o.2lCh) iucBM*q_Uեώ K^{~g.c P{"-X0 \gx}S 1  sKur  UX  X[ 0%  O  $)9GQ p- n-r8jq?afhe*{z6\FXOnCm~9Tm=@j!KCrCa/_pEu%ig**}D BL &03InVE3 k/wj^eO!Tu| |v` ac#t^OuN   ;gSm   * D% :  2 9r)B 3 9zP>'Bj ; D   d / 4   < ^B b H  BTT<* ' v c r'SHS  u     a i "  { 0}%][;DbS Gc 6:.Z&݆׶0ӧHL ˾g ̑ҡcg-H(H>B o\ O0;d/  OG2  Sn Aj1zC9OQ JtP}UTtW+p 7   rX   7. S ) J au2H[^e3uwYoROqDO~  &{"#+O/12X/#_W` \k?qs)IohoYe6Vك\Ò Zz•oZ~.Hp .=\J [x-5 =DUO8 s-rNV~Ra[McY-9{Y :  > ; 94[f H ; :  '  +I+= 9  m I 4 i"GXgXr bb;[L| 32 )Cdo |VHOXU޷HqvkYΉuj\D_:],DS16^qQm!.o XA1 >Al  )-xpC[[vSE_aXQq~-E  E V =HL,"#{#."+G c  Go sZ[2g@ V  c ` O?&)k(X/yf>@tԛݶ .%tCz˴T~#,(:E Q    .pb+ [ 6ZQ ( A GGaA`QyW& 7oznaL   {Q > l P  , 2 JvbA     2 j[  `( 2ggM|0'D.kʍ%jP]ť_;DAX,r* \KI t  aG % [3Y\ >f6kzV 1 $ ?B  a  n $  L*vJ`@i )  Hm{ZQڀEE oŨdĻ(QĭJNM۝Yb b u bxp U > V f%  * a[<8I qj (doztTh"8-d  , _ 5    :A [ F  L     V e ' k # 3`paNZg(51jXQdԄjLɟMU[!Ww-ig ~ zW P :3 Z~_$G$t*KAk~ l3liwY\  & Zs]5jnZO?`Xo#jءĀD$ڮ٪ޖ ŵ 5 |  \e}$r;- &  , ( L  K> szqjTiZR  u &(l{beMbRE.0 @a_6NwcTHOzAp7d =  ~ Q M 5T:cO8;rgZ1 ? % ^A/2|R ιؘܽ0۹Kc ۍb+G 4  =KoYiyG  H K I N# mxc>7sBJ\XHgj ^ f m 6 6 F rD z   K b    <   N x t 9-)! u X A:-x`uwK /Caߵ܃`ڟOٟmn6A2kK; iH : 4 0 9 l &#|z.*`;\8c D x8~`8wd{>ډl@ۚԳ<'7ljwudR @ '  6lag9FL  $oi$d  '3?}2j.~^j 0 h T  F H T e A` ,  ^   # G f0 7vL+V   /CP q|3rݛ a0\ؔڈ0L~y.: JZ g  q saOJm(wyJ  fY-2g V"9Q Ρ7'4VD <߿_d$EV'o  0aq/ \i= V| /k f1  = |j q>A(P$`/ y D W R \ u  {  kk T   ) er    ~ *  u Y-X.USX$kݪnذ\LxU\Dضcx>3 *5 I.q~ E 50f$Z]Rr K 4  + [~y!2,PߨU-x!D/5ƽyȭcҶ* s  )o Rn  | 2Ja K }  f  X<2 dT #+F"v| Pi' ^ P /  m.   Li  G yC,4AX'(r 2x   a#   &?)'f[Xl:o1AZd2ԟϓ;-    : ! v i )Z~?E 8 9   V d|Uua9YΨúݺށǨϝ$xf {] ^   JtL >C Wc  )h n  r ,!K xq >=>|NyT9Koj   N   K Kh F y znus.|) f bEpz,  #TRB<yN%n+α^9UAF 3 Z 8  cJbl go;l (=' ' Ygx TNt nl),.OYR[x'Hhz[ʬ]O G  L   L6BKKO9Z  6: h Q C[  5 ._3eBt)oqa  ! 5  3q Y d  N [X^ r H " J hK/y4]rr/&vjuh\9ty[QJu_.% Eo{t z- > 7g@RD = ?8 nG2, Lv *@'(ߞ?ץir>÷?( Zq4B   F`j8(Wz ,C Dt Fa K - BYN<$r? RB@PWWYwx ;I P  3  < ]  ~ mb   (~ j h;8r2f6*3#Nxpqi]aVKح{A& F, b]  # KD$ Op% zl19/ g  *'aԜ:ȝrWE?*bM1Lȴ>3އSh^t T K S0S  G  -  a  F Lf ]v> )-!(OVuRyI1^#d $ Z   i4 oN c t , T h dX Ak @Hj.Gs((3V@S87T}?A9v \sY  vi'2R-QU b B V 0  i$0'  ϖ׸pŐ,lXȿ?>nx u /  llDT n a A  2  " m  { H' 0>&oN|HN[7 yx +P w 9 Y  o U J H L ~ . |3*h  > "M]6"$Xcu^a+NNogM8VIN5FMu Q]n$  6A R=Q_"    r I`DN۠/¹j&ǛļCqV \  s  Yk M - i y, < < ! yr  ; IJt 5APA vybI X } ~ h 3 7 $' t  g q* Y  8  ( (  V'  WWaS<;8C7od}':(! 7vc9h` M !  O !e6&6 9G U kmo_GK7&o`7s@6]xB=3#Ȏ` χa <] 2 3 9 B" dX N  j L   dFj} H}gW0* [0TX  @ L ; T  f & ?w ] ` Z46EOl   ; ?NR_)5a ,0F@byF80vk6g6j^G^u ! P - Z Y s Bmhcwwh eT]2q'^}2ށ́FiД>=yLccTl ^ xK  $2"** H  " V  D 5 " -rx*Kkx(RZ@ E  ] i #  2 o C8 n $ I mX F ~ < F }DXhCRUAl_@5PUz, u-({sj+ 6.   <8W Y = 3 m 2G;QSU@Tz9D_ iDN"/$Ү$s Bح6ߤy'c / 2S &xAi ,h   g 7 v t =  QsM  A  3QQ\ Y  z u   O Lp&FtN=]D n[gckFY$ Ce )eoq 9z.   %J C jAVw 9|;t&ޕ ̦́-̖د2B_  $ T+\U@< J#1M2 f   0   o K]S3d0=VA~?9  A  ;  -  _  -@Mf MiPyh7aj3 /KIiAD4$0hkmYQ=(1Ntkrs%OXWUCZ_%9#a,*hGsaS : ^  gyLJ >{ZTv Lf{I/Q߮ԲUЯ:HCDI  w G c lA Y$ 1a ` = _   YF    (qo D"v2' aH ,-20tvX1{3wYNr-_8y^_p8VkV?]A'rW/*(ܳ9~V<x,B/d) & Fg@t1D@lF(.  r  ? Gw .,\- ҙ2"0<Tq8v]fu 7( r  ` uo }Lv#~@ f #( S _4ejnpz<Sa4/ 84ajCO5  Q $D 9 o6 ;, ? y+/([-N]N,נ [\C~gO  hN *YB4 <)*K Mq =  o$&On^ e !aP$ eW8-m@[N4v*4W* aY V  B q 2 " i Di 1 b %(&ܑK8$Z!߮GK@Ip:n7/w! 2  K | uxj os 9'iX=Lu]w۠"TiܧBx`H "  x_ ^ ) m"#  7 ]WzEڠں'TܡlR#A:   _"8" !b 7C guپ}ܑ&-nuQgG^9 3> ] bl a"#b!\ AV/ EP޾)0j*=697c'ryAn X V*  ""  LW 6CH C~#m[N=mp-Q   gD 'p!2"U  ^K> MpKd;2َrh$~V=e[o` K `)""m!z* e > ?.OhY܇8Yܤ4K(guT K{Wr @9 t:Q*ov##"] 66( *87)VL!+LmVTܖN ,;^>1J1oTo' D2I Op ck"$\# u ) s  '.0t..H*Q/-0jMx  h K$&RG$"1 s$0Aj jzLdxد . a S 5i02fg.`&!_ 3{ UV%"K<&`' $i\!  Kfow+gط/mZY f eGe  r <H.#&%{" dyW^^Z!׵ْcDG< pX =W\8duEoCmO Y_ ah%#'M'g')$c  y+b$oiBS[ה2%؊ޙh!  /~~[B b;"Z/$L$_#L!p %1L ~abOJۚپܬv-8-'  )CAd S&w   QB R#$c"1 v k. o#>nیYzۙ9ڱ# gTf  \T Ahmn" f 5 h/3"%`$! 6=`L.?ڸYۍ1vBVOY n  yH}$$Jek x aQ^i#J&Iu%,y"] xuB'٧MٞCK.1+ 7w O /R8  $##F%L$_! &i7 Bo j1Qa . VD [Xv!$"#. # 7\ y!8/ؽؗ6A\ODH $ q  ~D{HfkT,Tj ? Y`. $adc!D>$S,#0  |liI۲5<׳pdM5ۥ\=u + &  ?jCBU  \ y{B!A#$ ^C|ܚ܃y\r4D_)^  x  p:  5}F7  7  * /#_"  Tm{ݜ݆EԨ+(|=۫ Yp ? e _ x ,j   R 'j"`#R  R?ޣۂz.ve?%yډ @2J _ Dz F`^ 8if6#8" ]F]܅-Վ[jӢG,ܩ^> '1^ u "  1v<  A N_x ^"j V*! F#N֧p&"c!{} / (  Qc8wr ] ]N(R+, f+) #^ k5,'C܅ܤ/: 5 GQ-v2L&<B  1U!X)wB-z,Y*' K".JS3"A< rC )j1&zA*2+75 ys!i(,,yB*( "c_AI//A#j܃ݺ'BV z_"xvd639i< Cf!(,l7,)& !{  slיQڸ1YJ:[OJ s ?@c!ii-1;q># * 7C4Kz%+r-~+X(#0SSqhNc0379K O ~ 1` i0E,B I=(4h-/-6[*D%,-s s d2$׌ ٙ\D = ZOvp!_fdpc  iig  (E-D.-)k)#2qn߈ܧXөxԄsF9S< .GE u nvouwvDL+Y@ _!)}O.).,( " Oj܎ '.,sDamZy y `\ Nr(#aNcSJ  _"z*m(/{0>=.Q + %u;.pb/9"U+ c !vo27J  : 7:!&*z+[*Nf'u$ m%!"O؊eUG@܅BiF%MN{(XB( 6#8.$)h*[(%@ 9 /OٰtܚAmeB: ByY Xls %> X  ;_p Z$Nh/"b=*ּ2jY@(gm #+OH @[-N k^ #j p}x/ E i A iESi!:עڒLLsMy K A.l7+QB3xMY" j Y 2E"." i Z? >-r۫\f(~K#i#l  GCdX R[8AbPy| ? ,R 0"3T!f m nn rKܛߋ+vK*5c 9 XASV7 ! m  G $xy A+kݺ<`a"o) OS z = O ; s E|S,WV1 sPpM  ^x9wqۜ*2ߤyLߞxx@[ s^ d g   RW  Z|8*Y_f-KY G <DLxi8A\WgQ{W3U & li J 5 L  G|Gl9rh"z#  aM.3Z4_p߸L1h! JU  J fz3b_8~-f`s Vq !n4RDO%TH.Qw9H5mCme@Gij O Y 3?B8$"uy|`  T)VX?)x h1vt! M 8 A 0 oJ { } w\f]=\^x   y>>& !rNli"(rOxed n s K `|Zd { wDLi'~CDsX(%\9('4+%{_5?Q;1       \4 p}qTqxC*JX;JfJ/KT?NP-~} 858^ e"    x 7? L SqP&Ga6-Q171?Rx#+k*"]Tx'-mwyiT in  k,a'_?Txp\\IE$Z`6+Lxv+ug'61Z-7'a$S1((y=F*-,k(a`K^-AU0lOX?n/\cJjbJlJQaO zcGx,Q WO,o,-FB^uc+kF~Lc@mN's05a}6g"p^7ADVf*:F=#Y-P^WPWG2ZzY h_0CC2xu7G!_ e0:gN[g#0 $J8P*iya +J2vXX!b*$ 9 H<eJ;8F<C2BS2J?Z^F^<[v}}kxFyqLPbXrIuqo[@CQu8I;O4gr2*;`+g*'R~kk\hVgjRcVW:H{7gV yr xc-Wx;Yy4?BvY#0,1,-y v%H :41`?ff#3I3YD-\SaZ%0F#%3'R SI4S^ZZABB{ArDBLA,Yk4I3`gWYngBS%x-u,u ^*L0jZDZA?P\v\1ag#$ 7Q?*@PxuQqi rZBzxQbLbakzrrrZuuzov@4rO'q^Q9^OWWO(C +'!!  '4L;* J zz27!2koHLnhJL8;#< V'H1L#'B447+ ( 4- ' '##!$ I+2$ OnV0CgFJ 0 1h+(@CoFh}xJ17[S 4H08`qoOn`CxqkSu7Sh7Rga'{8^ x  - 0 u  =  }yX 7K1dA b9f*=|  "? !i~!"["Dt!  uL  @$Va   k GopC:][QϗپwAݷ>v(߆ )֚AxL-  v  gR @ + + ?^ 5 ;Wq  %I2bM\ F%q`.[f>X!B 9 ! w  h ; iu D rx * a H  N [W u h, Z8 z+ yW  /GJx0Bc}bó; AZh>  X + ? &  } k ZM  u { ^  P W  Ax   M~W5[b]I:] ;D e ^P 2 ,U 7 Od C T  ' V]  h$, YJ  "Q$;1.Z7QDݔ2@jFʔ,   9+q } m  V  &~> c  P |  jLH^.'$7Tw   a bDY5T  K e 2  }> P u  x\ S VXP'Alh?&/DpܺȎʼnބ(0u1)X `)RK t 4W G RQ@  M d6 : Qm  J  Fty8> QZ sm8.CH:!`  x < +bb7R7xJ    U  > \ J;  <:b g U Q=)|E:KޤpSۤݶñG[P c >1 * BR 3, _P F @  C  :5  "<^  BFeg)"5qHN Z U   A([z" J N d JoNZR ?  )$2yi?B5:xrïCwñɟ fxUqL  Ik Y| w q  m ~~ U ,K,18p@  x+K`|G ^ '  P n y P   Y 6 ( N f 4/7I36   !R>s ,ۈǣ؝۴y0{|PlɤҡBkyT  8q  } Z " < i ZhN 8 :Kcz e )     - 7 ) c_^ ) m@gc f}ژUg͹[ȄޑB bf ,ևWތ* w (  2 ' & B0kmgO:q [ -V yT" cc' 3 s w 3  @7twa( F u ` Svw  0[B}&}><p!ǑF׿ߧ+1 a +   V ;  J1  V ` 8 3;= Zq /xu_:B ~ V2ln ; w '   "5 i;+BoЎR3[\ Cִ͋ & e  u<  ! g  /  8 @_^| 9G[-Kr&6Ke$b i < >  6 N  7 J I vK$  [ h Y  V;K gu ]/oܮ0jʧOܵKi%Dbj7 . ]" b 2 Fp FnU C 7 1a x  @  y qQ  S ?u; #  7F * l   , s 9 ?u  i }= t 7R+`* ۸-Nrs@Z@͸x_y>It3 !  D7z`aI W J S5?QnN 2#~P2 8JH+& @ 2 W <  ~P CCB)"}    H AKn  k/oVa1pyiߴϖkƌ pP89wiVP+PQD 5  %h- z 4 z mr +y  U K  H   g w ;W /  9    > _   m^  /gdjfԍa4q#jnv7}@S_TM0cjn{P0% 2 & _taf-p0I& "~mEe97R`*oxqBpqZ  , y }  - $w  1 T Y CT;  =KBj>nE8$LuܲTڦ S@~/ \-  ,   (Z!TxL xZ # 3 d k f_e """o  9 u'v  z >3bQ/'ёdKtFսGa҉$ky E  2  A  A S W,{ "] o H s V4OWs 3WeQ 8O#,"   8{ 9   1 Njg u  t2 A  O"U H PH g@!( 0 ۉGXwUBĤn;(ɡ7!<; ")O x: W2L)?wt  % -  b v2#I j D Y= m f+ pl*{}Cgpz}pss#nuJߏ6/PĖ_s!3 `S  a Lf j K.  ` F f fd\ 1qw]    @ nf9 o W pHrJ8RRխ!Dz޿`0{   J    y = : Q 5q   + T*&  { W` @(hP ;cM^^YQ _ ` 9  0 W 1J\ s :  ) %% hU `}2z'%_1@;Y3ٰcQ͖+[XȦ_C۬ eA.*aE; 9g9'xeO2h,>%` U (8 WJ8dp \I;{?E2'ݨ|pY׽3p\㈽YS s * A4T,ywť~˳0׌?4  w  B; ;R @{" !~ "" S < x -Auk:|_g=h-%Daûk.*⿽=K-ݦeY  p$Y # CO i + f R# N(  o~ ?= V )b b; S kz9^ ,Kki}, [ - 0  ! & 9   !{ " { 0a  fI z I B A, s r 1) hbcXH0M@uj0if JӥvN/n֚CS<4a$B *lc}! P { M |o c u-Q}fx]5$kĝB īS˩ץi  1s ' mg*fx(si" d?%XAv q1C~hbI[t[4 n r   X T Z } ]03H TN#)8xq ?  t nD5m_VBm_ VC>:#J zK~ o")  ( Ul+k   V '`E]UEH'lu P.ް\5!=2 7slpݶ9s&E#I)8rArQ&" $   ] W- ZU >{  13"f2'Vw.  I   V   x =  $}"';dGne S5 E - P5 *;/ 'Of>:'Te ~yOWGXfi V X M|d n~ ^ c Tj ~z   n# (3 Q nK(c5Tqbp<ֹOyt܇=Y.~(rw \\GvO%L) { ?CKY/ 45 s L[df| ( H DW H >  A 0 O : J5)i:KK^  -l n sy ox 2hf(NLcCl@Z}} hu:{qY kE>@_JFFg  09']/" v W v W @ G]D@,ChXKo Gf ( 3e%!d J  G     3  & q  C   QSK ,  _ y g K % <H;@ "qifK"N-x_X,m5  ] G 9M  S3\e.Nx , P~   \ }Fb?_k{dQض\ݘGJyM_I9vM~(_F\2-4\ - P |     u  CRFuk`Ak9 "! Q! a } ^ I@ <C l(M\Hb:3P }rKF%C >2-F9<M T  w   ^ L    < hhJ(?E5OQUoY{`MAzTli/ [r݄h.IrG3_)l L  ,h o h  9 ?A 9  G  1  *\ xg"%lX,asi8s7.l~B\=iq,  } 9  t > m W+y3  > gaZY rh l \^{8} a qK=;c 0 xl7G3MF.U]|}2Hx!Y0/MP]y1Rzx> 3u i w e  *. >   w l ;:vZ1e<?{ 3 8@(WOk$V]+|C|4a| % u Z  . 9 O JYu&c@ h R  m A4/+,:<|~سt@֡OB{*cL [.f@i"ax b{ Y LQrYA ( |u  _' f8  ^?CNzFhR\T0iA * @ 7 Bk_=E~#6  5 %k VW2 &K A"%_7d 18gvxڑܵk_Rc{ Hj u 5 /VPpaq %Yz ;E o /!JE #c`]c ;sRG0iR{+   E4 O n   i: N @    MoHW x0{Xd7܃x no%0np@-T>)DVVV + K v fE  Y  ^ KT?Q{K5(h.r!޿ܩ'r@> $ l [! w  >\ ^ i4r@   <?  >> P   r :bV s .1RyޮߐޝW V  sx ra  NL   TSA4 a J  : b m fF u Z_`u3L  xU4`z1 d?We%ߴ 4  nc F 3  OBh@4!a2mHh> u1mM C؊ha<# [ T WK i  E8  " 5fWh_o  ~%jtW 2  % {OGW=8 Q1=\yZ,3^(3O 1 - { . J  J P \ x     ( e A{Qe<oۈdodܲcXx m- 2JgQ /C)1   `m Jw;K_   R- w`o ja~FFu y2<@R aG8 BRN%  #5hp ~  8A.~ 6;5`?%ۣdݽs}N,S + % 3 p#o-|)wv TZ*x|.HyMU'?9_n6':_C,#JG%  9 2uY! bO), V}  :]PRdX< Kh!om_pC  a  L  rCFCF,L>qRH ( jV)|>FC9AJ)Ia&XBKtKgcijj  | EFMr U K s  O|QTp%.`') 8Wg},)= I3   :U P ylKyN y Zx]>#XR=\35`t bf<?jW *X y B*2 o( Y 3 _Pfa|i#d.]iu2re'i.; r*a 1R z ,vcp7+v + c O 5j\A2NjtS^@#j@0=P78hQ~vKjZ Y t b*CSC%i 1 nI %% $eD z8Vy=Tw:>+Yb~ts+=3Y[ `av=/\YW    R   t  3 9 &Gm@k1mHB6|{n1:3uu_OH~@RCA/J` $iBgbDhcfu=[H"}j9w `6r/nV:?i=~"Z%;?-oA=~D7SkzQIaQ32 \RaS=Thz1;  Vo-@kkA7'rDS'O#jvWevIs83bKBC%++8boCZTz;SZPbJT_oQ$ B=5,   cTGZ,zpP",WO 0 4"D<5k@8xCS}n*?!rynq^n$-!#[1F*vMQ;*uBoa!V74. $Z8nXqc~K g[WCa 9V zyvCHJ?xiHrxZkg^yX{Ln^c`KqzyW##hq\,~Lygg14ISK`f %A*q@ )0ISx**F8K !Bau(#c{Wk?OnWRkZVcyoYPSF1 #  3jj~SRRL?Vx?WZ7rWtI""j x4VE]K>jEJYH6ERGOC0u; \v,VHv#%-\fr%,)HYy{ZYhLgckPyBxPiVnB!2 9Vn 2e(PZ4LH ?ohPa1aY2nCnjS38),adn:(+*K$'  1Y'fcPH?YZyj\^ka~`ruh;{g[k nOy*y<kJx$hraVVyh ZZnxSOVOva}e~Bvg! khR7j A'x ##1V @J8`C*HPnhMG%lP[*J.8+B<~zW=Gcb.KP=8c388<,s1;yG{=KB21<rk{SZ"SP\y;_gIo +-4s=IZ(Bb`SO[JC"Ofh=P 4uWx9QX}9-HxH+4L!+r'WZrBP -+JQPvruCIO SiO7 q-#S K#`B, Lq8L RFDP)~,quY|S`gc)k7|^`k8I"u"R^r="-YIxag09R7,r3_Ob~_ditw|Xt2OQ[2QNfmT+wAieQ_b=-K&Qq(:|f#4P4_3Y"4-''r{'('+ynkYaB0Af\Payn{aIFK*LAc3~v,V?oZjx`3(! ;F kfgSo uRqLhF#CuC?k1<(1k8yk`Sx$(,e x%Phn[aV0u,xMfx1CWvflP1S-b[vZBOVz}kev(nBnHiWXeLZ<$h#F*@31 }a M+_1%B PIT$1G5[" y c 2u".*%IS$ Pr"(".Xb2L8gkHSW-Db:uoQx;yhrX~0hS1-3%8xZH'{DY;Z%,` Vy#xq# `K =DPYa8O7K '7:I'znptm%4xxG+2&)g t :/~ "K7;" ,:D8:0A0-0F1Pg3r`vFRg?K?WPcxRfn4aq-I-"^FPOfhiHBVI7@KV$8#!*+B!$V:48qBf8~I*S){#%cV0=IL{W-j"ccY#Sh%8 K0c7h uK~DVc3? RRaSK H\g~ug11{WW~8x8c~7hiHuePLk ^ziV'2Ch*'VX88!FLeWz1aIhrhCXga8Z}uik+= B\K G9.WP\@8_J < i h+oQCZ@l;arST!!!8 +%; %.(($!++ bqrZbiuyi}aS." = .=5GKP.8QB5M<13"+"(*5C9% "%!^#JH89 P*P9??PWy%?hoxJoP`-u8<z@e1O!z[x!n q<#[^Xxx<o7?v<Vx;h7  Zg`Ong$x*VHzx}gWkCVnk[h8Q?hk}^S$VbBkP#(-Z(u`@'19~hZ:qvIoDn;x8?-^,q4):= L=% =-R)=  ?3R0AA=I:4#IH- I3u-kW"'Kf r8yYonu7I`^0YoWVh,-;~*4^1L#^OR,:''#%Y O730F_wt -VjtiAV VS='% ;V4*j4?-)%R,Y-1FvF?I*R0Z#)'"A;f84=ZWFIvqxuh-`h`"{;D;HhoBkv\r$ 8O#urCn? C( b$PXZeMphcprlp.C5Mr::r$$Z*_wQpb}<d&Kr:b =3aOVo>)YcZ{TT NuG`*BljqcL8EED6Hd  ju)4>0g@]h\Mq\ l  c  z 9  S5 ;dMw  ' { +H9o3=!D%<؆ՊӧҸ*/ӈ o6ݯ_6QtR(, o2tRwga ^  N  . U yW +CQ- a |   B   " x X  0 M w- [F=l F%  GrWhwe aUrg'rNy a,017ŴYŗƉȁ>)֕m4%Ub[>(}# -Cj6qj6 's g NHIS)?v"gkM|d^x  oA @  p m0 "X  ~  wS(c"q\  N n^/dVL,{* eVY.`-ߴ~ضxsh{.꿛P#-Fƫ̆_ө}bBx.bXqM##a ] t 7) 8 6N  I4a`e5:lP`[>Ce zlZQ@1wq,  gO k i & jd_S3tpj(p  )`  #~ fc"@( R+V̀7'=ôfFX/gmvL vmz ^ % ] .  #!Wa ,Ix^Gz]a8]D O  X   m n ! ! m!L } 0kEOc*{Er P ` w`ccHq|4&Lm҅ʈpDw顿Ejw͒sHD|Y A J I ' EC w (D >B( is-u lG"A#:OK#xB)>) 2  @1 w s U"4&U'' & %g $ !\Y8Z   D    T Gr9HE)fڣeK/[ꉿ2Lh!m h1 J8 #d_ :y L wo J P H\GLS cvL A 27S#>'{s? ;, + Ow  | ! &"&)* )R T'# [& l$! ldA % $ ho 41,e{(z4Wx12 *g4   p ,N ) g[ ;t3d)e.L _ vEYMY0 6\Au!_l>ExkH >'"   e " & ( (# &$wz"Zf Ak"1n( h 3  h c^Ez}<] g  O r V' Z! $ % /% Z$"#e Q-ap~_    >j($$eꉹ-G&ӵ߁ ? : "  !  [1 o0  Dm $f  HjG0Us2y  8Y"."Tm'7K!2pO=u>  VYa  e c  X!: "E ."= /!JpfkY>y]E H   NUd40 |){.٪/,(ռsIws: %e ? " z;b4 Y p goa8'9 Y9?94z]KP*D` u FBXu  > y1 ;   Ed0"> ? ( 7QE$I<`jjɗTʺvC.E@ ' *  @ {W Q z +I : k3 {m Bk'%$ F ;v^O|nC.`Sv |  _   sv T, J  *,}Y,~S4' D  N@zsDҾM_f<.f!d w o:  llM]+ 9x R M t q @ Y h_fpBE"<v"C RnoS)- Z+} e4HHN   , ib    1LHxkPh r;'PHAo\c˨>\룽~AM5(Wuy[ A  l  u &  ` T 0 #[ i"Ey  6'Ak3ex?72wF^7Ld ] b` %$ h  d  k&<W)[ @!WMycwې! ɌDJÿбz# M ; I  A,i T S y A > 2)9Y, $`   D! ](ai";1Hg 8 Ln lp] l!z$lLY;T|)  !q+!vG$3qns݃. >j `  G 0y 3 w3 | d  U=2 Hj G j K_ rm_ { o y  &[  s7 Z>R:Y5H  |0xMJQ4_Q.ע"̕Jȑs5.͓Iܝ#b1  G jv a m 4+p':I?:l  p$ Dv , g ! i  Jh  \ceW! 8PHHyo7C.۝_,Ŗ[is8*d8v  W  H 7+ |/ )fh[T]1>w < g f&,-%-S %I0V~YW#Y8=  O#66v MYLwLo%ŋʅQ~cb 3 z dg] Z %? l ! G:FN=  h,biI1\74W 0xr`   >JUgUI  u$93`dmPFˡ-[iľ _̾p*Wv wv # '(. U 0   0 `<@ 1d  ODZ( ;Ju:& ] q<~WP5.?AYZM D R.<ޤrˡ}qs7> |jVu9 Y3  3 > HA  E ^ T;X2'.s b%2[&Z,2tu-_aZjrr$o ^ -EqG%4[m%sjk> 8P \y5^7^hJߐq/U̧“p¦f+ϛRp H) \k ^ O9 j x[%n :Cl/w- C  }m G! =xvfV6}!4;K + B<D.QpԺ[ã]1=N %  '  o  z !) ( V W Hr<Z*t2 Gg6W>5E) 4 ^ D b   M zoO)?Ku@EX#uT8P r9$nM=*fs_mDŠ Y٠D    A<~wW  +  % .f4q `?42 %--'X?c[A _ @ ;B JT0QeOe=|yl=y-L  <qC4Zx"67+, W޻,ɌakH]*ƟE!v  g   f  @d C Li [ Y!x\iAkW{2wi @ v/Oap,VX`sa @ s w`xpF &~Oj¹PzERtǴwφ!Ut , . 1 yX Q%Sv2J AK%, "e3  n mmSPkTEW7o+ZD3 & Bsf>$],9+/4#q ` >&k&}{|A_nOQy Ew&Ħ6=p   9i  j## 10 R (?A G!`oqLo G, !fQ-#Sy- n x) C"6pLT3 b a. -Mwie2 uZ NENvDJbsYs d\ǹ%'*!|̠^Ew O |- w = B d"xufuz yZcb  e-W wSw\g:ddwk!r3 ` ~);&D`{s_=Y a jt;? I_vSu:.;Vǒً D 9c $K c% ~cE s||#|!{n <`!#mDMe< H7P w l C 5 %46/1jz/ D;"tp6 V  D=-&eZ"d:xܰH҈=Wk#BQ+-;  6  rx  bI xU^rcQ  f  X F+yba4uJ,nZýEN'>M[ S 2 +  ; } +[ M  ^ B % dA-+ Tml1x~O W  (C & s MSo}Bd(q"l5 \  Wq]C9zN`;~hN]9mđjVҾ  G x z |ro8}WV # $4 5  9JO"G}| ]16m-( `"U  ~ c\  O ]  eoeT~q/k  JT9GPY9߹KמDjŚ\x˷cӘ9+  o:  { @#naQ \ Z c} \G-K  IY@KND+X3A.9L   ,=  pU>w)F6 Mp DqB]Pz;^UVcw@,%$́pG Q\ H: . ] $ \ [ E qKB/ C D $~s5GDe(S0W1-C/|q u j*J0Cw0={Q~lg. {  WX*k3`{6z[ zv{\{ňg?c / 4 Pd _  . I|-  W$WY 0k g.I"7^   h on8sQlb ' vfgc|% -́C%ː ̒-ږ,C  C  }0Y'  A O qgDp@l Z Bw=G63c.$[h  4 Z  YE%\NtY9Y,< k  Y T$ p[K) qcyxC E ( 9^YiGF682oX#ޘ SF$@I X?P5Guu:H :t fv .lRq%(u>    d R `w6]3&6%1g ((,D:[\#>^o0ZBabJF!@|_r|SIwz0DHf&+  P % Q    F 8 h      U n u5  { Th,H5EVx*c94jC4a n ]=WGMuwk+"x|:&.)SnF     BC ;t   \ Og e   %  KBs (e1B^- VE.0V A8B{9Kw+R|b(S  M Ow  G m  (x    O ' e  8  t - t& 3 } Zq\0#OqTSb qMA=o4?7"! 7tm,ut\r BwQi$a3 B~ ] Lq = U[ ,   H }} *  u     g VxY*pHYX5<2Rx@$~>rn\R  wZL{V&K^-[k|/}^:IJKN   ~ };y Zf>h. q   2O  s    S$_kPmHmWPl +/v6~ e7I+Ab8(|E 1- Z ~ = c : = O Hd _  l    * 9 OGEH(F$~@EE eOZU!;i!#PSA\-zF+ +6 ic  b{ + e s    : E F  G    ^ PY@:?p`N\gzTh>@ R6SZ::)PnLGu=8i ;;a;$DmPKyA]  -     dh#ib[gryy2J4=p^\!/l[DW[(jN-pK,Y]2hA(0pB# 8GX/MyB&)#%)$(en{5B C,an2iqoCk]-Ui fjm (Bm&W*g'$^$urM@G!lv{~]s`wlx[22^Uyy5 u!i2 e}7>"]&DMz@m5cZ<|oj;s\\ 8!g"5 Sc$-.<:cXQx; m5XAhy n{Qn/?X.o"2+: H-uX#Gk=d)oj`%UTIbIqg/ZJvl U@ \Iwq{)n.E5p3``(s%_}S[(f\1,5)-Fb(X!eq@<@g\F2`K"">XS~3eHI9ajU_]!)GXM. u N NkGHMWp\Lcmz,,n xnI 0 BX+Mc62,[|k8!a\=nq)NY]673#5aZ`3 3a,* B'@0@eZI#2ILQ[N` BxQLZ2^48OIH^4H^(hoIQ^}o?9 a4PIVJ{2~e7;7^v@(C@==3O7%0OL?j8 k~)R^-Z !!0qS `v xyy8knYALV] @[E Gb ]7*Pzijz"t gj=R7gI1<@^J eu9PPeSW@9!8*02 LQ!2!X1q7 $k* HLDIa;Ix{ZZVW1H:8:?8)rhu'*-Po7^ib<F ?72$1P[ihib<0^H2+S 8(97qW:K0PHL"W0Da=Fc 1RB \jFVLn`JBL O98x[y?y4k$21[,z1zJ$=!9  (9079[5KF[a'PX@s(< e[ha9P-2B!Hi7rSkkP2^I+Q<9JS+v#Z1[CFJorg<eC8+;B-+8LhQ*iPVrB@97ZBZq@7!F{hyB2`O<8 iVLxux  (2@fiWsvWz5MbC5iZr}yvZ[* q1Z^# $*44F`'~S AfIBqqI"%jq`kgZ\"fL^\IoBgo`g1=%SOIxfyg{`Bv\ZHaAx'~,r?-PAZI:Ya]Q ?:138F;qI3j"LOH:\O'`0==D=c*r ,'H:=81 ]YQOabXI-2i,]fnm gS#x W"~hcr,#SL=H FLx #hZ`o^ZFFPu}x 0SFSJ}iF$kSQJ?SLJ@F$2 bW W(xW0n9H-<1u'r*#L2$kgJ9Vk<S;e#nBBS7S2FCP +'((rr<WOxQv<+^2II^n$byokCH9 7@`u@0#I b2W7;L r;L SJB1H7J8#9*(WO9W@H!nQ#0(+QX2'V IOyWHyCPZ#WSFg(PZb 'z9VPC<xV#^-CJ+P POk?;8P2H(Lkr^eguqZohQkeVo(<VgHr}h}io8zvqrbnQbP}CF2Io* *QJ988*O@@[CJvo*Q X0qO^7kCzqxZPyuxX?Sr1qgu7LIh8aH8+JQh7J h* 8C`kI@L<$Q1C4 h9`hq 1g^*JVX$SFb#}z09Vun[`P0#Iy''HJ078# -*(`0 7<$CL(I *! #!$Q 1!770$u{vj00z0J9 '#$ 41eCh9yzaH0!?nVyKk?c,:*3=473'F; "HPK03FB3 H" '##)%O)KDn047H#-#O Z'DInPjAySag ^8*e9Z(SH*nLaXqvW+yFgiS? F@*b?(;;(B$I#a*2#11!B8; S1( rrguvo~HSrrxWjk{Sy{~# gn%0vy?=_kG8)=#k7SEfHUUiJ&g [X |w4?L^n3,kr 9@FXbf )*&=&22&,>Qo$.Q$o%Bry3KaM+W(w%f@7eW=S(zRVZ\y+A(eT Tw .6 iGRO{%I4z2 S]`6dc 7 r   z hLOq|^ VVNg  6V7]J:+YD _%^o"\[;/<_A.#B'pY$X5Wi1B  r a.lG!%zm, >; : C A O Ty  ^T ~K,cvTah@X$q({7{T7VgP=g4<x#ip=K3ZLCHb| qiJiE}mrYfq-CVkPT8URh e4  [ o v o sLD{TB} rqfi(3>BCa>~8*c\g *Klnw   G'   Yo     iA  q>;)lg[*z1Ew2 VsVIo>M{L6F=}G4N3r z> j f  ` d4K! |  j  "w &|E >JFw'i5h2'_ CIw3c]g!qS yjsTBZ  % } 7| Gc),[NW 0 A $+,F|_!}U|6-yQ3,*row`6_'uF?/Bu<%N')A$  Y  IW=ug"u0 W   d|_YSElkmN}=yi{%Pw ,F8\xj6X` j  *  qW:]Z[  A6  bg002  yv4,l/Woo9X#zA2\TF&Tzj_mh^fY00<eS/-jqr C|  z .O  $BEY Yni_Y8' Z8F2+8#TT,a+&seTMU fv;dY2@qB'{k \BR%%VAF qa {uf-i=]2|(Y2)c~C":3|Qn0EpR f`xY2- !""3+[%Uj[u 01A) ,-"4 g)^;IRKPW'3YI Jp{@+l"W _/% ^Z4/SQkY<UO/B|c2nJbsr>z 1 vv ~ ,e 5    r G o ?   ${F'ZV11c1-uxK.ha+    iv  $ +  $  N 0~  Q ? // El uVrEv2X\ q)cm&w:}  d e FhA0je\6/BR]/LpN>QgWixL}gaqbSVnQz<P<I9VV5,!8+vaVa1Px~aF4"q ^OHR?OqK, PgDu^o'DHH4&o9gkCEx'5|,`3uGK@0&(jVl0  ] ;  R 6    )  M  SvE-jVw 2y;'c]v53y@{ydqqJwEH!#z9w  R]{*1T  l   OU Y  #  jkX %h^Jye1 9Y2H9nL9bI< ,qcfY`@c}Rw{YC[U<<a\y(z<[gv- OA=B*=HLDD{1H?3\c\yHnu _Q#UCQveKQT'Fh.Ial~=siUeTTfiDTDl/l~H&XJV@]itwip'P1#fFOKq`VV2CJgS?xIy,*ur*2V R +kn ZmAsV*' U"'mp GQ%KB*63h , t  * m  y ( K= @ (! = RN   Rq]Mp1 ?zllmCr9w W*N/. 4 2   [  -  {   R x _ v L):5.=HhMm0S:] * /p E.4<z)5otDnUS=9U[^,JT3=+=I@fGlph,8bG 8<2N &B31$*5  l8!<WX H+gf)L7,f"qPY "fSn  02P ^ZSH+[oSV*O LC0B2$!Sx,uc~n~`8I{gvc*B-~Bxcu))ngx7g"F,{c 01,-4 ?Vha1WWSVA0;=f7B,I;7\a3\K f)CEC6./5 \&fM0^Yezi'\l7nWP$m$8%@k $ ] /  > hW > g? 74 v   e9 E  i]-/Q5W+[p)r=`?(lz\CV{T'9im 4LS   ;owQ|t9IczV- r"UO#o+vn-QNK?CC+zSZ~_ k[~)Xa!V[o`P81kDw)~A\M<>W)$! Mb,l3b I~~ak'x1`^D**  1 FaL#\cq~`Ovun$*9'29[a[QLk18J1x(S4L L8 2P'*7PJCOLI`bFk+O4H2X8x9L0vIJ7@hBeFyI@nXQrVCnruVL0brL2hS nA ``[fXykL(4*$!@On<yFui}ooVrzzZra-BnJuQOhZe8;*Z') ~%B?*-7~(H`U m^aFr5ae]bk >9  7  1 , oW 7 |2 >)    T #%;f W@)o3oE;a{9 b|4{}+~@V}JMp%cMr%v2\3rcs 9'  FxzZ'<;Gu -et+S(8JH*g[A'uasZ]^+"@Q,uXFH9I|RigKb#AWWOIu}$2B ^i9C#ICX<@H4$4PD fbzg>h9{G+~}~-K7UHuHg~m% Dv,^BF`fkHFO=A VDI'q7ZZ'?;Ok,`#Fu R+ 7`  "8 4-1OLf,x 1kL0*3 h)S^agk^vc{g\a~u{njI '!9S<?4g`! }o}SS!#X!${WnILaz)_g]&y+^yoS{=m_\N ;C'.SI+. v3at: g-ZEoqftB?3s?K(*QR(Vf<&q<ns # ?5 J f m R fV}s. (P|Gfqeiovq= +[k;QCio{8Mp@if<M%lMc 8T+a+QL{%t p{YU5 S4L_d0$<[s&T<gcpg4MK~bIJ wuFg8=aJeuUT*c&lNv>Q3$ b [ O[  ]  r  = L )  W,[0gPJ;U(HEuTp;^f'ulNXL B0 . R kT  m   hf ){ %x   ^O$EE4!5N=3d_Ts[-)?&z;`8GW9% ="f$Sx2 * / p , }%ehiSVf"~Yax[}Bu]4w&l9w   .  R _ ~   ? \ R }L!j(][E^>AjVL7BU1p5G  2\  y  z 7  \  &   dQx-h' |P ,w0HTFF ((Nj-G2H3&{h E \ e  A CI } x    se +w vIh* &y6J"g&'O\kY5'  U L/  & Q .: u   BRmE3xihdL!oJ22S0 .f [: cL "x x -Q   ' I ~  ZC?WM'wt+7!#UQJrO  _ ( k r w \ F  % tuJK56bdyv c o@ #7K1 4T \  v ^ ;@    t4 AA ~]EY}Qx4$k3F4qL=aWfE ] ` ]    I   jmAm :6Vd~r-Q_H  @   h p +  7  k+)_/a tG3_<-!F n6WC5 # c H 7 B C z  D p X -;4DxU_(=N%Z4KVcGc PdGI m  HC  1%    u l^8m;E4 99q5FF^-z?z^:H$%[b!S^ttP c^ N  A b  w 4@  ( ?4" r:VNG1@"rHV{kD@Ea]j4O *  P  k / CSQ Y 1u9IBy 7 D7?o.mi2e/&g   @D  BQ 2Y,, N Co$|"x mBvFmIf,{^ELH' P9 x Z&  _ @"5l(UK-V' o&g0HS<,1[ZS)c@  M ] L K 2eO66'q\DSzi~NKfY2  u h  # yasWgtl,,u%d'c|$L Xj{ J% w7 x 'RH"e/@9vAlo[T3)+VJ`xCDJ ca'&J-)7a#t\K@MkoD?9<pO_=LQC9 paj&hQ#WW~Oue-DAnUP(L}P4.Xrn6Y`uc(R]Q=MR#-q;n "O-Aw+N=6w) +jjec7 f5^Q6~J*'sf;%yBa|D{ZF4G@&= hgpw+> tE'a}5WV}a?{bxE0qV9U;Rb3O9] Hy]5nJP^b8)_b:*{[OwS e\|-<K;o.W_MUf1H( \WwL1O8RqEE?,,%pQqb9TesxCWnlAV82."hOI4bH%re \j1 ;Fs(%ZATub8}k o1w, B {"hK/6s3eFwfE9=uz; |JI b9G? T]J!>BZp >i DVh*>I{A5 nV2r.EZ{ "OwvH #(n8(%N>t9;PcFWykZ-lK ! 9XJ3/ViVJeG2E*WScPracn>:XJ&gCS1 u<T,DEI[hlbS[FWJ *WWIghOo(<ofxR8I%wBuP] Vg"xILk @+2xYO^Ah^7F53)39 lVah?vZO (JCHnSa b\LK`;^\bzoJ[M4h ?HKH4aVXh^.i0@V!##0(S@n [8PebP8Xhb+in zuuH'< (VCL<PXkZnuB_(<v<9ZJ+x8?!rQxF0~-$$[7^<JHS`I-hyH@<<-u4' #< 7# $!1?8OSSr1q'vxSb0^zSHPq9-WqF9X0#*QJXBnnX`1SLSH;9SB7@0  x^PDfY=rAHqHkq#yFVqWxrv:xu~ycfAq-a #' "P=4=DyD{H~-cH-':V\-LRO3I"0jxI-H*-4*f{BrZR~v*f''aD\?O)v{IL\o=\?ku^YyA\{)LD"PPB;,WqghnynvuHIA=-=gorgj`qyyf{nYgW~{^vx'2ggafLcPKhHPjoj{kOuYR~Kqk`j=DcVRjPk8Z8SH^xSSO-(VOVeIFXHbF9JHS@! PH94`v+@ ' L(Q?V(^zZZ o, "I7hgJu ;HbQ`z?B-Z2F$@S7F*<QH-gz.83=<@@ui<rk09L9LCH?(?!Cgk'uOQuBqu =.%X[QG{\I,<,C uP* vYV Fn -`Dv10Z+_l"%(wba2S7ucu^[ /"2+~D@J'D:Uc_"3({DK T6[|Ps KP8 gxZC<4vNN>Ub^w+9eN!SAE<1 Rzq

     O /f '| r+&'NO;="cbsS@"?{hLQ+(|d   s m   x   p%YLRtT~34b-UP BPQ=Tax{yrd@<Os5 C     4 ' t m  E3[eqPb*M2pw|Q^w5 m - HZ j   " J  Z  ''!||Ir@e+*.6tgnOZc| 9 L \ J  b$  * D | l  M  H/@[5zge,IV 7 wiP~     ]g   N " t2 0  1 F@98*`["m!Nv$ Nt JsB $ >    aQ 6  G (: r8  Q OwF?,r ~6\7Kh\Q^(Luf3P ' y  "f Y r   &  =  \ : )n3s5WZl?2ZZPolJ.q{a9Qm B  .! OH q *$   p@ i  y / F ' KRYBG [6B'96=~&+OYPu~! 2  oM n Z   E d  `> * c L u H >0a }[qs0Rj39~+  | Gw  z  X & t U A * y  Js:V6I6UltKsFUz0s   ^ @ ;3     :   5  wiROy6jSQ@j%Mvd; ,*9Ptsg ] \ z u    @B u  P  |ezpL4wAW '[IGnoI =<xaL  T o    e "e   $ $ a c GR&|m6N@#,=Lah;JSe *_    - E w 97 s HU  F W D ,y7s^d?dr FJaV &-&<((]qR~a' Q z  ,  <B  E} t  e EP ;7}KpB&&TBR&yb(_,~C EP]Go-} w   N    >    f I WgoRmuDY33 ] ? l NoPd1{o="0\R /r6!2G["u,4ou ' : H g ? (    vEV&`hqYrBZ$j! /w4d6Z)2.w(@yxY~`;g@do"U VP^c}zu 09$izp:CsW0wlVT;>,;8% ]r~q2NSJ2[!2^j$C2u.wN7x,  iR * l~   L Dy N]  @ ]28xK{(Y.r/(lL^Gu\ \|QA)N/=ZN   %  JGC]=Z]1pg[aa&ynnft{:.-qO-NyUX;p5W`("=_~gpxa" u Z Ve0H F_#wF=\pT{fAd]p\LB 7wL3rYm9lG  v 9  9 A  9nHW`xY2V89.SGU]}nL3$Lw\ Z $ZwD; e  j  J  F +    2Mj]DtG<[-.xh{x8xp h 0Hi6jHAi.) (  pc Y  < T z ; LRb)x+(ohikg p LoC2'2jn,6krK  D  3 N  Fp9hr 4/8\1ata_-#j)(0`mS*Q Q7<X%@5N 4 %K  JW3#4[]Ui*)l8N#rou M]TE=c ,G4>, k   n K[Bp9Q&a"{ B^H{KwRMa/fTk^h.9s~F38k E `)   P - r]:r/: Xn2'*NQ%N{Vxl]\ I6APhKvF\} Tqx  V Ovnm4yi(\v.bId=}F{tpXQgsYQ$Yw 20pRY8yi_o|gt =\c0!vRP]3. B;B=ht9 T2 ` = W~>AUqI+S7yJARI`07,t5 6q^S   ] Uv   Xc/hyr<a6XFk2#$7zea!M"1(1&H,x/> -  jL n | ~ R  Mh-,3R%z+;khg9uZ61X p\Nc"E3 E   g  Q  S ?]nZTSY(FX%C6_UaR3I%8   H 1 ` # u y U =< . B7yWr]z@& {J[M(=t@RLL $ k l  ~ "G  O G l @ ~ $  v GTy2uMh(PqifU-%>\#1hft d B+  J B  q /    r  M F - D B\ieV_f;vh$IgOK>rG|%3c:si;c&k`5n +E 8 Pj ,  w  u a W g d R lY0Xoe]l#[WqpPUVQ1BU!~=A    ] ; G r / F o JK pU'JO A^4oF`\hSsfTO $f1f.t\ b %    I  4 <   % 9<c#Y'RTxvHx.jnp"8%8.byL2qH_^,~]GbtfB/ U   .h w H{  N ?;US3{ hoNZBjD4'y 6-&? |r N &C  P{    O7 &X9 z&6Xtm73x.mBOz{XswMlCY/vu-\uLa ~ 7 p * S X ?l .   ZfO>Ju(90v"A Shy,[Rr5J-_ X g     .q F  ~ TD x  Z D *_v9" .[W+F?-5OxZ,D9_kJ  T u ,   R A e 6 _ 3   d HG!TL{!*?VI]HNWS )Y> O    W p L3  ! 6 . 2  Z~B5?N"%bk;Jb}6VV_dR a(DiLV" & <  W y + e u  P  wW6"1qUMK|lN&Z.|Cty_4W  eBmZ d 3 S X \ K  |   Z)1Xx=](kn>l{j' cRcziaj /eYnP*0DYE:)4 Z  L n 0)  i) w} ^6=f !bx-.VvbfxReuqiZxE7-LY H , h   ~ ( '<osVl-$.{EP}Rl6m49C Z++m[.6O;? bN / V T N X Y#9YE+C-xY\]q1+gOg6 %_ |@G/1S] a `  " P H  tE mQ $ _P c+gO61lJ KU|#1AfP i]2t / ~ b#  Q , E f < )  W 33D)Q(ak g!w*d,r{\Wek3lL7l5  Tv wF :  g   +  Q F j  L{i}`o*+ rZ| w 5 U  ~    d 1  /   M& [SkgjP9i*bq\rAA_,Z-NT\  P  9 7 A  ~ [ q 5 |    Z Y j*k@H7ux@s*TiM6T)| eq  [ ~B  Q(  V x o! _ p  fpvbLNf]Qxp |'ZSZ3  F_  { %   _a 7 Q J ,W L   ((hh%/(E7]Q~\W}_@TKRF 4_o j  y m)  @  7 t 4 r 8 xY  !p7LY/x}==U:)B]s7tU4zlxoF/; EN ,#  H    Y_ \ Q   Y |b s,jF-$6+?>Gp&5^aDM   wl  p gJ  W  $N W= J n   r[u2EFcVR?X`[ +Dcm9 hp  !-  ]   ^ S ) si e a n  jT5Ch&L]?!7 2g2b}>WlA}> '  X   u h 6  \  * F t y a Ls#^,5gp_oLv  d 6 3 - 0 #  c  N   P   'jpP&40r"S=<s}yP - /   N y % / K  D {  Z Tz+\)%mxz~13i1k\P{gL N jN AA  u ! | g g R A  o   JR 6:1`&O"1atzbW 6K z 8   6  w |    xo  $ a d $ =6G{ z-j,&VE=adE*;ai/7pJ- v   t    I   O | O  u 7 , DmB}I"(7oR9L18q=1%dTw ryE;vqq2;[_Z\m67]y$$VJbmS-w@ LOg?k]jYhTy!lCs(5WUt"tpiW!~3Ei0%(MF!!NyyGW}#(7[HX#u"Bnh{kyx~|?US78(,!D0VVYU07-CHpEj)4By7o$<J7(?}L+a\-)K)7B1PLSZx{4ja(Z'eVPh^eh8!x  181 ==93DC;JQ%M$J.%3gxy2unu^$Z07n0XBV9Sn$e@L7ZrByeQk Vg<`JvvahaHxJ-v7xXLVyHkuuVkZzIyqkyxk 32$B*$,"+D"1X <I55%5vn+40 *Pk%;"J58 cs~c{ \8$= qeh<bh}n(9Q[}}[oX[@q#aL782LFO FP*ZH;7Wx4@SPrB@y4} # k$v(\rf\`foc{gjch)3{ fx* "~8DD4{IZkgLVa0#3" *%zuXJC~6|H>z! F:%/77*3*FO71SHu{cxruDSnK;DDI4 -i,iB V0gB-"!7*^igS;{IeCQr* O#2*<'uV=KV*#,\H%*- #%080c7n^*houaR{q $y~o70JS401H+yi<+ !72P2BJ`i+98ZzSvO#@9#?P[aPFX29ZWZ(`<<W[!'-# C7$#kg1gO?= yKcugrqF\~gv{$IHI$(e`*8H4-;2+ -bgr[BZqeQ?BSbPb OBiqg^!8ryS@eO<OP}-47@ $`i(u ug#i2 y-9*@1# ?u!ZvkHqXS^eehC0Lr +WgB<P-0IPe}qyHaxazin ;ObL+}#9@hqC8CV@ x@g09qCx(akiHOLVv}Jry ^'J?LZ` XF?0VK@|uwUXjXbzBb,~)F#*4"L#IYL{W%A{HB\ogvxPqFa~oqocuVhB@;*@$#1L<X7Xha^'n^WZH`ee$yLF#k(;oP@o[-(   ! *`<(v*y<0x$k0W1(+(*IH*F2 kOZ+127<7O#O`^}xbW$gXoF<LFPBzPi-!J^B(`r yIr*JeQ7!x-J2 '0<-4#X;n [a?ikykz"3"8J%!8 xy"W" WknQhLvWoOF'1W89(BankQ 47 (-2?ay?;~!{ujgu\?P,aS#r^Zo8=cYnWyg`{;yfqg{;4?Q<*82^CH4 ! #'';(#8C2-^102LL^eo}yrXi7r+fX8' k^B,'^{VLc7:Z=7^\`Lo4^74^V;8OnX ouSaaBuH 4 (k+a g0; z0ZOC!*(+17!QVWu<02~(`u{~y^crqgIrWjhW~r~hWhSD; 0vy1-Zu)'\;SF;S 7\a:"n14~H^Du3A,Bu-#VH ,7H0W#a3);B:PBjLDVI!V0jWq FI W We*LOVq<O2buvuvkSiOIzJkJuQ`BeSySr'VW0Oq?XZ'i qL-77 ( B7J28 4$1B'# ';$SCa`SWPOxv`xenbyiJ'1F7B8(#Z S9P(<#*4[ 4 +'  X{`{,c8F{gohHn\cqj{ +<!C!goJ(I (`Q7I7# B! *yIk+o7C^4Cb1PvWXh`gbivvviivuy@+k;7W`;H!QaCQ#; 8   4(?+ 0aL(kF87W`JSBSkvzy!%C %= 91 2+.+,D *(+5$yHv?1k1# $a1$8!4B2@VQrzuq i q}OZHx.2hF+M!rxn bbHqxv2@H0J44C$O;<C9r!}^oC'u(*y$o$e?1S0V+iX@2V@Bxn^^h@QO^h+1-CP$eqh[`aQCi y*}Ok <`2XB nk4^H48- FF9Z0$j\vfjR0`\*=7u0a h \RR^ 7 % ,0 uft~jz 4 %K#'R*D?7*H"-)#8A\vkhfkg^ZSWkRj~vy -BI9 -?$^0WW1^-LQHH1k*x<^ab`zr}xqxn?hv9vz^$+@ouX@kG^Xx1x,5os[5bf~z.~Zk\unQW?@ieWeS1HH o:oa7% fwjOz+g!Hx#_!A 7!dN +N7+E0qtz8y%BjBoqvZ%*3"Z2&C0>VZdnOkN% }JKTspb~wSG.8P$ ^vnCv`|bVz }te]%8MO;1+ .S?dj Sn+&;<-Rd*?_v $)pLJ ' T7DnL4iqNi{<)C%wt l2ho<W%@^J2c7Yxz@=K|e4p FLXY+qD>\Z {dnWThOzVOr +oKJyXnuz2@I8X[IHvoyIVV\vw}MK,T.3_\[zrhoXKS=+,Ce}ZV9 njCJfM/%=;CMr-h`0_Q,*S`%"3t&{x zd8 j(c!vPgQ}9kZ/w=-r9ak[5}SX[F<+38BhBohBBCF.ISCl19J7zng7j&.tA8a} {t{eByIxE5mh+u]R.$Rf>2_0.B3)haDsl]<jRY5kK3Dc8T$X8sQh8*!~c<Sq qp ? c;>;2d3%TVXvI"{]Ce sb)7m_)G;*z[$+$Wb,$K  ("hIoI`4W,hdu8j,)^u.9z8Dr'2x}XZ0Nt{B~Hhu'VDg3rS,# LkJ${a8/Vk.0H4 $G|=xLNa#WSp4%o)Y2nUm vyf'wv| ;]fSED_vZZ=fgs^e.&"m I=l=[!r;2X00vkK !4!7_hy6R%" BI'0~~R#VKk55. 1-E1a8dry[GDk=9G:`%@<sZ~Ol ;wyU>+f!?C:+u= Xs_?h`2eP(wu+ G|n8;t-qP!c['<4>`3+"\;be1o !X"pYNUFy`@Qb EGW~gFY_GI$VXByo.~cT2$pd7ADTZg+xSlx [.CEM'iv=zlH.'xH`2&i3f9?h/:`Cv9FQJ`E-P,~ Nl9`PB8vW}V%A4a B\\MX*Z&}IYe<#@h]f|R_+ F,I`h: D.M6(rz8!KTV oTEg8'5t[D^I.]TH &Z} X'  7 8V#CkI6<E7U)u;mEbXS@ "n9h<Xa[$'89!O!LuS <[ kV$""5c1`V`+I'td{BV9!"&X9O1ALPgcDWay~guu8 !2?hS?#B%!;I 0P8# a(jnIVFC 1o\vS78D*3I *""73I K"1F,WD,771 4  D  ;")80:^~F"Y ,;oK:-LAm`q[_f__wmpp " 4L)Wh)FoBh {javr`oPqhWQ*L8HBVZXIO<84onQSIeXvkkH1#;IxnnhI7~0%7Py~ (g!IxqvJGfh~Bzk"+pZ  [n[*9?9 *171y`n?a=R#h'0+@1%i98zK>KcUUapms E:E{.Q-7uXro ns$#R$Lm|b_|]' o5cgT/t+#B'OxD\6+H+b\W!|}*d,g ro )7rF{-m [_!5*rSBLE9%gk(]2:6wr a F#Fn"%lqJ vq ukk?;1{\B{lz^foXe3p7i6m[L 1$o`h8[9iZbLw@CX' ) ' qlwv8O"w69P62J7Yq % fyY-xvv0g[#'2 vgDSISY\qAfY+|_mu@yN#"~i"Ad+zV "ni!q9XR&L6cKHg|[~z&z;Iz !h75lu5o$E0w"o9S0V`nv0;xN  Lj[c 69AF`9So |Jd>  Hb5_wMB$Z[]wm #~=r\X YG<pv7 7 Q~  z Vn  q+V[ ~(!r~0rvLsF /si v WV*d'uWEXDBt?}:w9$Hu /Eo&x9KhOn?F?zhH?[ox+oq!H_~:}P@U@K^S%ilu=|htu ;BqMhB5kb]^A-.L+jCxy2y!DGW,@nbu'vA'KrYpAB~!:^^}wch#FSnq zh j%#MfJs*/ vR(l!07Tc Y}Uh0=aYq~yhvVE?;y/o, 1_18xaBix*8&MvhA#1AD5E6\"<Y+zl>6{l=bT8Kf[1lci Wbu :pf'@K:GN}]y I 1+$V,U@yE% e7Ns3"J(UGE" S$} A"zs%oL-|X Ep+4iBS RckJ=HoJ^3@e-1(BipoGiqn@P1PT7]pnbJz#$myr"Le2P"c#l odx%%#( oB >C~JKkW3A5FEJZ:jnl=~a`p5qNtDoPEqdPte>2}CxihOF \E&@3zN/+. %IXc-fS1pg2t6vK#Ps$k]T4J"|,s;;VnqC=@BH8yi'Fj gxBut:]*k-5A#~`kBz ?p-|nM,sxoqe.4`V59i G':7VT\}KZbmfG0RT;WV=d2Ygsqn@-s,2 bx\%ztC@TDqCngs6URAmzC*syR`v}AEJ&ITQ-qnvXw]_v{m~D tq(awyb_M`$o_vwcw@qOj $uc]8wJ@A3]wU&elPe>.GAMVpQeXur$'ouc$``W0"YlQrS1,N !UdwyUD/o`OoxY:>tH-Aj{8-!x =k@{=C>"Q5452~!/ 9GN84:B5n"\7jS6B3 E?.x)\{$2XRAO?2]V~+}l_xSP#u;XkU})ubV^FP!LGM\eiO:jWD!)y$nu-S$Oe1p ]B#|TWD +H0kGu /\v4o!p*TJX @P,dL'P~#@!6l-L cC@{@valKMfHq uk4 Pq&.{z|g l m=q-.i6k0$,Ff;KN6DYGa%8f]@N+uTvP+pT3z17Vkhl}D&iJ[6@>K95- "kc !H#x`uCiFv#x0_M2; Fts#uD;K'Fq,[0*xaB$'mVtauF 6cR* 4 /xxe"~'%`JxkIf;[a ZBJp_1#rqIjE.Q#x3#O  7 N  % P   'mP]R-@vI3w,e.-?3Z?9{S;iPZRx|   b h   P% :=  +gi+fB,wuD$-yx]eIe/\{ 1*3Gz 1' l  p . JA w Y R # 3 @"ub*V*yjzXmr TSZ 2R][5o z?Sopwx ]?  DF   i nS   zi"Xai$L<[9E9m_T7(iG5Re"" yv!~>IDb<37 O N  h9 v (: ~i 9,   fvRhm=]R^>S0 Y+][i`+;wV ' B  w % ( f  4} NOP@,sS[%>)WGr0{8>5@<-  p T  x` { z j  QH+ 5&uIF> F[-z@n,#Yov0)nd &a  l !j    E { | [%]S_9b.WKSrR8(![g#\+  M  u 1 -  [ >   u #  Z pJ-]fR_5p.!+{1W:Zg ~<[ O 2   z ? .    f iTNoL*WgK{gA2>+qY$k]E^ J   -  m  $ $*H HSJ Hms6&E/Kp 4g1 Z0 / Gf  7  C ]w#e~Xk'_~cF5U*qJ\P, jZ^ah$w;}- +  @  %R k':k@L-Zpd!2Z0d.[97NDY*!k=;+ 9 C H   Oz wY 09I_I?k*X.mYd$un;VVLI5tq  ?}   6p N!YmA9#dRD fFMWyJvTvnnb[Zc-gwK'  52  T5  5PfHIB/[dMq#M"F~hx!gy*'].0vdr9+,4   V W [; I rl_<ac@7c"v6z@')[b2j-j3w\ m z  m Z<[a)=>7rBC9Dnat@r4hZ h{`)r li m! g h _, W MoB8UgzqT?=Fj YP{}Jz<H Ol =3  { }  mB\HRr j:9h=}jnj2 6.v?)?Yw_D]  { < L2rhKC%ML{ ^*FoD#Gp;p [  8 .xpr `'1cZ+'liZ%? 1ji#RJ-}F LR 2  #st;] {M\+9 RZIsE}Ph@ps%?S)uXrICZ&Z,@JhCO`*rJxXYR%!P lcmc/ v*P*'|jBV+m%pR$m]Y!2{Y(P\`%@6A1' :(l>2C*2Ck-onZ<iok6w+o.fZ}~yIQ+]nOvMPaR<&vxF>^F UCf4"KJ]KZX{o~@=<-HP2w 8e|b#K$`C+ay-Opk?HJ|o]7~-BS-~Cask#Qw*L H|H^o#H~p6%n=(W `c`*,n kScJ(#%A9H$xD*q8(`r +`~;Ot Y-^4<(JOI TT<\b2aKJIP~XAq >0^Y H<8$Gi\I88gbC*DxA ar1Rk 4 rX(9"3 ?xILW"ojORK0=;4LLv<o#v Wx [}`<4 WO nv4n~YY4`,'FfR^u1Xyo*P$'(:Yi7[%*r=jLIS@F V2'jZaVFu'[%]_u~?1YyvLW{Z;^*V0n{u{kYI0 S'\fIc^,-1#RF7BFKYP1ar `7O@FF' !uf^ZO0ALR 1 Fa79H#W8e L-@iJF24ykBVn\n<V`1v;?FFbov`g8`iVS[-1! +*^8;[ho8razoaaxhJ2^HS!P WclcoswQ1y*~H"Q//m<[<2'0bSv Q+blY:Kz>S-9 \+0{vjqj%_dR95UeCf`J>Q'E5T8vHT{MuyYm;[ x31XQ;nkN_vPZcXpx1Z 4 b h   `  6< Vg  4 .FhU6X' fn$+L{v3{Wjrxoj   5 E x 8 &V x   i   ?gZD]_E[62KOzK~ $  v Z  : E     ] w T %Xh0_R./.F es<2Cd\%]ciiZy1  { r U?  *  +S k   b ) r tT +kzSgD]w5B9p}Mm`C/S;iKQm u#  Y t  u { $R  p G \p  Y^SW3ZU b:FD?gn @ T  d} D 2p O e    { ' f  - "u=iF58fw{|&iT 75zTQf/S) #   B  r a\ +e  b 0  / e `  _B<kG&iA1LX,40f^iXOs wk f e >U G q" _ 7J    R K   5  sH_'if I_Q3AT7`>QT12u  A  0 dg&  ou i  e  @ ? i j g q|I,G2BU(cH8/_o|muFmZ    +  "  wN 9    , o A Z&_M:@Und ,[XU!a|  s ' Q + a  x . Z >S  \ d Q'$[JW]<-\n()?goC2!$q ,d   T fx< s F0  Qn ) T o @ 7 l=C*!wOx|C3Bwk" [9kV=\J hL   Q 4' TZ - *     = y  2=wC1*]N!R=V^m/'; d  :l .  V#  50  ) c T( 9Y 5 >c =^BPAJ";WIjSSd="DPF]:x2U_   {P | J  Hl C @  U  s> Q  ?  i 4}/Doe`/6j4Tw2>Ai'F#f+Z25ySk   8  idQ   pk d "  g  F [KTYepiE!M4bo<hgRl=niJk  ~ *X ~  B o P  t fx f$ :  |  ^*E>[L2c" D$J{8EE Q;Pg /Su#2$D 3   ~ ,  + ( e e   6  W r I c? 5DjkG[RhRq*zylt;B{& J   w U   \9 5 s )O s g Qs U & 4Yj_#>1#x1uC&-[ =:{1@  H Xs f J  S  | i     5  Ix& :DX5l{S*#>u ^mdg Pp s&    Xf   'c yc b |=  | }  > uGa@DzuYo YTeCF]zSVXg|)X` 2 @ f } &I g  8  o | [ { 5 ` r R pMr4_{onIi52^tWz ijbvZo<ka  m hn u o   x )    F   Y {BS/"iV,4"* ?iFK*.qagE?W4 -  c % V  2 _J  Z. z  w  7 A&  F[h,3!IjH'>3O BE6\S*J WZ U % V   ,   y  6 Z B  , q6'U}CY"du\JBEN[_v4("OthU ' O Y w Z 82 3 Y $  o"  :+  a H bhovc !]JSF\xsE0[F9VpIb{ O  PO /  cT  (  o; j H  D F Am"e!/.>SNXwb,Tb"PNp n  ] z  iKk   K & h A -   # l zSi&SntyW*p>YzK@YxV  | x8 ) bv< {  w Q U  O  q # l aa_9<r^E-;']N34lAi.fP@3B|wVK 7  P  Iw q1;So  ^ i     t mhg ! d # Y PsnEmK ]$   / -&x    B V      mm' ,0 .,^OG5  |  9|  s % U w 4G I{ U W Z 7 < [SfN7LpmMA`V37Ujk4nh&qo   [ok  y e m IF  * [ \  vcSs[zqxy^# ?7^UkgA#N  N L} _ ^i" E 6W 9    $e  d3  l H8a{!%t^Cn?^"4A6?f+y, 8'  Bi ` 3I   h  e b i  )G LW   k^2[-:yC&\y mz&.E7R(hO l ] ^x}L3#n % n  1MvH,~  n  , t916-FBYj)r>y JY=N?1gi R &oZ # $ "w Em WDa  &  !   `"3`zrNuvM' i%chi /  !   " " SKi;J* r| ZK  q}F|.?5y :S :,6Ln5S  l   -    f q h} t@!k  '   d r:DHM Z|B^vN^a_\ tEi e : r _cP  -  \ \` <j$m<o_{RpWq e(6vV;'YQHUU^vI{c r      K   e I D '%4g&\}1!~| }G.;}] )Wu(}3Fz&    u G    YJJ_~   ~ E 6 < v$#]C(1!w D{[}`kijwW"bjx$]0'     D g  c 5f b~   c {  A"G IVjlgjCJqYV7Y [ q k #   q#RaM;;E|v<   W  <ZOfZeo"t:woS(`3iLd7IG\$'W='@ S7=y'xZ 7E   C  io5*c`fq=-kzh*]W!"nPerSv3NX*j]SJfXcVzd DZv^(B>-:?  - c   N *Q  &  v dP=O)1/_g:J2CSQ'N8M#D@7J jRvDCPS[uz1Do0n;h[,g0w >rZ.b k7Z4 TM7f,\z&J+P-~V XX/v[E!^?o8.HJ68 ^F9xr^ i%_ 9BoGKEPw'2,6QC? K%L [Bx+VQrq;3EQfuV*SocF{nru~)%,;I4Z"f\ '#")HA; = x#? %V)~L{R~kY*1*`eQB` X'W%*J3-OOu4g^Sr'HKu~4Huh @4uv }J1 BX[[a 3< KJ8DD18=S8"D%aP,*}u*o{Z:"7;`n^kL=dfmnf3xY;"yI^z}niuHJ+W #$+~3-gSI1B~HI>> 2O7:NmCwHnRq G)k#B"it})Dp= f5tA?pl6gqy,hgu# ~AuXRu"=CD,SPaMVP'V;R){W)?*{vZvF`^9"14VtgHVI9X5, kBH6[io V9%h[J7*P. `H"r.6#KYvVd%y\ :"ZhnZ[ d.g+;398?8EA_'leq  KW_KhUDBQ|&u,0gbxMP(xXc kO 1 C uPrc%q~^_fVVgzk;BxL7[*ahPf)Z{7 WP H8#?@`XXf(oZXD0(I$rvSx@BIL-^ WK$2;9"WPp@S rk=XTy 2W(.\[( $%<H@IgGi'24DS5B<"aO!? ?G*IS oVK(11BCh=\9<KS!;+1[?'2!('k0*4 *22F%""  2 b<}7uXFHWQ(SFYO="u=,=; %#: )AP^r1ZOjaYS?v7O0$1(2CJno -J hqcVK\ ^a~'@b2zobhFi4H$+v4F 3i>h3PgQu[8O+{{VxWq*3@iyQ?C7ior80 $2Qx?gF#Ly81% O8e1SBbz<VW@+ -#0?4VXLzQB9-@`$bkQ2V@$iPz-;p9^=GM>Vqj].F. V|8W|XX&20g1w-cj-$/ P4~o(71,=G v_oP@Hq #UaQbL#XPt`@E.]%LRDRL5}W3KdGC;QJk+5R 761Gh$ C    V 6 M l :   ] fgI?2;^)(P5 |>8VO9aE^rXs:I|vk}Y}b<36|3S,[o& V ~    M W  {H{;Lvi)ph%S$SLbBa,u(6uZD7I%bv`xP"';w4.Sxy`XbrwY+8^m9 zp   } ?  +:LPb7Uh}2hv{S03=afh7~ "+|:m[+S+[4t{qE$ 'q:-% lo< P+(0w@M5AQmG8fvT-h\}-C +QAqgIv')\^#z~kZa%*DCr;bfs~D =vobCX98S8qq[^2kgokYrrur8CFx;(CxhyH**o~n/Z2o& y>Hu)RPj\P9 o[LZ*QZ #4jj{yh7-;-V81 I~a1_1EItvwS-I0h/O3_& :[J P8 1W\8V#-ovvf\H^Vny^vn;vvo{SH7,#)# 1_xjn#f%vgL="q:88F0"3D3,@,{HN-{3mH:CUUp"g`=E JnD/^3C&>mf0;~,jA~v`0?P8h-0^kHZ7noZg=v1k## ;yRK1O;=  " FLc\jz#Ib2  V[<vk}3.Wex?7BeLa0kK"u*c[7yK0I?-h [ix9io$_( -*"[jHH[WDrzCg`zqz@k(?8H-HFH haW\DDgv`F01J<zH^*Vrn$2Oq*X@O%3ZZq;4%,uDyO9C'$Q9*($0 gaCnZ9XPy}lC35T9=D6 GQziS D%I*JG$LS I79X^ScrXF;$L u#jnfvna"u=y *@(B9BOi}hBI }+knaZrrO<yu73"oKxhS7Q<+7I:n P#fn,*7HIW44=:1yI XW9x!Vo`SWC-8 h90#1`}okX! #1@oaHSBPSKgR?;:*!  7V)8=R %VYOh~1Av ( @ZQzkzk}@1^y}2obPio5u %z`n9.B9a @ FiHV'4F? H( WHCoxJX107 Ar)j'ka380H'Wj Ph`*C7 8 WPB1* B4 *BX ^L7f#Q1+@@0Xu2HHg^*1Iw{rQT%WGo2yXT2"DJrkG~9P('rP"I ePaMbJ" <B[ !X;8GM .n2bP. gu'=g7!Vx1kI3 j3OI~`xA^)g0f =O `Hg YL IS1  T < OCyI.7,n_r*M,F8-yV!`@#($u#L<2`puI8hKRVaI?K,,)qOa {xo7^faL^t'3)fSII ,\*q-?%W{a h4gO-n\h0,+yZf\;VW[%F#);* 4;VqF0,oP~ 4Ivg(7*1=VS#knVPI^JO~ o R(hYU \dW'-F\o-CS1-0d)D1avgI17[1H*a.2`g \i ;' a<e'VkrgyD3u \+Cf'YI1SO\F0f\K8BR^`gRfaS'3^yfj1jRcFu4 7j\ur R:u=Vw.o2+uHoO$R{ 4;R>x%f-,FoOxj&E%8nBR"z=O,~ 0OF1%0nVi&b@J2z%#WW)jHD"L%'j1B,R4J +v`7{~9rOoj0} 7b@SL`{[+ o ?g^C^9 vVV'q-^b[*BFK%q9L+#8B;k';z5_zsfxMI9X1JhB!s{+qr^g! n*%J q7!kG ! CCJHe7JnXI29!^(g{o{ooc' ;IPgO; ?;v}Cb989vG$G %";lW<<_hHZJ<r<@ BWc~B^vH{QL'R`$OuK l <(73y$y ;;GQyaWXo9!f!hZ?`^?V 'gHJc=^@`o:#Z\Y-yB)*fLvyYkh 4YIdovx `H0Z g fW;xLP Zg9 e#P83Pb; :'~VF'?4chY)u 8b~3Y!Wn--2hen_#0LS|tPZ0O3(?%kby I<;kLh@z< FzIBq{!=('+4$nqv Ca,,8~lyeh^Xf7)vn/X~iB?'~zz'qqq;\+{IvQ'q%P!0hW- oHc4t&(<7 B%@K;BO?0,JR %(cn'8i@r"Wg3qH @VD1;,P4WB*[V$e[*q5 pT3[R0OjX1HyISE%Xa!;<"+ oKJ%PK D\@[KXk)q `P#M8X6BQA~ j}!k5"U!:^(L\ u29IO'0';0z/IA7#7Q^k?-X*?b4}DKgzq;4O 7@,kb;31[xuBk^FOr':kL!Ihao?Bu ~Kqiir;Z$VP1XhZW~enk~2@#ZHn%vHav^Pi7qZ`rfn[RqZQ oP7g8f5+bhrID!Vk0[! MX#9v y18gk}g(J <12GXP;I(JOO-zrwf_KW)~q\ P {GTO9clQC,"v8g=v+ioy9P?{g~ {vk~ix@+; G8w(GI281I%,<XnJ^hfW5aBF8}a4 1hkFO}PzH`@'$07H0FZ C2 F?Zf0'~LVha4KxA)1#j*]0JUE8\j~ ;Qv*J^9C***:($JqgL4 nud-VK-O:77GHi=LUG6nzP>V?J4=i_5@)^)]C[>/S&Z+#Eq|gg]g?Ffs?X=9bg~e "@39z>jqG7i<2a]0uI~27!2?Mr=Rne-;3?ZN9u K&q ` d#n;U(NALVX[!FOh-4X8J 0"eAr*{{. K+  K_8KDDB\1J-r4kC?kTak?+O(qXiI8B, C?eQ9 LZ0Q[CXL4nx^W#k+u2JVW2}?!711kVk Z;\[B,{ D8$;JGPBq"Q %w li-$B zM}ps\{io,rBelWzZpSZq ,+<w2[/aha$f11Q[c%`ZZnWrvz_rf9;,afh^"c\av'qfH7fg;B aA=qX{B@Qy chjS2AJqw <r!H38[v8? kZfQ\{-ZG@%I\,q#(,xfW_*{,DG 7oq`)i)iWgX["'?nb8cW? (` a:1XjSR{{vQ:,c^gu'$roq~@` FO8P`k*=3OIvuLfvY1hc-~R3- Pr"a4B)`?xgfB4h0 'mx~,c"PLno'yD   \-`Y4\SH K oxW,4; {-W#OO1^O hy,`L^9HLY(OfXE0g2JUp"3 HH1DR73P0RR)-;:`q{\oa{4`a;u;c[Hc*vDY-X~rghL~ucrgjIW~c 4(`kIRDRncO4\B4BK7)Lc3B~ :8WDy=1Fv{Xg2iievvqe*'ZF4+r*9\FO"^kc0gL#a`v:~4x`v{ku,Hb70(A+9z;xz(=y%~eM(< aDrh w: "$ %Tyyo9 5_D<%Q * <vg7;<# g1:-ork BDIZ=H#07V>;`fV!7dBXC)CHm!_~H=93 )ij K,x-1 k-~)B+yQ?kK^;H 7 ?H10A!$q rO^kHLD\PrF{IW!qSv !#PVXn0oPC P(8[Lik1^C}8p u333lc rkvzq!<xyq`k[C2@;0@#- 1{ ?#  #@uSO%YY g:L1~a{*?V,{ g7"S3-BFAcu:^kAI"KoA*'**,SK^;:PFk?xg=) 7%,K KZ444,VkW1%"F1'S7%-3^FSo*A1A3a"14aW F{nSLk qua?W01L4H$~(Jr9rcFFz*\^BQ?ok4 'ir8CJ9PJei`?e7Lx*a[;+K$[_+;ceUm{,)UNw]De5lt52l)\z%-DwUK23s93"D 3!GB; i[J~yQ:frI4qX3m&9Kd0)v,4M[MDc"{\+E fj9ak#1,9bb&>Tx#UG'&l0@i:Tg9jww,Q28y=9X ;"k( (@#!A;*A*OP;g#pVz0/I\Nv(!_{zix+a l*S #O,\T8u)\ < QQsvmehfmAE8TOJ0mtE;U]4n/L4V4V-u=D*]@V^te--VMx2w ["s$JphKXoRF`BO7/u*t}(U(wK"Zt&mn&V:){!I8P8 Q#Ih- ^k^)Y;l~;ZM %kl xkXaI@ 02489'Ckpkur\bc X\zI3w5CIK =ZCo?y<R=~3`k[ER23A"E/@C&/ePc X?"P-8o?IlT{i_etA&uR\ wfg +9cm;2.  PYk3Vf5*' &wzZbH";K8Bi0z%_"/FV=yxZ<rQ 4-IR0:~H3'x,;7O7)`Ha1o0x;a"Wo2A$QJFIu%  77S fxWAW ! F`kqZ^rCVWLP@`q xW^nLJh^'ernB`L v?^^BhWzn^ySJ[?r!BQLqqxg^hFk#Hb20+'k S2r[;xH;J#nQ$eaqOree7V ==K`!WOq-2 "9y"i~t[-@ =T)]V A 7qkK by:p-EMkSMaTm&\IONpoa( $n'0! "LD5\( cO_@ vqjrRHg(gWC=dW/wRD3*y9y 1y8bY0%..M xc8 ;K 1"]%9*=@KJ6~5V!tZI %e4FJ ]a\'Yv23C7ng"V!1Z"d>}~} Y:jd[fr-5y,3#8o7lL`#`v G]iyx/\z)@Q!Mf{X+ w_CHn"P^CF1 N'Nu&y<ay[PSke .5[o6wEtr=[ax`}$h ^+Oq n2u>nIqj F) 1?W`70QxhebJr*1wcfB"K4g7K+89 [ R->~ bqmx34OF ))DS?a$XB*%1z}!UD/&vb;['<`9v O]0 Tsd'?qZ i-cD$3K%9T/^0-nSI(gc?,Qf!JF#|6 ,,tw&?i,xm q_. Xf3 mZCj2>XvB&]DT|`${ XIay )5i%I!~yB4Rfx)R?yQ ;bKD;J$,')Umkw 27iHfH-DAtpMQb m1C :ZWa\Ni8GJ+H!,E w(-Df86xFS-YR)v 7WcCI|uN[Ryn@+z'_QM ]sK` c2sbJ9<r_} F~ CsU -gn;\oxE)"!;} oq3"=Y3/(Pzvj3ZH/ (D+]*r!A] u [hE%~73Ev 2 b 7 ? L8Sn4MQ<94OfIWHTT9W_j6%r=ZUta+;op!lC -VS"X/a?NG(6xl-m>$@I.%$`F0d"P| .(zLiTs][~n7g ;LiC]SS,ep [y LnAY'-/iRuzAUPL^=[Fic o NII7A8~jWpD5x:aS+BP^:fQ'RZ{K?Ac}<\pEVMiqL8 =z. O0F|Xa dkQ=[*y-?VTILjO VXZHI4.8[KXuw=$:,;#H#K}OB (G\X;M} EYgDnk>D3MJ9MSR"oj; & R4ZUM CFjKK`&P,waxlz[I>>"'3-< 40[cCATt@,Tt[B;Sb!Txz\Owu.XhDS53FO-hL=2U6j 2&{=^L2=`FEN" z* Ddb{ CM`G_F\c88eT '+_@*NdpR|7>%+s^<wCuN>):Bq'%8u;E9qwTLN XmQ52A>Ur  1_ax&&dbF1wR?+cszDe:fX<J*EU{@-~ 9 B'#W{Wr\hO^~4j, ={C$I-=cb?rg>Z@c@}!7Gv ],1TE dq p"$B7&oX%%{cpA^1Xav=Z`~1/XSfc)'GX4GI0 . Wpxu.Y1\q $ XpIw1 ~Dbn>R<$#1gz? ;l-B ud5xnlSIH$,G"X0B:[J#ngaaYP>TZhLI]YSKg ' i 91*{:LV*M. o  p99&(y6;}."_%SS  y ;25)Etb~[Y:8H[HG.f/XW 'ozB1 F 7@k . , 1 9 ~u M 9=NAA165{[SF\1I=)7)5NK"GQg$w;  W  i    % 3`-[#X k[Wdu Nu F[aH:${rB<j'  /    z  Q8Ofj%.h_Na4 F6&@D`~{K s 3   2 C9 (mw-h,F_Q6 py1K FN{FJ:1C3S  |~ m O  8  s,d<z_K^^ty^y&$w)) fYKbi=i&]   > X`&k,"K> t*y\O|&cK^ J3c#f   }   !U J{L 97oR+J3 GcS6N U?0L;h g~O # J   NF X BoJK MeTp'9Nr ~.P{?MS?HK`:+   | o ] |8/T6lrw.^uY1/s 4tOr,vWm~x+5Q#m| z ) h aSq/J?8#w[xB\>R)]Y W<;4\  w   [v 'h  D=B+h^UBr#$R=St1-*V:jP X`'   F i J ]X _B W`31Ad|y)=ETy KJja;UPMzKd 2c  = ?W  d/&`to~`  |"e7S_53KeMU;A0|vI# 8  ] ] >   ?n,~Rp1 G(wFxfcQJK%-I L   G   N  gU'Iue7tMgpj; pB>=Q#Om tk  [ ?  ~0 v ~z  % dN<xTWU85%:@{  ]-{f-YB   g@  W  1  ! D2Ppz1~?FS g)QY9S/ R{r)5@ O;   p , | .  q @2Wu*o>wy=c-{iT, Wh+jv1'HqjBmjz6S  0  d G ; ;   1 Fjw{Rh6K $kiRAM -tlLS^1r)IK u R<   P:  * ; # > ,  UVff_\?=O 8(-wa z5q.a   ?    '! i" ;sYsP]FuEu# NfLgDAIm C cO+#mr$  /l  G Y 16 7T6w=Xm EM7CICI.`-#~C ;w jWXt;/ 7 P W   6 o @?K rw>5xGEU!LZGN,^|Xb 3t  : ' \ : 0 d  B4{"&Y"F,!@[P*"Gb/"9J3%Xss3z-${lz;khsw~bS*!v Z`~AX1a'DI$3 T'?iOGU_j0Onr (gGa\zpJ8+-#J-7 *@Whe(k@`Sn$! ,K=dRH Kw|U?d-T^z}>a-i)Eb*aJ;o9bz A&Niw[T8c pKPI($hD\;K8f,{C.2$eZzC^v`g 7oH#:XCkPo?f2[b#H*8-<Ib"]z*L  ",k+\]fEyX5zZ" OSVguW$O@' xFujpP i->7N[[Mw "%jvI +v1D;\ c A)07 jt->QQZCZ<@%<"`h?OyJ$BP'L?KR0A#/I Qnxlgy 9`J'7K1{:3kzz iwozrZWK^Z9H#x~K*2:Nx27!@.! DZ.S[<&i!FY@<]QGDJFbPm-RiDW =@ry89q0@[y _MNE/g4To1`j,`-8{rc+Qa4Q{<d )E{MJ1uxX^0K0 f(Q-lpv\D4va$wh-$x#55<5c8NI71%;c}tDF E1?^^eVY%[ _DxnrX BA-]cqE|-l(CMZ[.-Qc##u8-{GuCEKe8vF =#P}Mq$;Gi8o1n*Gei!zy RoXu45""tyee7!^o`j%Wz`xm '\9{_$h@u(B\xWK^_GeD@~oQC\@6M?wPM-9:,#$C4/:z[W}(k(7* NQ5}[A.6x  1!"GVM.`:Ir}wa>qo?\-0Q@B^'Ec[$h2z j^0R?X;U( '@U(/zqqR(bQ .NC\9om"`[zU&`#\KhgeUD+h=OZ:Y2i R\~)ND 4zQ*sW;@D%yhw7 E?l/sOQ  13}2Z-?gyAjx|oTuy7s6[ykcHWH}f{Czs`b[!k;i!;f"%V:Q 1L-?J[ ]Fc&Y/ QdX?:Jo2W5[ ]QMAclpA a@gCTv1~7-mynE,E+B.Se)kqzWi"[a} 4!JRp!/UUh~l|'= 0l_<%x2l @1P`g4._-avJ9Yo8F-wyJU-)I@1:!h\Q.-/{6K oeV4qB`ZO)Npz.l1i4#:n/=l%F*I4T=h\OhQY5l.2_k"@ s!}hHyvW )U uA}@*R+mh/NowN3XpIY7$(c"iV{ Kn%C:WHi_R.]r#BGvqRF Vc tY"]<[kPD'@JSlS4Zbn}+t0+<?gNWY|f Uw!A|i"jKUxMtQ- crC h5Hwt1Pk.G;w|[-.A=zv%,Z>ON~lw}v~dm%= H-M_$X^ vfDY2`#kD:J2hhF lMyOV9m''+,iU1mNaQF,mkCo%Jah yP*g_t9F.&dWt EL3lW*{uV*a\1h $:o04]1g3Bay #a#h7d#Jmi<_)*&{:/ [z9KY 0WrcSg{!K6d]cSlkJM\v\ W9<13 {aE8Q%q&v% bRCF_C^6O0kp _8s6,Ce$`]{R,eN@[ LaPu_7dp"O& oE@W["F35}dYk!\*:H.1'~ o_L1]I N3J++H= ?uQ-oAO//|/DZ!Ze i$ex.?T}]Gw=q[$DLAZhe-Cj>~#p6QJ%y0K7y+^,?!'W13Jx}i^6KIy=C}+V 8XW ],`WP6"c>:&2koZV-W?\E$}q|b/{q qU|Z^'yh>= #,,Z@5{Kkb=:$[MZp3,+- ; 7,LoZ(M7] \v#6X`#Gq@YUu@?>A $SaygCnu,/Yv{dbK_:8Ff5vSV.#=yf<rjaJ\yK:*v.'Cr&,8}^YP!%E}mO :Y<$?h6G+ ,(`Q^/I+$9~wU1RE"-wQXk<rrmK}o@lp;kYbLy5)v91vZ%|A pcEPdJH[+ui drHiSS{aPcz$ VfB =rK\]ZdCd-`wQ9f*Q_G)(ZTcFM\$S][[Pc0cv hhX $!=/Ssu U h-)vFi+fVNpAhqRhBuu(c[GvOHH 27MM}a,wBD x;UfG#S[9n!lN?Rd.\]a]FaZ=@gAJ_8[z-c'\Im${_G#c?&:J2^63@MN:(vT9kJTY2[Fs4wSw]yBvZ]_ V7)X4X^hudpc5EP2|)K P<M 5EQ'/t RC5y((oW |:U~>9y`4LT97z`0xu Si6@->72;25Q> 5l'6VayYQDwcZr Q@vZL `%QsdQ2v&0i F>AG%,K"u j$5dvsySW$f$/.+"G')%;:'{ORR|fO^]m1;~[2<y G =r d*=~Im)Ns2"21I6"kkL< ^sys!P" r]<:bK[Kpf@QSpw#w%M4?^< {Deifh.!D0cRQJ1q H| K KwLF=Y2o%1-S?E.!:HeQuc-L.k;&~j@/ciO/3$0shUOWe'71<`4 "v!=y{66JaYe,q1\ 6khf%n]:X|K eR| g#s_}6X%ayfc0Q-c!yV-)zfEcU!)R9e.KojLx0J$_.VY */9>fhOmS E'T 4X >TPOv900dp_H d, [[x-LZ+T=-Yoe =}Y,.v46Zy*$/E{MvVE>GDVK) _FIp0<6`bxScjEnEhJ(ePhcfd%$ PTdSI+g<SN $$XPq1{ qXQB3myrSVJ+^8CsI XyV*uh<~q(~!E2E$tX-fBxWAVi|J`&KpQ@q9U._ln6Hj#W@Zbc5zN]QlH`mh%E/ bZl SS j=o 8U/V); &ii!AnV[L%ZD/_O%N9a  zHzwVBW=hp |Yh/^+"@xvD;oT;1]7(Bowr|Oss}<<LPg vQMn_CG`o>VQuv(Ryf,v#M}Y8rk_l[\U\+siG~, 0 J(H9FWsf2Fc H ;~KrbQ[;ve\tXkSwwTM\  } ZQ+?nYGZ0Y f3up?73vh4 k+S5oMg_blMJ+!u x4[I20Pgot-R p* #YPW?kHO!I}2Py. ww%``Ck;-W-84g"C #:, ,yrS{ 4-H'uLB1bQl_=J[vqhPI+4' g"*uhrj^7;)k?0HL^O{~xr?JI {uu00nLkyxK1?;A%o=0j%K;I?^4oyry\I)1^PSk27WPLxaLZZvk^O'\ SVvovvq^vh~Y^\\~{jW\fFu:f4,kvZ~-* FoBWvQQBv8 +hC  497VPJS[[hviuh B$y$@!Ck(iF}`vvgznqx $1$"=8DbqGpiMMXyk <I  \S %!i^r04e9 P0k*PPya82*  0  y{cu +00?+#?P?1PO?C#B;C(q$'*B22HH<1*^xou(XL;H - QOC8BWV<W#! -v*oq4RSa`jux~n ^F47),A3W8Z?IfoRfLKqgv^gLOkZ1~IZ`fV7IR:`RgVkHWkj)7=)cIaRkYO{\BPuj 3r*c ZRaa?SOy~u{q^oOVgoxFk`v7\rfI\^DI1xOfW7\ K ^1W1f\Paj{aaoaqn?LWcqWHnx~uxyYIVnkvnY{~# 8;JB!<9VFh4<!q $W'a9@9; !Q7-!S;;-X`#[8!'C<#LS*4J4y@kWB@807!8* +@0C4^! ';@a(0<(4;8;? oB78P1ZCHbOOWiPqxkeiXrrq}vSxraxzgxo+.< 1 ;_TZ.@5=,5..`5+}   gXgqqQy}nqivqzkyx`qn}`y984OOQ;8<1?##7;X*;L1bLP8[?[*zHB#J+HV Qur?`192kh(C'(28@9 kj{VFR4*3-IZD"8 Pa,  %8-1#*%;Wo R W\a; KB ggL 0L7808w=`=1]z"7' ;#bjB1=nf{OhqPZvk;yr\qnj~rfKn^rLao1q~Vc~?krvVv=vW~{cLk`kqPxr;`FIHS?0F?:`- q1R7HuHg0Ogjf;??[2$71?$SL;F - ~xy?yyIWoZPy^\^-%=Vk;WH??Wf#17; ; 8':' 87~uaFPcqRu^qjc k' 19W2([-<k( yZQ!?@41@Z*??@;nPy@q7oe@rh`g9HO*7+;qOa?QI JL<PL7Z2Z4P-#181 Q22a -9 CV^2hvZXWHhoxvvo*  (! qzgxei@gWX7z4}yokx+}};uQ8iO#9 qg))7ah (-#<LXJqy(*+_.ahvCbTMbY,KrMW33ygh77_P ZNwNiyF;['-t%i52WH-??31f&Q& {d#P@5L[Yk' |,_2*,FM/6U Ms oAfBj-zCs$rIJ99L;c*NlD0kxcpuf :O% MG7ac\1Y]]|Vq?a{igAh(Pq=@zJW$Wk 0 iu KE "mcZo$p#$>5~qvEuN o0t)A>v7oB$i'pGbWxvI#qv`=RFvIz4pA> DgSL'k@l#G0D![r=4^H ,~fhGtV9w+=P 97r!-#^Bk1gzv Zkn=Syr:9Kq+'/fq[JJinO Xd/O!wUP>`zvun#@y": UNP/J}.k5B ]Kt :ZmJ{Rfq}}iLJg- wTbIrF!o@;F)=n]ka{| (y*d0%| .zK [q&YV<cXr_+s?PjV}U:Q1GZ%y (%o]o]JsY'!qf:j "acMbd?6]7(!eVrOfPSx&%vvZW^$` |S"E>s[ I*zi]* lNyTXD64e)Lr7}stC~i[ G W!1h:uW<@.xtgl.Uh!u$ r]7s_i`YJ@LZ</G'$G HR`|q(^`0a'y=/\*2rSty\0[}{} Ah.D8a08 (BB7 -2 \^/^Kb@W hh-("|7!KnS<|4 u) Ip5o(q#7 ,nwu Z 6,OW`+tf] kMS0yOjjH2/~!>I8R9,tf3L`'MSsoU~Y:? T %WPU8>ho{voG~hB.Uk+Sx;O8`x#Gt{9cu$!I)*Xuq OR@c{qHi=8X6a(L>YvVbH4 dY:wq{sJJx?`Lx[ nWc Iq$qOBt .zl",lshRFghjn s0 (@" @p *x0yqj.Uzf+\@eLnd7g]_Ej c-EhQ$k jOJ#t>y$rZB'+s% *kW3!m>!}#zC"\.LQj_?} U67;Q|>&}9cc5S^Df-3'"#K^*T@3E! LA:FR'ad0N`xfQTKOKL y#i/kC!x^>`r{F3FE]81/~jXB#1~L`{(#YOb92RLV@Rl99I\*S(J\7qx;c'K@4rRXNp;6'8YiP@%kN zu\$)C 9|rf{6UN`=y$nK'$Rgd7 S:$^v zC?Ix1KibXMwryK9_i"$;[q8;v@H#u:~W` 2nH7u * 1(4C^Zvi9gQW4z `F$InC188;'Lvoj= "a~=P-?=W4,4IIWc3~#,a4H =Ryu?eo[~PiVgx( #2H'ZVZBQvPeanq}a[zzaS9S}FeHbxhOe^O^eJ`qCqQ#Qb[WiZyCB1#8X9BS!I(@F@ 04  -?# B1OHJoIaC-^8kHJh v*Q !z aI!`(@ 0HVL;?*u$o*9` Zx7@?P8-9? +F# 7# ~!~xWjy~ u 80* 'F 4BaF A~qWSSWPYfkL1D80?4"=*: '  3H "O)*'"L1IxuDr-A-%L'Zh`u jI-b`'Z@LOZfBLB7cn#!S(?OZ27+Q9 '*-4-;C`4g<LSSrXha^VZ`PrFV}Jkykzivn}BQB0@?X}P*C[*!k;BFQ?80X(*LP@8 '@$ -SZke77o1xCo4BSbx<I@L}C#PJOgx1n4Vox}SLVZZBXg[PZQ;rW2@-'#8S7e ;9b*1 F$X?WO**'+((oCZ878P+PeF$`0`ZVIr@o^SFi?gSL[^Iio[iyaeIooqWvxkrFvaeq}oo`[q^zivubWZ@;!o@8e'I;*1JL;L9 HI9g7[xnh@aP}xBBohH'-gO(HxFqL#O )'4 1"!B $B#0FH`E! L 4w+zbxyr~jfHr0Y ";"%;Bo0  =HA8Fn*1)(ZH7|t~jqWkqYwSVQ:7)!AA#{iHAbfC[E,:BV3g-O/=7%` A*XW Z^WH0O33W?P*"o'Aa`7) 1KPPA'-;'R=%r0-=,74 8\10KH*f7V#KRS)R%F0;~:cK 3-fyYKF?FI^n\7o \gS`q*0}#kk@(v9?#;7g[B@@@JBF}r$DhraF-`nQu[(S2e*h[^$y7Pa471$yrn`# h(hJ<-!P??#@'! S4 !-Vgunk(hL0Y cf+ g@FK$u<8vD[c//]s_!6E=x)t3IqI7@XSvzG\DB W..!S%=z3QZ~SZp~ pv\y~czB1GJ%%(@%B@9nkWSqo F;g!*b):WlNX.fQ ,xc~!*2ZW\= 1Hn[kv"h@v%35Z"/H=rY:je >5/,"+  -bRr3X=.Q%Ggho[ZBLFR)I) j+=K=/fQ-#?nS <8xb2^XC{+(NpsTTNi[ht]W3G6W$6r,-rW$o%J2hc;3 Jh,^o,L 0(k7` u3j_A9'ymQ<_N).VF8aafQ^/0a!bDq@fWaq<\8JK=/wW49@5HJ$v $gHqjjoh)-")89  }{ l"T6!}"==88ecz2WW*{-b;rWIqG=qU3pj^^eCM * uuvRPt_#^(.dGdAt\GM?ot~3WD+ x\b83xz5)ygoz2O$BF3V~^v1nq/c5Ni)y!xMVZI{P|FpPL f< 1\C~$)Mz`<\:Ow,3\AKh3*(yIQ4f0V]_i/)!4][B79.)^yEYH %P0@P'+RYc[,Qh(]L6t :64K$pw `2'uCGh~n.%zP'FQIy136<<<F'.;o.S$r'#N qgu(Iqnb(oc-r"<dg~.hFJ l &Z"Lv)c,u_G*(GxEN I*l|+"<R*/"Sj2ZFBj!'Z)zUAQ3I Z"txt(Q?@jXx; fWj{9 R6@W'8 'tJj(z,L941A0Fv vX2 Bwi.`^F[F- .'f[R2z"Cp\C9lyeOK6zWzpPyCl4[oWgJ7 yNz&RTN`oD66Ku;0K~H%WK.8S\S{'[le fws<KbFb$@q_ 3ziKIGiQ!'W#;^51|84K`Y OQszdzo'HD<hW]P^ufE@l5xdtq. C3*6`hE:ropBU|3{]^l<9kMac.o(4-xjVP3(&x<-|J(AG0RGotVj!S* K~v$ Y5eW^l5M t8"hV}FYm[i].c<j=M=[|o?gyCS SR+CpNe#u{o &'{/c`< B=W)neQ5NO,},Z(Wq^xJjNr dPx$sT?Tf$J?hL4{zYbi<1vWh%QK8$P;=_W"j&NmZ somc{=|v'~6iYboAR~cT/ {bw ?^ATt.|L-?q e_ 3~$XX3b]#ly]2%;Kc$a5!!qP}o8)o e) 5aQCJ4QIFdf`D1#b :0c?.n/i.Zz.JTT3FQ_:;<COBOI:KCM\ qv-xVAnv^2DL,w1i rrg Wuc}i66wmO;[sa1Wug-fY'hgggCG4;<51 BL^IJCM:w l;BLiStPDGi//m6 |fShm|qP`Cv[W   Sg2L}@~Tjp>8* >{sFY1$=%TQl242alq+;YVqSeinN V') ByZ+Ba`@S)EY1`;K|k(ZQNuVp'*rh po37[y/{-MQA'[W<C*v*,(w~['yRyy?v{MtcU;:H9`gya`{;6'=@'e0Ail(vgOOVP"~?PS-@41 Eh{] KBT%iT<bFj_"3l"Sq#8c8e7EKE|SfqRnBl<4#+L 81wR1Y   %kLxGGK(`9r;R%bcM~Z@"t[9{aU8vG9o0$r]c Z,whiHGO!yJNk u08fRP7gb]wO9N] +reD#gM:!DHk \<\6EtmA#P{WAUTQer'Z(bN eX#Wk6U_*k %u%M,-x4_6uK9gbp bu,"+/\?==1r-Q]Q$6Egg;\ qR+?yr>n`I%1*8?g8Q_!,G VpZkt 'B!dI Dfk 3pwHRW&6I2j7U wr,v'{If6v9cV<ZZWL5FMGO?r0Jg5eJh6zY^)K7mg<x`xfMWP{`.$F5\k&]rHO^&zxA[x"pNm{ Y\fyu_ /b,h23Q Yr_HVskGUjwg4aG TZuC!sXRAWw^+W7;Ehh<8CJ!v@ (0c c/U^ iz)WG!9{a{-[}d0 QOF!G;=t5^y5H]!UT%*3ZU&3la&b-kN0$ %]r!"=>Hb-?kBtM/y*oug#.-W0\ee|U9  `ljeEa/Yw?uREAiyL1%?}@xK&[=qn3yhISJ<YH +@miQNL>])Xci+#Jd?Tb'8 ]SLw(;'Vv~+#4ek"R[n<9A $4HTrZ-A5uF#? b)&4o7oJ|a{ymSlt/twT[u# \,;Q}$2ogn>'WtLK Si_9J}K f0OW.M^" C||(Dv)m``X3`B+ne=w.?y$N_)z36=ig+2>O}-Bo?dY;]0i `8vL':u8Td%^`wxO;Ao@{RaP DV5w   / U 5  rKi<*8/ZZ]##1T9"K>ec0nz\B5h2KQw3^O .n ^cuB!!0X]vScq(s1W|d6"zkYqC;M9[/tZPupEY20KtlCvWW"LrX=C~*od zmB|Pd{%1AUS|j5Tj@@jNrS[aUR5m' VJ T 7 #R97h4!@}`O7[ [!Sim9VPY ,M=B"p!fd u   ^ ${gKxd UJan)e7KHUH k;&ASJsP,<3M= ]}   -|ZIuKWI? )0 bex2}5'YbINTZ}w!{2m C   A V' ZuV)'9vXRg5*(a7&u%B{RSgi  r 9wH2ufMQTw9fC[s D:y2t0SPr B/Yrvv > @ h= =5c@+w3};@ -<TWFc hIN i[3Dcs"` J  . N E F} ~<Eh&ZHJP[|I\4ug_3@xzo_UUZm: ee  k } W+SG]}_dgG8Tz1 sFjr08JH>~hk~{ n0]xI. t.1^}9,4Arsv>#Rz`p<2z-EY  / su9mo5f]qB;  :b-uJ._2kc#.=#,=:'f[oj"-)`LI&l4(3)dGOj38|{k_<xSAwkM--;~#1j{yBE~ZPl 0Wcvg[l$24VZ^[:`,*tMr  e$ E 5 7> p14l:j+l=5F` "i{VV/Y\1T E e SO,!9c)h$m FzH*Q S,Be ZV=oIm##0$B9$uqE {YyN"Z#|-3&9Zn>5 s6Wmo%H2B  eM  ! E 1 I.:<fvoLe6`lR <S w |  I   .'I'h` mt->] T8kQ`#y  5p+ &) Cs S M b 9:zsfyLj<s?:_F`/3aRDs/M^N;SX!hJb,cwkWzG-Xv3(LjK,2s7F55O *,f^4j ; &h So~O,aK#/Mz>8o|24RLF_6vFpcq0V1T#gn. ig&2Lo1` ZQ! BZ3#=%DSibVpwP^K\.\Z  JS  S pc)?Z ZjLb)XQ`7g{( h*KE-v?ab8EvfWdWs}@"/2 ?NG&k0CQhV#z1r_OP,'Sf d=Mp L?  p b@N~]:P^v^jcxmZ3;qg5TLrEn 5^ Xp   .  F , ;H$s1F>P UVJF&&?Z ( tW"%   Vc _f$e e > C,o#8>`x& -#H/G~c4>N x@Adj*/;[\dRA=@)&W :u4&} [+8Z[g& _+=9st>y@Ap vF"7-%S3> ;0BEFQR=%GC-;k ige0o IIPi-@'Fk q-Jz'Af'BRNWd)s>20o W5p>|7,uf '.^\_{x&*f$r.S]?JkCwy Q: L]3=u ngQ\<3z6<|R7n5I$Y(j__O <^ [ Qwi(EVQJ'y|)'LwKE\V" ?0 db&"xZ]  5 d< U  w [RCK)FJ&tpD0yId7s9j&.WVp.EX\b9Q2Z-} ;| wmdZP#[Svq"jil}wmGlqT}X8 }`?z1 '  -R^-<IzO)Zgni%-;W wI[b;1xecb*:dGJX%m4PYyCFx^0i ]>(2h'ne$ +@UFw, q>`u3j)u>S:0m^0$]*^#WJL$6 N\T7i0 }UM`eaS5CK-s} oq(KyLI8zc %m]Rmi? S~4+2 )5`HJ;KoAX~CIW;Ma""~93&;> ;{ Im$jYx*BOKI)@w { B:uvk. PpOAyQpx7 v  b (  l { %d p xdn<JA55],GKUHS&PVn[ae+{Dc&  - f ) 2 J = L O 4  E/]=;Vl^7Ghl>Q~ (JX$&8l;~iS \3fIv < B  e    c A -\*z#'3=G{,EfGArw6~r~=F-9/z7i- b  D  _ ` X0   ';Ph "p^$$v4 c=~X2.h k@LvM*Mp Um(|  N }  j     ~  $8s7}St;J\lH}b{$A~#vGo-fE ftp0Tk y 'U   EG u 0  AK  NJdRUw a{ (? !W`ZX1pu^^>|fY@I_{@_ 3?*1[0bPV 7]   J<  u  b  'Z/U8HCZ7~aBoZK 6-Y H(_i= r8 r ; {    m . yUQc!c-rI0maCZc!z3 DIh%P$.(cc/K &   | V   \  b + &fw<c7S8o;g$)I N))7q M"5,L& + G }" 7 G Zx   j  x2 ZzIlo&'6u95*-Id<~"\'b53 '  2 e2 m# U     3="s,I9YwRlG7)-:v@:k8w v I    ` ` =    M 7<|T7 p%D?$KRPx_{'Y#GE3wF v-i$pr6 Q > } Nw  q k ox 9 j    E!tAu+KE7k <QW,dv>W;fbI ] ?  l N      B   oE(tZf7'_7s:77# Yw/kY H 3 0 3  XK   `i ` `L*;*A)1j6]l7rVL: ?Kg~jBIu . R l _  )  $  NG we/YY2V=Gbz~( xR;!nZ_5*iVu]<[   O OWJsw|Z 9  @] ;tcMXyJ|cu.W@GUxP52X !  G  Y3    ];cL i){ 2lmr 6>'1H=*~cJ%q  2 .Z  Q a     l|ZM QBYN|;ub5c!p|w  u '    ^ QCDhJ8il)}kJqAy?S:$ m0 RE /     u # rYzEg_dFR~lbUmtf|hB,lJ=7(t~p  %R    X kO%9R.A(&h( ANQ4N]W 2 0 g  x^ B d T. BE#(<(wxxxIk UcIik6ZPh Au:|       8WZ!S^jGuN>{jy]GHM'   t  ? #wOahG0_O!A/y(0O8 s  x  o 6 NM \m5XOB' O+oh>W[]F$( X]c- z O <    fv #>}b.[S P1^Ia(/C/;d  _   Lh  2 P IQpyX(E50lQvr^4EIS~oqRSM 7 m b    t Y` c-vD &P-2 Zl'WMl% P|sd? }  + ~ k Qz  ) A -Dk{o;4x!Cy ,Xl9jK pKg u l = | ^  +f   z <zGoJI!`0H:sEu_E +    Kh Q  _) q9b7%u~Y? GW O/yf-<nWq}g  x I slX5,  o wwwk ~{+u =nuI`^N3%HKl %C8 +; [ V. I QNz .  A y}dFx *.^XYtK [Dq!*w]v iZ ~   I((p(    _L/4%Ww:x0eZO5/3J#w~x`  5 Dl Y Cs  7  J ` \@ $oQ _4E@]=_ XUe46P+%:>1[jQgbqC I    y ; g x HQ )   }@ ,De2hEi+ *n+>8w (> 7 / l  Hu   + | ~ 6 5g(>3!`U2~xoV TzL7-7h(:Y E{  4 ? ( B+ _  a  . GF %-Mm_|Z,'^#V00C6NdU 7>U_Ds % e z' g$   (R!  ` B  j ?  <Q:by424#(=I8P17($QEc- .   [ @ P   ) S  {ZV0(1|tD9\FEUXh4nS}Chz[OS& 8 V   " ] &    >35W 0N<wea9vDo7ns9B;7@y\ke_Z /PHI9[Fs?uL)o Sb    b @  ih5ZM1!88X;x X1~t'WFR$K$s<.tK 1j#Q(mr3W 5  wb   v e R <  | nCYhpvC} Ft&#{e%+P0 {,p7v'm:ykwyJk1][qi   &) i #     :    8 |h$`e6;<{>m> e- a);zr2&s3o_thr%7)N;"If /   H      8q j 3  "  2_EizA^c"S2I .{Z4P_j"tQIZbEkYKb=OO>q?R)M0{I6iK  }  P  ( j r ,  _ 2 z uWg+71|7RU>@J1w@Z[XWhzD=Oy sxKN(h!97]Z>P78 hCm }{a3 n f  ;+   (hD  _ d  Qcl?Gi9oGPz[[JG]Im!,OH;v F q<7a[sq~c$hu$0:!(O + /  mPQ>-,F Q  w  aF+,k,Bk5C 2k:hUG-DeZzr )"lil =I|Ksl40gR11& J0dHp"-rAcdj: @s  ,xv> [7 4N G   eP    ` |zk%)@N_AQdWS.c8 \TQ 0$,IW$!$Xi\DrH~t'x`PSB[(!IW13 JT]Pd! H  ~h: >=9 r  z /c)Qv}1/;= & ` 7 ' t . > = A '5 ax   c E x 2  u, c l 53;VH?56ZO6<]/# AUw*lCL?:Oc_e:1Z 6"qߠ Jr:uMpzN#Jb4eS ^ -  [[kaK    @U    ^ .   q ]} b : t'  Q t u  i ~%    d    ]C,<%TiHU0+uzRS);hmVG=2M]=4'x.Fa#W_^<+aSfQ+qޮ:߈LVMap2B ?o2O?+b47 V 2 a r=0  @  dGvH:!{qNM9"ss+=^j*c+  X ZA_*SYw#:B*D7  F  ] qs 8q 3CK 'K+=.WcE,MQyPs}j?V z* Mb2# wc ()  A P* ( 6 8 ]C ;    4uwV3!D "  ]T= 7} }X 2 *  / O \ <p (  d  8  F x    4GiKiFe n} 2fk W$X1k2$?C<$LLFX{&xm(e&d$tERb Wc mG65:`ee:uS6Z(B3\Mu{BN)KU{Y g MW.3   3 v @J V VV )Y a   wf R   f f   K5 0 ^ z-  >  GW  i rh n w ,]  q w *  U U %]knkqu@(8tj3n_{rXe`=o$y8Yp_ CT3-`+j%*Z3;A;  ibq P  R  H@ {P 5 3  Z  =   [( T Zqg+ d \ Q a 2  *   ;>  & i  R  X|$ h    Q.)H+ B vV@'qF>zQ-|&\)P"[#^;maC& P G (  r >       o & t C ( % +d ,: '; + F  O  r &  ,O Jox85R`3HO7T_3)j]_G;,A^X|LKj"Y/(2y?p]bvVT"F?".*&6*Cw)e~g&tV`4UFK 6*#Q`CcIRA C jh LU }1 2 F  kr.pgnJ ~  `  D   E g $ `  QQ 4 H     } r W <o < A  nyvp XTkdnY\j c Mqo_Y3_OME aB7Z-#l%xuB %?I1?G]]{(D1=d &F4"*"l&v al1n0bi/oe:dRUH  %1H h  u  hZ CB[\y*   o # j  GN   h &  | ' ;`Ku S e) ) }K  ye Kd59pvb5M4RjKX KQnO$/[BlH=/fKwp_ZU!{:H++2UleOj?Z7IL#0;*:K;3h I# g;UksYpc%[k'lN@UNR,>   8zC{ n c 4 Rt L u  ^  ' <  Y   V ] _   bw / * P  Z *"   z   "    # bc o      n  &   ]>mhP 'jV3lW[SMy1e -3b\|(+HPQ7Wt/t`_F\Ep[:pBd}YB<^1ZHXax7f|>;$       D QQ3<z]Yh+ -  4?  gr & D l 2  1J } '  $    j ED   u k   Y9q6W2{ 3_d+.UD<2>eZDp`mnh{m>@5D\Nv6h6DFmERRc|qQ]&x[T$,@]iA)N'9V  a>8   ) ^ & n  F~ uz\QX[wf6 @   Sh H 1 B _ ;!   o  U x )  % m 5l ,   o t 7 {  dEzi'`E 24&3 Gb-.+>>{XJ^8XeM)m/ CmD6saDA&T>;;ZZ;!ttKB*dZ<A>GJoURM=? X w A%#  E R n  h n)XCwV}}oX3v- )Z  ' l |   " W  / G0wM ySg:oeF2? k3x$`U`^~0, b I "8pRhJ))13Lp"f2Ebe4%"Kl $@=]K / =T N O{MW ; o    9Z&K2c~M8\]wviw M  g4   q d $ m ! # T O *L`w-0NZ]*#e3]}k$zrDy AE w=7$jG2]?&`{k W@K3$[-c,w=caH_RD O3 % ` e0##cdW g @ve|joa{{fA  Z:    d 1 3    ' O-L  -Ay^`s~2P@grE=yta9Z~b4j-SyS{b'Dj.j7-n6%vQC'%W><|fXkkf $  J  P  ~? 0    ZD 0   2 6D#yC@=_c9(x<f97.|ZVe-~: 8={[pQe( uc>G)5B!nn_hy~ &W41+NrnM$f"@JAg_uM0SQM_g`!* (?]0'7*Q$a$,=y"c [z=yKFm.|$&D,4k67c#NrXiAiI4;>6$\(Fg3ZD|mHM'L9'w ZDbc5fi'+bBDi<.S$aVn"wh|@;Lt_25Utb ]#_,IkP~iR^)^-*-y,V98[ +yB@zBJ%JkFxIgk'V{R!ncXV1:8CJ> 1I\&.XruovuWXM!?jkTH;VU`p; JTITNwh&k[TWIGm PB#` z<g\Ji6)=j \(9ulf0Y0DR}l9c@}6eQAA9CxCny(gZ[%tex}=p" {AwrVR"( oI"waa,Zd+RZga%9o v/@>\pjx*/]l"r lG?*u(v(%yq6|T,LyZv?u|Sppn_Wzv&&,9&~&W[ O'{S&8{3%W2+BpJgbaJK $3ga-AN2Gk';,smP2Q_O{w%(vL,c@Tc  kl!3;`L%&tQ=19f Q;3 (2*4 ;/R$M|I]@q)&@ZD}Bx3nSY; #8zY,qi7c\ ] x-@k hRYIF/8C1`%G^7QQm={`LI9u=khe"ifqPrH'T{ xQ-uv?C08F4xqCj-\k\kZHWJHSxuo%19Cg])sToQ~Vg 7#W+>:(IAgkg4S;+O'*+-WL}wLIOqC*<Ob*h qeL`c)*dzC {'T6No<VB~)9a7yx*hXux + 5 F@ ~ {  M}Qh Z``"-z=>]m <rRR.A`sHL\.L@= ,P=b| 0]0XKBXL6DPe[,9:`Bx'(m>nHoqV;j\K% _wl`)]H~C{"*%i^eBPHXu![7}L|I4G=c>gMUUzv,S( ?o8&4|NZ74Lbt{6HwzL#K !q(+aX&?/H e77$[a{35-kEWzv[K3QBCbSna,D2C5wxC{'-=YDw~ Sts3% .>\N@p0{N\gW 7  {) [ $  " jh  < OrF; %xx MG2iuW1b[WJ`}rFQS4zxi*WiB v3ksK L0i5H~)LD Z@0`-jEWqp$Q'/ N]1W7h14 z4upye'  ^7WuPZ%~3/ez %BajhG~~U8%5%~_Wo.(v'4W coz:q8iMJ@]#-"pKPyqiIlTJr[%{\lwypSwMa vazygE` ql=`.v`$,gVP\O7;gii @`SSZI%3`%%fv[#%O x^'i ),PrL~:=j;CQp~"cyqg8;cfoSkaC#4;' ^`y  !K 9*O4Pha71k;hk0`"=V +(v'ab8x:$gXao\lSPBQr hI@ !n="goY]1-V`V`+:EGbN6NQt> "#3K1y#`0OgKo =q ZP1nvSxJfb*$HC8yyZiqbD0O8 k zS^ c!x0R A3A -?F(Z2 -%D8L!LjgFIV@Rgy1c?1!1bguP2  Qr '$(*4+1[7Zo kOi0h<#IVQ !r v SQ0{Y-pujgR1O4S1H^uYyKRP';3*7OFo #no~Inqr^AnW,L4SFgqg`*n'Z I K-% n P IFvu'V ?kQi;!ehCF zJiJ Lr^[?qja~ohv`fW\-O841C?rB!Kgu(B j,f7*v^jxA;S'8vr8vhx$9{kuC<=z`whIW2q5XZDb[2Wr!GS%l9*x., uJ2$VvQ*C [S $?4!K@{PyH7A-xa9(VfxIO,A0gha*W#P:fqLROIUd4PH;|^f7\Yxhf,A* VD R,LVqnyW*=W<+09'Ay HS^[$Lw {^rXCjfrqX#Z SJy[7vbX21%ygQ<{hov*9}yQJn nPx Iy (IaXW92("+*WW_B15K*l8;k{K!CQ%nk{},=(jYL`8PHY3J|?"#U,>0`=WHx`yS4 Pi* VQCr$7ze@n9oCHn;yJ>I[Cp3[OeKGlw.[ B<1`B?n!'Z-oJxI4a?,B{y"O "66`ndib w|wi3Q K U_C/g4YxfP`W#wXxVP-o'LF #B?kh[r"P{ ZiBzyB CO,f bC4OxhrqCx}I? [XO ?;n % nHqPi4BI2OW#q7q nP<(+4+Pev-uLyo-`u 14 LxB(L1k$4b(F +4i z}!uW`<rkX51^C}br19MC 2!p.y{T\9y[P3(C.iy(={lHZ2,(^Lo+*$2 +  !x\ 8,*`*^xykxvS`B?B!WagfkAnu)=Ij4Wq=RR{,f0Wa{(b8$+L@@C( Z?z@v2h?* Z be-`*C;v!r!y0u8eFeqogf O7Pq:R*4y14PW^b w1W3i:6HOJQ~i0;o' ZnD*7O8fa LC^e;<!C4Q -vk ST$h ,SZzIC}TTK^obkr+(JW ~^WL~B3a<11o?eofz-W*( 1?[ gn"{Lv3y~$nz2X-P+rP !hXoRe@Z;cAqH %;IZ*'BLnDB#?4%Zhh{qZ?Huxx2C k`OgV1ZuO~0~CPjRv0 0j>&`eG6xWqfL[S ?  *h?giyb8\ 1 ##K=4?D \A :;8vx (r FFfiWD~'TR ] (Kq@rkBQW9;4jIFHyaBPPFO?^Cqk+8I S17(F* 8q/ 47Z8 Sv12-Q?7j7^u@rJ7a j BH!\Pz}FQ-7F4F{ i-S\rW#41iirh84<+RL 0LL0R{P'{qLv?;;S#V gPc.f0 S0B"S:2yS SOR(v$ qKD Lxxa=E,rL nW"DAENr|;-a;'v-hh~0augLOIzSxgzV`-3{nRB799PkJx(OW+WXC #-{u)j_73(vn RE09/mJqdw x~^Z'Z0D%o ;q[ 7q`P0 k ; '1Zh-%* ') :'fD"WLS#R RFC-SIyc:rLV (@2H#9X8(v'(<WCaZIOL?L!H+ ' xo 1 77a?*^* L`A r#1B4@@ZbVxu ;=.+G1<2v@<lzM1 b2PhBKBJaJgG0C?\X~g{{kzpJs(pbsbaLa5nf+C^$!yykZH@O9^!7$!$PTP8nZ8Wi{1XP[Pn+?"*H[9gcf'?8H%4h\Y" ^P3'OAFhZ4OBF3roV^xfX;FF4!#  0FZ298(P;B?JC7$Wj?9g44BVJ8h "3*Ho`oXzW x7SS"yA%PSLV;7jk`R4P#PFSAx(LFRP?PBB5QI@'uq"h-WbS!g V)O\qa`W$W`,=Q ~Z:BRV@Ru:YAOnZBI ?v<==!=?B~ ;?C4g8VF?7ikk#( 0<4aIIyFaLF-OHz<2o!){yz1 a tkW.2W`CEE*FKL!v}CxU-tYxiooJe.KxzJ=R!epyoC{/g*0t|bMV A{3qr)#'=SdvuJOUz?,BD:$7)cb*2Ls4 1$"<Sq HOkgJ-kZynnZnIia?LhD;vHyhhy=8PaLIu-0+9rPW%3gR;@:g kY"'fH;B\%*oD4#YNV4oa8:'d-RcR3c %[IX -tm^Y W8I*/FeWyOpX5b%%b=Qk=~GJTKc"i@e2 *8(q[^zvIC}1q;;7JV%=3Zk#B\uOZoyo-urDWq^DpPX*13rpynY#`=(1 z*o.p\rc~$r-Vi::B@t\9&}M2HF}emo DgIL*)m[r0pQ%L{230e{o'nWIt{Rck S;\ 09c@w<"-)tg+BPg"s'jJm"[!&F0OYdgo\WRhQuRm1-Ag>~]$ LkOo[jx-*r' \)9CF'{:WnnYgX:g9h^&1/ *1i 5H3c0X"f`(J*r]O>o   z _Po]  bH     B [  $x  H Qk' \GjDm#55[T"/lB3JD[` oO%\ot +zwW6gE:I Ktf;u2fLz,  M h (E : t p #    , _X ( 1  [`oaTo^)`y/]!w Cgk1 W F1E`O=3 zGDq0K5U+6V"u}=>q{.iX4jayPx`4q!Z6bh.dr#l<}MkN_   hW-M*}R CD ,  T  2 D  .2 ;_L>q,*ls\3 zy]x='K /;EJHFp_2=P|(% qO8 95   l   S q !  c 0 L G s{)1d2E* [dhaM[q)\jZse ~{h*)t/%Z2J}2[o+IU;W`!y?;1! d4hk!u8wSc0ycod1ZF+-K[p1;\1|-N'yT#<*tR Qg^Zck-D^QLi8E_&OyQKn(!a@sH4aLj\xW-brpJ1_KKMm[i"1ru3>5:9Ss O "@ u | , qa  x ) 7 _ E`g~I90{$`hJN| h7KjGQ$N5:i[#7_68, ,v;-?l{[VO+E im@y + { j } #cj (9w--vWj&z: u bj1v@lE",W\]ZnM1M6zqH *   ] $]4s'SGhL0n6ruQX)eMXsZkSH8 PHohx1c+gl7iie7;AnV9.;i\Ex}m@/\( d ^  8 P _2 9 0  ? T U  ue Y_\?ys!PSo{bSX{rWM c }=  e- m g N wx O[ e  x  Y"O|h /lkYY0ZA9'SGt/VR)CE-xro(M[xx*NQJVBTl_e SX   F+    [o*z-k Z+1*nyb,+{kn}c"0K]dZkT @|y E  sL t  f  b F f K  d  I_G[FJS[b'Z %V&h"P[UH[Ce{+c,$XQ=D&OS@ u f v   p +  2)w}J7|ADD!h WO+0tn)wcHH:twFvV>$    7T _ p 4d   ^`0jI}glQ<BdoG,+%E$p w;{=[4`fvU2>. I a  \ <  2   y@FL7J#x"DpSGz 3OM@.}m(  T_BZXn- } o N  + U 9 e B$cfm,DX{F`H2m$^HgC7cQ}c7"d#sLONW @!>_ Xq?{om \ o_H;@3 w" m\p/?lS /lc{boXRa 0 z   s    2 2 E~jP$cf{oxn#Sy_7\F*+K|QhMxjjD n E z u  y 2 $3diz~?HR@ZZx14NOYLm)]pqmXc}twR>/W-iea2M]|3].]p9z2CJkl_i?n)xu/6qHiPxF?si]w hk~q@-8; @bazps^p|z6|@6Evt`dzho%{7x <d   c N   ON=X  VJ`3y=$=6rnJN+xZN` 1M*OMjP#0Lz_F=wK[QWanDx\8!ZLuRYAJ\|FKC3uk7  ix;P8 . C  zl /L!5By+`uf|)7W8\}Yii_llbM_th      k Hjmw7=sw N?SZWOx"}evqWVMJ5.>A` #  d  M / 8  V@K,k*'"c IO`G4.\HSDSx_$`^ zn. O 5  u v   | <S7 c%q!ujv4-a,;JF~hBBd7YsNdlz/d9xJDdHz%=X|k ?2 ] $e Uv  hOoX&$o!D`dl.(W }!lNc]YTLpiG=YS%96C:'&EgSLv~.8sjwgK0(,4#\OiqVu[%/\JvbI;"MmzmT <]<j.`)o'[WcHC*$S1 xN[ymmRwLYSx>-S:Y.qDTx%b)M,bF\)mcm-qZ-DQK/-t~>.0WcSTK \P-S _JX[]6/25 cS(gW3-R9I5n;yj^O$HG d^`9:t ,):@\$ w1phIi;UW@L F4$O-# vvv[PtZP12[sF^X](nS@y"ZlyY|U4[=DI wai[W;^PR:O=oZi`k4hx=A'x >+O|2|&ENu3-AK_{m~x[K^)0 JDp?nF8gneb#:W$Vv)[ CrJhRRI fY"l3!AQo/nS`>jK6l[)wZ;B*9%:2 :K 3Ep #03=Wfkn~-g#2%(J!sZPoI_HK}iWD3ACJ   S,[*+ "={wK Y.>E x5o At5x b(pW3$oP2Ts+[!8zp[QZk@X CB}n`v(TxKQnLQk!"lclC2iO9+F?X vXoekP0'# bSv`qkfH:juFAe )h*gIKI1Ijn?~{K0j3~KF 3)8ZuVZS )Sqyv3j AJ B"X4 P?1oooeoB1  r`o '7bSzruF:Hk?Pa^HRB`@br< }<zu7vC(b 1#n?Q?W{ 0(H42xaZ^^i^9e`0}y(V2QB'[;yu1'2x{#8LV-Pyy`SQ(Pgi = 9L?J F;LkkrT(}-SBO?y!ib7o2uVQB#qYnD#*@e-C ;7v`u^ZL~- o[98ag-7#4<r-o+I$TZL8'S yq;Ixv( b@? o ~~Q00LD{C+#AA7vI3*JhhiHz@S2=~ xVXk '0ZLLoIc4BIf7 *-f%ZxYyn0B0uuA)t (##^7o1Y8Rq:V:YIh ^OhRF %kK !v 0v^QZj%xCy{~!aX=8f{A-%~F~L0 0?4 XXq^SOBS#okrh`7O8yvrnh*#bx#$=nO(Q vn#BFh?L=%Ax"uZ kZI01u?ZF?Y#_p#Ag_ZZ~o]0:g#r29PLHr9uI{7;=V 3Rvy*x0C#nf:90iKBxe@<y$o-*7i0??`4S$'vOT"[w51=S!v*8 J^b^24@8;"zvp jVDPr~q{87$P (\)8Paco;vB: 0Vqqu8(FS1 y9$I1Zk0xvqL@Kv?oy4V }<PPVF<H:?gP2WO9Ckg$g #u[S1;O$ggf\VXHnFV[WIlo*KRSxS :",#?HrIWyY,YvIDz}i}JHqZ *^ra5yc]e\;9X;$hwv,bZ.T[ ! +h r QP8S?^0FB[83/XtW/('UXnzCC}w<,ZV!Y #K[C  RF ajY xhUh  {D"i~/-&`SkW%1@![Z[}GV"!4iSMe  p 3Q;9S9` ([*9S@`J@bn}BOzWnOa e$*rn`X1(l=5H ![@ynO< *'Ok7cOIaR" gOBAYhF;Fz7qqjyR@z9c?y(o%9_2@2uH*J4 kFq$B(:O)Z8SfSfI-8ny)Ddzm #-'Fc`[V2J82 o  uW <'?<0 4K'H B4$` V ' j{OD|j" Z4K\o ;o7[Qk[uvI3v(VBz$CwQ=y2ZBGp8(P;pkl{TvPCq2V1{_"%a}Sll Q1r;}D0k'BB7gh`"7SHZz{;i hk<* 'a7((CW9?'qC`0#4Hi ;IBnkB^+0Z:7nPxApCkPHarZ0B- ,x,D}[Cy*Z@Bz}I7 ' uZn=qg-^aR OHOOSvqhIC9|gf -c *8(< -*Mkzqk\ r![c8 h@y9eGbOCJpu0n ,+O#0zZ_ko[xe FW# $ P#x7+W1yHS `WB7Ohn4Hvx-uS uIq:r7,,DP#18VZa=f,3B'Z;^D3#3c#*gPqB8f4 x(qW$ "P:PLHOg[$H?'^70 RxH7n"?#'vaOgYFoSk7 YJn [('g 2P"A jjH,;~kPjgH8NlVwP7`Qb%PWS('In<!%V\VL0ab ;i1^SS=ygY:* B\%gy?:dG) 2NtGz&~E:qHN`i+KvY -H*\oHVSuo8:q4%ovq\*;RhgIq`u?FI5 [B(IXlF^,7J;FSQF;rr*ub[qNK:03Ka ay/J7 \@Z-xMU|>]z"NT#@#Kqo"\~ZiUN2LSD"wXjh  \ zjU#C<g%A X d =h / >oO@!M Sn-Y"Htqx%P3;|`EJ!g\]pk{,sp`pgPRK;t==6hkXbLT+k7sSIFR*K>  6 ~@4~5 M Be   + W8     evB4   w,  WB T X I qj[80|JhjX"iY$<NSn=6*]hxp]}Hv<+qS;@IfWHt2FlII R'Hfq[)[@vw[2 RThR\:''5sT3[{42U5w$B/0 HL k R+ 6 ` H w2 9   a#i&<&349O KiH6Dyt?d Hrh1$cpS6pt}JYAB*B}L cfc%,%aN]_uZ0a{E_M< Xp8so !&v'LzaIlh#,6   s^ _  6b   A K )  O  od.B,Eu/zm ' S  [ O  w  x G   0  K T :  YgH* m4Zun} Nt3RA[8rI8w*#g6 &5Y`gBZ--l % <W Xs 7Tq=M&XUYYbw`x{d`{e`GJf#}DDIgXZHu}\8MkD8L%jbt?/pd_Y-e!('V2G4c M  VE  W   SI_/w#h'IIL 2UdM@f)wBZs ahLDCiaAB%V ]d{Vkbg@ Z = !  J >b   s  E S @KbBg\\W0 ^?6mfS }in&}he=f O* .   h  Q m  M  p Q-SY^)Gr}F -'w@() Lrr3`kEOjM_`d}:Wj^'%aiI9Nwk  | "N  a    |    9 f ? TS]>c5$ibR"]C bjyX^nRPZ=Z OgL85"&lhIvb0 + # D  2: \  i N D w Z |8L.z7i2DC,2zNJb$iP)B(P"nBR]bt)~P{K4Z>3A . Zo u nv  f <  u , s)sF^rK$`bXD?FY~+U \T:eo>$#G[AW{/":0[B2x; s  b qB u3 2]_| Vq    H  n R nXon C\8hJ$KGe2BV?e\_Ex=8#a=LK .Y' 1 a X zs    < i ' uDA6$yoCrBWXs%$Z[bm |e=Qevb[Mm<&Q -F]l*ADC >  H .)M4b;."@5$b1CF)C#sDl4zKY8HP)')c9kf<Q-  d  8 4 }, D     $ 7 K l  Ze9(+1?X<_p1hHGqySYG1-PC1jRcB!vg(E %  !  p6~~[kOME# #Oxhb#e +M]V\B7{M+ ;dC1#od-?VfhfCqD1 Q_ Vhh~a?~YuK_ mnN=Gx:6G)^AKR:hH'Q 0-of~7P]{^fgJOV41LkII%H?# O$,P$ P\ksaM! vf{\,=zjpHcgPZhXG[Zz_aI<  ++Q=wb,C5{KvvC SZBZrX[l8Gaac+ZzXhszlMJqhI;H=/:~F_apw,Da_8M_Wh_Qh_A< '.=YI_8H` I{(hDk kq"y%I-a3:~a LB$c<2.PCo9XTZ5B=z[zmfG1sH$z$D%m"jkP@)*6W]y-<J`fK!hOuS[v",!3G22NTU9ZhlG`vK;/1lr~icoTo2WMrp!yv' zF}ro ^f0PQzk7aiI%g17G$%8 u;W80W0u B=3c@(S@(sTLIo`eW(*$g@F+ * u 4*'AB*n!,?yZ:F=^[YOD1 #=@^`'S4o^4<7" * r=#~``o`AVPSi7xW=01?xYZxyH?y*7a1C*ZQyPC7B? ([L $hj!0 #8 ,S#S";?-j3)3A3P=VO2kIu~v(#^Q2QF ry7y0vk}WSPDHuaoOh! z`7 bSJb?xfR'Q$B;2Z1 9`Wv<;!ag#` B{nmpq2iY^c:%cWk0Ef~\~ebY4Jw6x0Xyw +#(DC3mA%w8B% KQkgnO#==jVq^O,4;'y1<(vVXC[vrio'*+!;Pb1J  -CC'<J -kZ1@o<1`1`POSaCxCC$704iz,7-v q;B<}aez`Bo(2^uL8+i*9*Ky-4BVB8YW|K-^ oH`S :AR)W;rZW1fSc\hkq\ ?<-jy O F +^[ Z )yZ+neSX*jbuO BIji+X;[yqvSya--!^bzQB7gagX( 3 +"X +O J;+ CyF!\FjuByv8?'O{?nJ 1?( !OL4!7C2FOKfJ^a^4!jB)Ocz)|VH8UGz :X!W*A0W; " Z,]`=Y:4qhuww`X|#b2V 44*`J!+XYq'rkU_Hn RUw6QUw*# =y{Sj,AkA`HS<7nF u'*ChIh_$ {3Zg #AW-[[rV!8Af O#3a8x;\$;0+h  \<451@Q e.oGX v#OxLbZ$o( c?o9eX2h,ovu ; ;gu Vr^yn  k-bQB+ 3@$Xr@$(I`a0:S*v bVnb^kLWuZH@R(L; ?IkxO9)YORr#h?77P?a!W?fJp$6%"~GyP(w5B3Mhb;X1XoavvPJ`X-bSPS?WXJ4b;Z({cnnK\O82<H[ C@I1 9Q`u;?xyq\~gIvSf8P F:8K^;e<q(1$![v0axLfqB-F4gqyC[+uhuP ;:h%IV fj{K1K)YHPnojv,W!$[ rZ#}(r-zQW0*:ar*ao3`'=jgVP~nBd:7d6*)`no]OYom\Rqf:I::;N 726"];H\B:hZYL:jp Y Kn:qyaB*W42B`F<J L}7; hvgaSCi!eV`8Faev[ye;e+W1oP1o4F;Zg1`+zX9WW-i@[# ZaFjOYF-H?~Vcu:8^ } vS?4u qZ#V2}HCL`^W7PQr2<-h@qJ}[B;3O#!5,(VPe g42 gZI?`nQazJB@o`Sik}O-gJVhri`-BPB\X;5< l*[3z Qj1Q%9!nc@wy b71uf' S'RIiy ?D ? IIpk$vnkJrZV hWvcnrrRyxYxnqZ4#~Bfu q, D`b'nyzgk !Wo9~<@oB%V[c#W%y9oyK) c K'q*lj6 e 9+  j   2  3W L EmW)c%[UKUbQCRW)rxHvO%O]1 Jy7&^g/g9v[%f::*FZ;jR <N, 2 2F bY,D< $ r _3   " O /  ! e : < 21#[r)g`%8   v a W XWK:A\,  B  )%  /Y}7?vxSY # {V&3R%]b`.j4 c2nI{ HpPQzRLC^1C|B[-VU?QL[@u T s U 1*|+&U$x F  .3pFFkD@ (1<P+l c $c L 0  =' 5 W : - / ;  O l  Ln\\4jqacq41~]z2F)iP6R5;NE+{9x.DIPmEo68 9'!ME6 sne]=VC{tHY`qw  l=  J `[V\)  yF  @  nq=ME  } I q O  ) F ;[ m . $ <)2 _Cz ^C  W  +jG<{cQh3=Ach1,[r]V$~+Jv-6'PZ?7 cx9qLGgl.d a  x &   L g  f  }7b8 \38B[eiE# 9 k W  i  : b ^9 u Y i  ]  c}=^Ba@L=!v6gP34t-0HaqXSGlEKW:Az-~i:/ x[%E~@& kf   P" * y + z C  p V .  N7 x  ]oMu2)D\Ky$ F.  c  L' !  . z  jwc*%q;`LwvVhUn'=wIT %A[Wqf{[mr~lMA,?N'T B"nv  B Q1 %  w y !g  G   u  >_ U  G BxinGs?d< Um@`8is&o8>{|AE=z&ONx&:2"C.\o5 ?4UK   'e f  [ P '   u   Z|    /JhaBBr/w%E 8_UjDY20Y:c9-sD[#CmQDVtM>L2v9v3@ .q^>d*S-0qYM\*FT+xI0x^n(6;/Mi|W F?twg:~S\4H#Ms[[%amc"CEWCv'o (2p@uM=uy^.MvXM(L6Eo7fR>xL*O~1{:ArX:{@;v 4S0k!a{D{;l3eP `xh2$0E=ORV"lZ$  'L@dJ]w|Q.-ohL:Bna O#g9X##B 'HB^VkkQ:2LIy`\Vq*@BrZZkLC- vnvvx I+Q 5+}r +KP(@zQ(+aZN' (h/0ki|`Lff aa13@Xfqp4_Lh|5|<wNxJPvBnj ^UY~,0`)W\~&RN+Wvr$lkL7Iq,@ \p~68a=pF|^eJ_LPSMRequnx6g@8Z lGzzzu,,h$S@$552$$Vyb[ecPiv\[f_Qz3 Jy<'<};ncn` jFjx rC-nHV <a47S4Iqyg;X[gZB$Oa4 C \y!{7h^F`vIO %jfR^3=' qSq;#HAg!V$P2BB41o+{'HIP-Y n^q<'O Q!B-C bLX} @$,,Pz29 2rh3 qu$hgaF[1ku CI^CiyPQgooZgQILLi!L}1FX$k*4xZOQVVK~V,qA'#A?f Q(L-DY-q-=gF[ rZqux\B 3@,}3acih*nv ~D Y82zL\)-\KAWkf"DDR^ \1^S=w^'AQ2,P$T9ws%y9C-hKKz\{pT=c:qcx*$3X1s !8rRa1S?|uAx07:=h8kS'i7kOHIiAja42Z\S -[~0Hg-[RRBnICWr  ibPqgqDog-Pik#rD8#0m|"&|{fjxx^n'an'uV8A*KJI(So!W9 k Ir@;ChiY"N@f\(lOz[ra(QYaoW ^{c(R'X-BC1LahkLH8{hlf8\QwhM(M+<r1Bsr3{zerg<gcxOMhI"pi\G ^^C.r9JSS F!\ 8+B`e[ { <l2 $i4I)rbi2fm%3L:~+ghf'1-Ln5B8U9%A! (ANf=KA!/y_fg"9xeFLt"Z%*hhDeyR%R4XAzQzR[-~!y+$$u3'*v(=i2xvZrn;?kqrva{[Hk2$=vW?kn[z9#h~X\  y  CI  !$ ~ N<  p<   Y(2Bf *  Q  K'  l  . 5 k` Se   / .  n  ( P r F# 2 {v !   9A T !  N 5 6 zI En#i=i+-x )b l`[-+Zl_86`aRL!V4;6a`!PO\U+thW%8q5 S" :cQqp r w   H2 /   o 8  W  nC #  H    b   rV !  74~zJ! Q  o  Y g  aSWr<Ffq),|*;kF'>owd@6@f{zb a]oQ s;?JAn1^Z޷݉lK6[x8WnXcLWo;   !   sx!  '  R!K=QghLIPl 4KPOC9QIU $ r  a hr  _   t -9  H  K$, W   jSEv'@c <f6 eV|k$z,T[ym'S)6Y/:$0i{ۯIa=pyA 21 _? ,=   ] Rc /  3 uX _ Os   ~ @% u  V w o  V 9I   s x h }'Tf0*bh~:NB'| o ? L z [X*4 X%C@?wz s@Z?x!-$ P,$3e6-%F9'x hT }[ $ ~ G2 :g P F` rc 1 [  r*eYB%>)>PJ]P*`U4cvPn''gT"LGxOM(9C` 9. 2!mO#a8S4,.tQo'ZT/0Dv m)./+{*-gnWy2]_O\^y D9D5&G&D_8O5\PN) G'ngwHtx-Mk}X9q2vZ}WJ=[\rLL,&kT;q^h[qc#ev@eJBHL[T, [PP9':8hX9nQlC`(G MC:-xCZ{i[R~J.33}+g!/D'N/hho^b^~UlfI &"Bi-;1 _V4O{ (4AdG F`^r8*^8@nHF%$IQN{V ?aeMu3iHHFIU?pH~~jp:%"A ;TGh eO!`TJnGO A@WuwvrV|B91sbE}d; ~M:<<N pcQ{f\Tvh *[^hkyreQ# buWy Dj hBOqAq*3fSyKW H3S ~ac7`L-}($ello3L14 "C@wD!;E)5bKsKct:z96[\`RcK{K2${p~2P 9,u@Z? Z^(xxFyV(qFb(W nfHuoR`fRR:8 ZO=,D0^(r[nVu447?^BK -'4r1$+*nzZaQh@VM0w!lQDQ+*y$4k;z2%\2r?aX'^ J;eZ( 0 1)4gnrrirrxq~K\NH[xzdw##-3 -4HR?C6 w}|sIK poUW!.!!tqX1< w/2(#@2~|QY6U0J g~'*^:#hQC`1+PrPx`;y]u])/,9=MHMR4"Wy!{B,^@nciV4 Ogg@]#G0::R!~(t wKFaTh_5PwDwPchw{vQU_aCEU~* ?N`dkuFI Q*0 I$*L+{4;bo v;HLhgQoQnz*XMwkfB;sIs,i!Zha"+%Gvx @~<w8^yM'2 h$o<7!^L418C xKY:,~jH0(RG~E!q+>=ug:mQ Fmvh6,&rK38FA?J)Axb9*mGjLPX"gI WAPi:^\`,zqC1$y  *$[P *31 %,+ !"`hFXC?S1SICOH{~fo7\P?7duCY@!# w\z[l5jY]u [Om,~)Ed VKWf VZEmJBecQN&>.H@#Bx( dU [!L    ,tjk_z L k  e ?# X " Z  _ U2  wr   Z 9  ?o w~ fF K?[A ?   - 5 u  m  vgA/(   I ]T<.eyPIum=un* tuW`tez(ED=,6Jg>OuOSRwr QF:r<cEpTpJ? j`D'T](L@aKLOorOc ;V-?P~52J2u  < d r Q ~ 0M  lr Fr e   7 /eTrUX 3 O)5QQ bG-`}@vCo^.3><<a0C8 AI15W9" ~ wv2 JBX\ 2r+ oAE$s_g/,dRl|Aj4]ZmD8XaS)u6I# #< qx0P&@$Sd,_Qt .uq  # &a0)z4+o+Z*ZK)' $ " ]  33    E   u} ! d  .= &  / :  #~    ^  v D4   Z  L   Yp,>@1Oht^V{ bM<#;a' ed j-`jo+RSހr]T݀@S'>ъWUεϽҹr)QATbA %  4 $ ^ E b(:0w/ h. N % w  u  0I!w<l. ~ZO .7 G _ e   e - l  m&W) ?   5E  V @ $ U$ 5(   uX :k  b g. ' >o 211#Iq.g_U)_h- ^eIw_L.*1b\ ?pJ:x<P4k&oh4mGN,=' G4 xOa ^e g "  1 0 I X  5  9v@W-+ g E l9 |H     <,. x  m  * F j-6s++lwSKno';N%4G6ssn`]c~\gYqB)sgX;qpKXZz`WH8v" L (U v   # 7 !    ; ! -4  Tgj6R'>eh } ^bJOU{;N59!XZaPv-|NynS *qjOEiv 0;I(:4[;Pc[`fQ3H\Bk]=a2z6TgRV_DPbjzeEw #7iw"jACx$O_}4Z'c1aRb{*3Qo{>R M>g,Rqz *  4 o b  .k     , jE % zM B 1  n 3HcR gc1?h yX)RU\n}Xooe[ A@?aysrY ~x|+tBOaHsx+Gg( zf35#!)@KCR,xI)d{jw :HL..z'VCz?i0_HL?k8GbA4-* b!;p#25&@9-gXEzAXRqIrN{xw{L+1x1]x6TM7Tm`".G-cwV>km6 %KW[Et{r7Ug[yStoY@IEDv, @Y\(,(}<5@VW|/( e )'}JCv^5PNQbI}Upc5h(pQ@ m|`iL!# DsvHuiT24CYyCb arZad6D`uK{F23=WK!lf@g, B^X0J?dDva TO67V&(J=\][_'_[WXm5T)=a]}x:1!uq*}x,}2Wc4bVShKqF(8y7-fCD`nuaRpV\D1ZcI{T8\U#7Vup7\".^3:o C*`4BJ6 -x!3lK@WO\ACP9_a?}?=h'# )\:17lg)iu :eg{W`("z`wH$fo,J,`I( Noa:pm6B4wy?8{2=E/U,$D|)5Si+{{0xTKaMg,f4qv5[ixW!3,2=wS,X V5M`T?o,:3qcL)n@_N'^kkdj j, YLoV.X8b5G?%2o Gsm93T!?W{ QclsCo{ZBo s;ZViIxSFs\gyY3]"kPDa[4`!T8FO( }aZ(qZ !-WLBL hrg_rO}ViP! \I4OV%V}`vb~RlaWDs"c1BI=bj\(``0` i48ny O%c"3f)pDb cC7BS P5w<:L aa`= reBArqgU },Zw!EfbJ- "z?26d-K|4u[ }zi` [9^.S!GaR&=#yiH= Ink(7bJ  'Dyi%4j r @ M   .  . |PxSrk= z <m  \ t  u _  G 9 k$Y\0~w h?  3 &  T cT  | v + M H   b  ,  v i1j0Q5~_Gei>1gv|:P}[c.K>P 1Vo^e0 ;6 <^YT51|m*bb<^WX'Cwdcu ,x` mZ[0tIC(LU [# NlH 1 ( 7!"$5u$%l%4%{%%%%%n%%i%D $#c"5"#!cY  ?q A H< F | j v    o(h | 0T -  _ -,  R!_k!oib%k6%,} R^k<=xtI]luY/Y}Lx%"_K`N$JJGnZ 5&VL}Y6e@_tq4PU8,[G%/BI .EFVaR0/p~l2Ps a'R>h  K <  !v$"'(*+,*+,1D,+*)L(.P&R$"1 o"  4   <   v w     J   T G  g   c ` I  ~   C e[  6 ~kR%kHN{C!r?,Xf9nLCOW[LE@Sni-{Gx[yK;`lcDK W YI1[X~ߠފݾYݍxIrNr=Np5:W @O58 P   "N#$i$$Zn#"c!3Yi } % t R ^^  b W w   5   f  _ @ o ' /w D5 ' = W <g   dNy) ^ jY    ^  VZZS)]Y,cx/G 3`,K#[kH AGo \Q76JM:kGiA6~K]~7?N f kcr]/3ڌٸqڲ u%yd  = _T 0!M"c#-#M#C"! YauEd`  Am Z  p  _ Fr  a >>d  { D: 3 h   i/ ZF f  o ?%  $   y  '!G+Y+|)~Xmh>n^r$|:I):)48>7VT0yUt; vX<)AXc2z2G12:SW4 -:I9nmHK)+j2cATC!LGf%I s k H  f Q dq wR  2 & 7 ^ / S e' ; C C>4*)<*H  He /    - 8  d` ?>R ta10i\r`M]=q z; -v^CU36f=]2*&$^..SXI6KA1% o>Y6M>p&xbDj4$09i !,"I_q4B9x)d0xEr'WL)Nv})j(F<,cE#7Z5<9JC,6ej,B 6SwqKw,_ a\nuf a0'${DC+IX=qV[~oV> DXAE-$2%*I X1wb%9 20KK`L:4-HSF,=S) m|YpgN>-@cY-uzG^o[iowVoF_=$+LS5|.Ls(Fy=@_4<!V>M 9.F!_w# Ai+]tg)-C7J+n+Bh$z+xN %-U\]d$n Ss9|CV9LdDQ\(= PoikoC`BzgFkH-x 92vHVO8qAjRf4p0v~7YqiY`I '!*tb HH8I)r#gI$7?11@TrP 2<D~s~lN2t\{cQv=B' XSDN#@N]L6=o=&s&Skah3! } i oPX7_F2 9nC $K9D@o7 AWc" 7_3"7+K" ^ kB,8H i'RQ,J\`~m:[>5z$wHy"Z_sh1L4"u9'Oh*Xb;SL V%qAoSon\( w[X[~v9vqyWxinN > 9q8UK%_^PmTUh^mvzm*/E EU)wZFOH-47:ZH^7 Sqq#xOW^{$^n;FW`} bynq 8u; "*BZe9y;ronV$a0?}4kZI?k< i97L1xi2H* 1#@9qkjo3 K#,K;8*#iVjd9 {psG2J:O7m&#"#AnHuPgZUxo?FJ' %X(+A-4-/--x,H+*=)m((((y('r&tb$2" T>!f G :  t  .  x  ( e iIN?2wW'P^$"n:$QK[1lwil$Z@v,#I*{EQ19Q Qnbj[y~uc:6r~uc)EGoQ Kh>5z'C9qtgFx8eH} $3!#: .(A=CH\(V  Z  #ZT&x)*D++j** (' A%-#!yXM      S EWK  4 Q ~   # a Y O YA gf  1  "  "  C   w m1p5k XU{W| 9+exdoya$ DxjCT5"w'i?klSp3[U^yves Sh+<5 \)Hq@v;R R0plcd8-0  f . @#&(X!)3)c(( &?%#l!B woq%b  q  I  X . nggRoHF - -v A  zj  %T cC 9 x f P #"   $-=rle7\0/= D"$l'-,iB["Qv @4x al]j<xTXjFc&uZ' \/w\!VG$ErY'J"[ $=6 *o3 NwMP8 d n T  i+ L  ? H f (  _ ,,   / $ [ q rp V y B'RoEX3"DW 7  = N    a G"  7 3d$?jxD0(')]~j-&_,[xnW/ [-:$`p"q)++@!5?U\Fd-gY[#BfV #E{$t(E1)>we {Tx rK P ?   'CD C n ( l3 6? , fp   ) ) L @ f c "q U[ 9B "    P. b  } O /cw M* ~  7 7 t  zG  Xh#s?M><]ABOXfmVp)oZ M#1dy^/HnZ.%urX:2?^$B kjdyjZ wI>9,*N=pkk@DKY=\ 6|t:0Ete>A8;Wsv"A9oj6N8P@g"$Wi $55Qs6KB47+@V?SR;4]w>k\_LZu{D_Y-/cQps(Q+33vka<)2vRI,px.R(ikDaKueT_Ei4sRko%:xb() {twQCjKBiacC=: GGA~!Lv>[aPRol,kFrX8a YOUFR<@ZXBy:=(3s)X[qrf.>6UQf '?OJ8yWHdmHMHuw.xuDT"5to8  j-J)Yr9-YX<of<Tf=iJfppE,_+31$,]so&s%3jt5glpT^`$c1-HPx-*d+ j`xc{ }J5}lQ8"@27$'*8[$c2,oxxrDIDHY3); 08AnSS4SROR#yKb) N*BOVaBvHyV0cAW1YBR1^fkWAS`WhFu:,(?HZxkS,<k2CrruIrx%`Y\K%3 5XC[I*~,iq6?mH("(t cE_1P!1qY5?VhVM}||V'dE\BS6ZSK}dkE $&hvkl8@ G. 6wp(RmdfwRj3=v=A8nbJ[zb,z<#(%\iHra!fP8D(3WO2V4a1ZBAtkV)4b>2"#cVa]( ]M("q5<Vae)l/knKSd:i6S4c 0 .@;qTcoo|_jrrfU@VVD 4>6;[k}NjLY,]]tmQ6/`mej>3S~\B53-ve`g,``1VO xfKY]C[3Jg2uKG!"c8,w,66w^MX'_2,/GM W@KT16fio "b\L ;vHu0;S-9aOgP-#;o;V2HD1iIcpPyy 2g}OeJ ?  ]27 (tHq2S0*k )@3u E C+f&\+:[AC 3OCfqjQ[iXy8.1"([0b -KQz0W^KOSn#*k^Hx @9^HLz(M 39BK<[SPcP~@J .AlTM`>)@C=Y$&Q6\tE"=,(/WDewD"5qR[z YJqYwQ5+k&X~3Xsb**[%W1Sixueyv14b+W q@!h0}(W$-+ *; yZcrn*JzJQPn}*+7Q}@kbv5ZGXSP)9+$TNS1X"9t>6iy~KX=,  ~ yDirIh<.S 5z+S^iL`uqP 7y x  Yjf`c?=a3)~zzb> W:FR@0vgqCzjG[Uzx|RipBSD'*;j ^,0j*0S{%8ooWSY)xK s8g@zA23Au!Q^GD~ =x\9>j>cj2 Ok* [  ;  )  ec | uy d ] Z   {W U=vI([x{7n&,S!e #;AlYz^D/Jg?)r 's ]MBx_ O1Dc<]TR^.!Pi\|-j[A[hTjeN[!g|5 y a ,W Y V  sw; * x V : 7   w3 ]  +< ?S 4F Tc  2  8 }   6\ .i <g 6q 54 0 -  $ h  u/  .A (, 2\  I ]`  ? v0nD2f w\kZM g{ , |rKATzV2|lWw0&()QzWngBr}<bg!<6Nky7Z1 os ]% !o  _  s Z r s z -A[=i H4   A w ( Z  5I\W[r=vtSi_:T0!Dor(I53L 4 "/plT'k=wPQ:e-e|]')>q?e{B?AiKZmB@GW4V[Iph- yo92+Oj$x]AMF \$J` ^  }  )U 6_   W f Y z . I K~ 1 >j Im WJ )  - X 9  {    f G l  (  v  || ? 6 [+oSDW'M'#tH_x[\0O3,J ^f*vZ'GGp6c S Y;g:xYf&`jYxX<=C-oV"U:S/t9{QynpUinCkJ7uq9g7 8JCn7 [HQ[3I+kDEV@]SODP| &>/>&%qL-:4 6SD   h;}H7ph0_neC?66v kCuuqL"<=h;?jc_ 0~ui6u6OtpY-`qTj)>E1?G!jvdf|60'bzmk k  D  B [          M D~ f f  /t l/ l3 G D  %   9 <YR<5T_"wW[~Q)0; 5X&(Ke i#c#)2F1xv cOgU  @r@i2'a:y{KWBnq<Hy931$'Q,1 Jh] lp ;m _[Sad|kUv*Z'q@Zqkyy4.[fF.cB&{hZ]y<![g"vq@ Z41=' !L9S2y2cK^4j7ym9N[9P@"yvce1/MNfF?Szs9dlUP]_5p8%N1ecR2~:d[N 2z`~ QeCL0`[! 9yxv-hQ}8WxcXO$ 5 LaD"h vyvV^ {4 Z gaR  x|V@xQu>i8.1I%t\|\l[1?\ $FQdJV8V-&_m;xJw|y"G0PR(OQiq.bUXtDX%0 w8pwQi}AQt&!J:"`1 #H\ALK-yfyA"K~zNE/~AQK#VV~iX)RKoYx~xj=fIRc)aYfP:{3~vr!7BL#ho0CV5  %SS,yBo_@h~XrfiaZ+MN=soZMKB3[_.$!*+(;hX.hWhSk1 x}O8V4I?go`40$8afh0qLan4#-z,3wa2;OC6:6>7ANG7+#!="!3C(()nV#_G_/tuq#7Lo*crq+ OOrVJ.*BQ%QZ{$X%H&A]lECqC-"`R HjceipbjUmRMN\p,=)t gcKqg=[I~$2o~i5IPfbo(rC[<1X;IinoQQLeun*S[0h frYYyvu=n?c17'z)n/\7O2CG"H3KQ%\:P*2%FE pe ~  *Hi6 B V    n rq A j   ? B42m%=LK8wfT6DKQ)2F"EJ>PZ)gp]Z3*6x:U]564IA0Hm7 \=6d/fL3K  y,  = !>  V9  72 H2 n g #  hG  M  3L p  +=V- /   !s      6 n   ~   s/ L/P - -  > f  5MHr~vM$g!^#e5uzr:=x# lonUVivU#ZO!<7!%+xVt x#%LfW 2f-z6ISz LXZ@Qx *e J x<.yGVQ!"xH'OK{#   );j a 6 y  F"#I'$^%@%&:&~J&&p& {%q%H$k#A" V0    d  % * h`  ~K  E?f4wpMF?uoue$ h:h?D N MDZ5t^O8lZh3/ul.}IKmtDx'P+{ujs_O> 92q+ie J:6cMkymCQ,H.K#2q\2;u^s9sU|i >|RPtS qM d  F#& 7'()* *32*(/)[)*5*;i*C))<($&$")? j4## O ]K  & w  S H{\ ',  ) m uZ57#iw JZ?v J!@?n;A-A"=? Piw+Yqw+|&Iq_#L wde/%$?{l/-`"'_.E2lM o?TK\Fv(@K@m_%EV(  #a J8  9  !{5u j!"""{"""!   x  H? X M +d - 'b+|Tf)c   Z 0 _O Zmg= ;` l   ;  OB m / 2e1* 7=J.N2\JATI+{ZCLe  )   Sqc!N#$%nG%n%&w%$0$"!BMT%Y. v  |   _0 E *Hd]  m  )Z 0   4&d:f;llq3C7*W[PiRM:l1KczGB-A/05'  ujLJP!KZZE/W,;J>f1=D.d^.b:DSN:$RE k%gL 6!YarCcmL +{ I-  F 3| D F A i  2 @ E , @ h_ {   F k y   Yg iS 2: ,  j  a  )  h  Zv G qDhEo4arUGt~X g,o0hFb %rY;qz\~dK+AR}h [^Pt%[cm.1((kk1PoNJ5N+=u/j#Ap8Z8VD_k-`i#]Lk^aBR[YS,GP%U"<3R$AbIS-L7pg)ph@J+W=$YURAvUv!;Pqik1 R8&QW= M,$3w!_jxR<(~Y #[tR2ygvXUI? w8@sU}lit5"fU#5|vwy;: 0 J *9HupyDfa%Z@4r ~&Sb^ezeqMM-,`Iz=(LaQ7;'?!BbLZ;W? #7 [RriufXR-9ha\YeBeP:g~+AN=>Q|w]0 fA` {Y[u-/FPk`#a"[Q?\%K u%IT9h<{ivi S BgP}xI}i g;~ntHE>j+6wU`0_aiwK5__"G TT2Cb+\h:,qnW7ug?j Azb7f6):}8w}Gi@9[Tiw%(y1(~/oN=tWR-cw'hgXX-Sqg u~{g$'F ? ${ +KP"2z -`9q,H5=h_k2.!iYB}?wQ+Ur~%u`^kH: h tmt +-/t 2^WM[tXq iwR~C~:-7'+0f#WZ9gJu =\VH7O V[+ roIo/EAYtcM:cDA#6wpI7aRth=/ V/>zUC%$=D9%z{mX55MTiT_Z@J[r= 7VrgvJ<I<8+kheb1 * [;iK*4?49 '`"K 7UOZu:C:-:7dFzISJ=R R3Dj~'E7EnBor3f WY4-[uvuZX92+9 yI<2^ 1!a"Z==yv**(v<o[Q<*M1Plnzv~8.XF8(+[W`FqVg#{xxF\D,3-S:-YHFgx?, % A*4'1zx|Y+ngKq|`R|#HQ#@unu3RHv,)oyq !B{^-SWbIZB4Fj VZh SAo #y `i#n"6!E2&7 --Vm6NQC7|Uq&-O"=w_A/(nV`6Jwm w C!VE(RJdHY", cOKxOykgYnnL="Be<Su 4%X@D @WKE=2@35J\9/2QYM<QH:3wtUe%%,R$C MbbQCf$I%"$yyQZ2!o(F#7?rHo 8JyBR4\*:?gLnyF ;;4HjFPgfujY=Zf- uf~2;F+knS.a ["r"T <X v9Zz+X;M$! M<iyThoMii[_r;v\_T;9M2S S9h 9IPMCXr5((3H`C zh4#hvanWD% ~Qu62-|62+wbwGz)A_&Y-6JU2H9b0wfdw7q>m@Y#+Ci-fFTDT/%T,c\ 9"oXbWFv ]#  = u TD M   J: )   T Y +~ c ST z !  3o7KSx:mq#(n2OuG8qUQcD2 r?\q >%>% -(vKO<HFc954?}i[(e?EX|On6s + H; z { V   C* z q k<   x 7  x ,   f_     / q  ,X 13 P CG   '  e s OB / &4 {NL> z * j U 7  d kx~m_NWNV2(~bGv";@_@ %'<E&eefx(1,Nw U~gK @vl#aVzb.&/ =Q"d jGFJl/nzi #u$ BO x,  1"#%&'(17(Ws(''S(2'a;&%tJ$_#v! UHRI   d 6   * 6q r ' Oy '  R BX]g" >jpzA;`2Z%YRIrzBr2uK%>rc`86mq(6$D Qp'i!7)8f?8~1"_jSH2d+Cb(V?sdgGD;!{w /:H|NwJLNl;n m)Gm-9 %4Ohf> n5?E B  p/,>*j8!c<)"6_y0{+|Q`7G 7?s@H5V]m`t 7zqR~yB-#{FeM[K /*q^$o~*%qZWOLLR? = l = [ W ,(  W ~ : 1 3 dD N; B    3   Y x  Q  i 7  o 2 Z[S*~b  7    d  ?u"^A; LT)G_3C,0ii(C4o "kpGz=k+T;$$'.IG.nJx!;8Or{KB:S++TeK8*cKRj=T]X J\9bB0;B4 fYfG ,#|'Psbk56CdEoTVl^7*MP|)<(/A!W_>Ay2 p] 9nRcPuK ! 1n{Pjm Q = K)'NeK_$3SH'Hgj$CNub[9a~r5 Xva@YaFTQKe"g+'6- k 5^eyuGv^. 1w DQ('7o3N#wChympXNactQ) ?_))~n\8tLy({#{bigeK!<BPiZ}[Da~)czdPw2NDvwiPS5"NgfoerFNVSHn7y+9rYW=A<GwGy4Z f7)jUxH*^K.M?%= Z;P6$ av- .LL3E}5&u:?M|crl|{+e>DT5{]VT?1!f.@!/CQ&#u \=Bu?|*7a,[JS*F),j1nIiWlrQC8^V $ iA%&gCWy#Qqo`qxa$I`h^xn8ox{g R" ~iW4(MKZ681?b[M+ 1 s<;(6E (4 ;T- ,]%)j j>1&  C'{"@[Xq~bR$D6;pmER;Y,[lSs/;X p8+*bxv[FS;2 !;9$8VYqhKKC=")J.KT>b6?p1kfygny bZqg^vi;1h*WB** %<<N}&Xi"(~~\'Sbh-\3riLcvzcZOr;8' Vn _ 7Y#= (!T{Dw(NNdFQ4(@s~NVSTleZl7N_n  musw#1F`u7V^S11:nu}S1r=WcrX!5!o33MPwfQB*+aUi{G\QkIG2@=ae HUXI~!o<.[b+Xzg.l*(arrx*Lr'F$(Hog0%%11H]zfOUqm` D,bg'#n-y@8 (Iyv<zrX<9:% /qgtKp k>_t{NU>wkIaq'-S&mNiT6' sAHYRwSTly!BcJq 9[g$$V4v* nx-*;?IWB? U H# gh4qOK~~jL8{IjcZoSv`DLS @8 h B9Z(4 S#(!Q`yVu`;8[; 7I? f,4!4x i`ngV Y"| OG?=z*F%7;Z;wu)O`*`'(?YLrZR3V ZkALSf{nD 1hH^?Au0cj{:\3oCFLV$WFC H2kV$ ~a 4W[`n2@S1 OJ TGM=kiP<1Qlz{c!2y9;B1aT.a-B4[!1b8^ `zr}Iv:xx7A- w_cnN!#tu#=gN*f3wIY=GAv 9&AV;L-;E-'F4rC)    u iL  M   rE b   ee 4 U .<_;w=U$9y(7lgfHH ^b%y*aOo:XP@L|4ny_'WP+ @DS>}w PVAtZZIsO/R[ nK*iD*Tw; 2 a e DP2 T % ! 3U  B   ox W ?  `  J  JPL4u'[  O C6 4W;1RtA$\ bq= "   ;?bG m,kgha+NAy mf~JBNIeCl>z'>=/"${=8Uj:MLAHeK< T V  H; S! !z`"K"" "f":j""h?"7"0!a ASg; Y     n CDAi H  c i  ,!{T.CvzC*N&YK[[Gy;l;s8~w)gAbQY/uab1{w j&$(H(@lYj~H;R3 3HBLS1TUK[TGn j * 9"qLf x  !U > ~ 8K  e V o v  ;   \  PP 7v  Y  jw 0 @  1 e -G@NaWU] [    a w 6 3 Z  p  K\ 5hpEHJhS o$1eapyH,3r"XwI@},J1ekqei:+DDQu-f1 sGFmDWA4BqnM,Thw@H 4Zg&o1k2 k q 1N2K  Y ]L    ja   j? 7  .> ;  " r    c |  py&DQs  - y   . }1!p~*w-c4 i)UfSc-8n6SPy#?&n>#dU~-{m? "b[MXC)QW zK>f6GJ-LB=p3"bLp*2B49=R+|}-J6   lG4 b P I<$ed-Fu\S%1 # H uS  l      eA dT   7 j I    1 1    E 6 C aY &:7Heu!WgH:Crj\K<f!<BQ1(a$@5xX q 8>  = & N ]A   v U K    mg w sN V Joy\``_QO8kmGiimc+*Y=0 !L=:{m\^,yAWttJD_cca`s[@ME`{AwrB{dxBh:C8(5Mi3J&G~RPT#o*NB4( ! p z S8 r   F 6 = Z> fm t    @ a B =d %   ~  T G  $  Xw{Tt8Vrmi8[.]"Y@eJ=TC6xe(t({q!@~rWyo_SQG1$P5en;Lk6O^ C`a-7i= X=d P^H AA~d~~VeP{$xI (5 QKTkcEohaE6#:CJATEX"Q;~",),N:}Tw3%5<J<v--5z:/p$2, o0!+h~"y-cN YKiAei;bzb cP s+WiW!tgH @mAL-Y qP=6 0=@u {'g~|>)p# {/AUh^ +<5$h/UDM(.t m t>wm6\.=v_jw3H mxA!3n^gO|$D4Z-aTr!cP~#[[~iz+ +@Pq*&mow<uuiKEQX["ioJ u$O  ^L'^~Z@(UN*XV2.yE iUT5MJFolZ~Ep@vmle@BMGN=Sjd{cuV?;S D>-7$R:6=]9H%&sS~M+9Hk`0Pw|VX,Klk$9s[G+b .hoI9`u0o)v4~hHbn:pNX!hiNN/% A)yIF()I&i[9:2eoJt9UfOjNR_[q '3-^0@F^ _5kGpX5OrC`V5w3Bn~; %vSW *%k@{73ceJ~$s8K=~.MSze7qBW\h?-xK@27Gj/2tv!P({e#-2~:[!_)PR8MUwi@mW6x\:t>pg4B mgt#)S-` JaFa;k<bPrWA9btJEQQW~TIb2CM<vsbj}z `wQX%II B9SllW[jJ9 @[)PI%nK wN\vc51VV(8ly}lNb2 MlJN+;@}h<oqGV8fY2j[q7JD ?"ZHv^'A)(cWWWnZ;5si{_yDP6 "\JY&/{j slh~QW{$\MTq\uVW1-KM:CFc|9y>#7(t-0)Rp% 4))BF`kW#0BA'=OBY1B^nS'*#\0?jHZh 0ah;D=L70! F% , ,' cSxP~'K#g% H{ O~v0BA-Rv#L-,-:WWj0gy$L1gWX'x?z4  e ;@DM~Bl2{=br_byocoC  )$&, Q\p,o.b2X,TXaD2PDDf[urzov Tvxey}bb};W*Cz$+% 35(BB8XBCc5l\vsyyhK"pKl\z\h1@Z$/v$J$w-$  iGTZT9 5Z[~9!S8PX.p_II=fZ@< 9"  ( @QzC9r'SCvIxB?IJVai2X*Z<o<0-@`Z?gS,j"?I?S{*B1#8jI8F F)F"%***' :4K#PrxkB #:0y! A'iyPxoI4UoKcovxnS~7IK8| ?pnttx!!}eFtHpq:^5{Hdy *  P  Fw4B<<FR5   E ]XcT!Ix'9{7 oW[EW1 +1(jMMh)IUrW^nyd!:?]Za*l.VVy^G!H/ =G<';Iy$gNn-\n`Jq]F  Z=    7 ZN  `    6  4 = R~  MrcdE~Z7rdS,WR}k5; ? d &v >   %<3  Q b(*Qo/(<:<)5N0D$NED7[}z|RZa3V'[HL=dJd r A*  # ( !#-I#$#q#S/"!!2 bucp kB q b   kEb. <   iy  / TL"N|;[%196}I 8zEW[8}?UXBb L1dHfDOf (Nv2menxnC' j4Q&hZV8qi'E I *LB! M  sI  z N5 / z  Q"x$ Wl   :E  $ z  A4c8fc ) +  =nBb]HN8LBEKli&@X:SZCuW$DHBIq|m_ Fjq? kQ R77ZK1+TCRn(ipYH ! #K ! g    !J{!"/"E!i l j h  c  K=Y3w}HAAx( + o n{YIY   G o ;-| `iqwQhvYW&]9P\gI)l/5|b Xgdv1PL8=U9GOxjm,L,fr>.0[.|X;I7~\i) c\ `:Ui>d]E $ZI %  q "$1%&q'()\%))))'9&]W$.v"q 1  ` 8i  ,B ? -  _  5 6| U  b /  t  j ?[0{+5=y]j& `B1y 7Ct{+WW\@1CFbK|e7?"5`xQBHip iKiTT=2LN{R?) Zo>?P<`-coxN#V ,u    Z  J ? M   9 U G y   A q !      <, 9  K   "W  6  [dCgWN{;{gqQ\wkgc?tz|Kp"$z: 62/2>Aq$\@Z9CCf9NG CK~ [p^&r7;VbeQ>b2|Xpx\bsi}ufG s\D4kf/-u-+s^80#WX-e2G;,BT]==_"iP qgtJWt*e \^.+*M !uYk{rK5^FyTn7= %#VMJiL@0mY)yA2 ,V'iNu*~YffI% H F,*kYY~z_[23n{KT wst{\deN9pU8[l}^^ $hv[Q~8)=9K"FoX)M 2l=y<\C{Lhx Y>VuT ]Yar^rY{JSpyO JF !Z.*T9Y{&>H_ncwND\tp0#=#:R6_myE]|3*te<A M6Z&3 a,QHB,%kI80p?ommIsy>$vWzrb8L;b$Gggog6C}W&-WPG&+L.dg!4" F'8}!bEzKI%\)^@7ZSvv;alo=I923]z>qEq\7 #2jlf,mt7lQx`ZM><:p 3>:<\YTgZ,ykyonX2ncI3xQEU2OE=b#[=t3@&Un6 pl Dlc~mti^_`">  SvBg#L4'JZ1^g" =B1QI[<i_J~v=-_B{DDzXHYg<@nRxQrbp+aQan 4H 87?g4Hd++d::I2,U=ileTW?Wh1aX[}Qf>97=wn )*xL,#V4:2;1PZgvHuFuBb4kr(G T iI<kQ~GM% %MEP 8Db,9kzZ5+MPW_PC.< kaRH;'Z _q*bE2Qdp3 !+-h%!FN&?U5@ >':XmUxG#cpDncWUvmQ^Lxx~3qPT~PPT$^QqC,-{+)DD_QTKb9\H$qt{*}D's]9- X9XJypMP* K3%H~;\cL:Z0h-8*kn;)*e#W#Q.Gt'8_U48~V8%Zh>xKfVr6=:VVfyjaqY 1+ $OVqbk4k?9ZS+y< ll=a>PU,D@poR1e_`Zl9o<U*3:939SScF.hF!BIeb7aW@y8<<Z'@?FLh)IWoRauOWL*8|NRCjpV:xxUpRt:(tgph4u/+3=:c]nj3GRG*p7pKVnYP^u0nDaW ^4VrioviPgW( ,'O r1P<Blx'  gkxx*zIZ`X+ 8$kf\8~=`j0D{-qF% P#{L ~I:PL;'^bkW*b!QC@zkhP`@HCZzv`9#{S?;b r'*xPOv+xe!}x1e0QIBu74`uXki@ 4O QH;'ZL2C@HiZFu9`9W9FRV$Y8`# n#vui;r#37u*xk;rI`W FZ0VPY*o!o0,\YaSFRg~^qO;Sh?A4j,07r*D{kB:1%~ kxcaoHSgrkkkHR?*Oa -*4(+'[bh xH8CkVXWxkSJ9$bSQgJXSHy[Lqh2!=8Mwi;"C D *D81 C P\C +%o[oSH@`C`(7Rn0SuW^H@O@f_G{bR(!:M5]iFx~u>@k d m( Gv`  7vZr V   n;B0LS{U[_gr7m(u93h@A61MJMWO?Q*#FznNnBa :Ydg"g+Mn o&"&Fe&5\]^^Cv B 0M m  [    ~  l   C  d,K9W C [>t    I  w N  0 } KZa BG  oWh]+0 rCPaP;eTNNoO_,zLI>PQ&)sGAXgQ=)`2H5'0,MjtlaYNq!->.S@3Va`0[|u)ai\FK 0[rQba;   g_A   A 8}+!+Q!"P"M!n!j!9 pw J_Tqp 2  N g y c~  mm `! '  F"{Yl6ti=J7G gC2t',kipfli\|% r1}i$XkSHIx}|ap]ZDgrKZRKI FG C< v=i&sxk+F)@2 j1 %Z" &b   " G El c O ^ H  J 8 @e<rA 3 76  o D   v  @ Nf   W    ( \ i  W  @|Q^0YfykFR//lI;`0/FZM'`0% Oi.3 =@DXlDg-)"niO]Ntxz|IAq=J_O3 lkd 3    )F3gw99yDO6=1[:KN{Q=, DK#.k'|Vf9 k}G#ߞrެ?gݻO6 1 7r   p ` U{(cu`ik4p   2 $A Tp708Ts{sNsNL.Q S B.R4Y/]aEY#Ek`\1PNjx3u/Z@(+j)?q:hQ]jZZG`Kv'i@$zf]- 5  ]   fE  `  [ g   1GN @GiM.1%$*% x QT WS $ B   2  [\ h ;E-ST3xYFRkYjW\*#; ~}0q@\HA) uF;P'3?vz[LC[C&e6L_N # }\$q u.j2o` ?7&.exPx/J~bob[ilzEF hu4.=ec}y"6GOz r\ Aq#(.za`}+@ii`5g]z2XZe#;p{kIS|_ de}fy )\Afq>gcsD;BM;vyYKR* B-TE&xfXO3,c="NUc`'l|sSb*"{&?(@OI7w)xYQW 'oyesJu6<4bo .S@6WL!E11vJL/< ^VpAp=m 2)yR~ GpO~hA):C%'i'i>H#q9UMQX`\$P@+9a\h7ZPCb+9VLL0z]-2R>db6[=jHj#&mKQ&R63mpU]Eg_3[V7i"bCDdSdZtp^X|ovxD^;X-9*;SJ%@HL<\J3f{UQHm9:,TCr![8CZ9hPoe+riSarpPZwsj{IR"Rp-2#}yH@-ec_aTAK7~-BROZ(#]VRvF;`n"5*21Z+r8WWXwMTJaWlcolzKl=Qr5\ hzFG= K,xR;3?2pV\uZxE9OUfnH-/p %@=mM9P .QFA "M!9N).}9&Q(@#]1=4H`D0f^*=cvVcCLo}(<O(L\^JsCgyJioz+[I;$`;\[ znpQkfG<rJVyZVh:?' zS +)upqVB updVVgiH6A-~))gNt p)t0>72df">~4H\ ?v9Q12LHrxxb,i"f~wh + lYmVwdR{ukuZu~yh|aISI}pTb+:BhJ;35+5"vz2[B[50,B u;PByB: q]#3&"( Ybup +'$VF ()^$RgPL1%a%FjDL~hcryqh{n'h0SkK =q 8  9jNE`EBcVEvf#)7O:A=%t 0" d>_|Y&22m>Ut!7q+E@XXX7U?[G]:K"GduQz~P?xP`?g`]#)N/!S_hj`0`]SNr:qgd>`jqkLyW,P cL?\A 30'"qW4?a2S7K?n}iPqq9h}rvz*}8yO[ov[xqJxe %21I$ \cB28VP8}"PSb(ZkWeBWOu@Z1Q4'1F;4#<n@eFa2XI;#z@aahLhB8$'}?JB *pZJ_h G$;;KwTI[io=P,i~isJyzwMlZ~zafP;z5W[W=+\p8fQPWy#0W[![2C4Wi0Ce8I?QF4Q ck#Zu[uY,\SfBIxuIF-HOhI k(o D 4LFj~Yu(Ayk)hr$B``7C VF nII  ;Z+OCi`govg$gICJHO2;7 BihW`z;yka`o`^'x2vV(uA:I^1PWrOB*g,P1 R;%70":xjuR[d_GX||!`Ympjf:UEV[>wHx@/RC)OC G!OA]N]@u~9nu[uQ"|&GR_X@aW|/ #CnMf_bc-W '3tjct 8 Q B  P     C  LZ ( G  hbJ%r",/tKP2C*zX~]f6 kP^ ;Sjz;%fi9f}E TVf-PV4 #wxSpUj O}%1B_)GX ;*=M9B\;.Vhh <n e  C V :  z5 <   e O ~   `9    | - * \ 3  t ^  ' * 9p c.};S { n y   |W >D W4zxl( | b= 8 s&4N{ =[!gC$o|`%# Y yP Q !! m !2!qE!!\  2{K.  R :   :~ i 9Vd-j  R G l  #9C0}kr-8,KR?uPX(}a cdC :ib@EXR;,+E%Z9Xj{ !4s"0s{vY1`=![/>Lk  a^ ,  = G V  '     o R X k L )   Ha<d + @ + _  ^ R  J <3  R x  XJj9Fqic[rcnXP#XBf.TF5wd1'6aOb1TmO~;\ k1goyrF!R /=j@=1$(18-+9oDi1`T%]SK# -<2TaF %)N  oH&}gU>=& _$  Pd)3 ; L8Oi4K][NL'O  O  <ctuFvE'K-5(L-7Bx6_*)8<dl>aLo`uQY9{yks_B 72(yByZN{:L)*x_#C5MLO,{1? .c   @ ?i  ' Al/T0I">`$g^z0QOYe]IVT/sp  y  F , t f P  M mi2?v:kMCq;?f 8,'h'?htH'A;`bs5@7~}e#}!i a'hiKFNX{Tyw`XbS4z"R'J2Z`t!y+&dglrse8^!IEa "~wJ-h.& %p-cc lyv@afZy`]'f cMY7?gituAN!T.ZZ"s/_Z!5gr||| OGiX'2+}_/P^mvDWY=q_u*xu{hHFg04eFOybnWP9Dz:g O7?fJ*@vhZXD x=;"[E7<9u_Y|=i}]QBg9D$0,`PqDXJw~{}bpc(mHVR[EmL4*^?*=[=Pkh^Z8m!EFa0Q W'{_aZO3 &NDD "=v@@O8&{]nC"1+B;^z9FMau~)F>wL@ax~riOeP-*k-#'-iK4?F5j8'm)3mE}XWY 9 A-|] yoSH,<p`Ga1Zy?WLQt=qN0(stQ_aWg_/a?_C/&)82c "  .bGz,P%i5{WwsPffW}""3fxf)VOOobz<g !;IJ2Pvf~hTCH"g9Ri,=M`gKMC m)-e9qCou8b9PInWa0Sb0s,fZ0qaoc -q|pV9~! }i ^Uvw=(S6'`qn- `W Ay 0 1FiZSg`y@i" ,[s{r9S_f"D  HgD3}2>Y[>WU+Ji"ran "";%ZR##{tIAS|:j dY _t:N yTey==(AX}> HA}&mN2 -n|i40n7*#ADF8jk^1OF@;OQ0k@r F!g+iT^3gv='[7~H\cQ(k7XF?ZD7wCr![spoa;!-2 [Gn4uu^WV  %WF :4?%)zNU_/db "/HCq"HEd>ONRp #B3+KBh0W%;#~3rykF  8OOQnVbz$2q3I%yBp*r Q5c83mSU;pixbzS9x;z=B{5"J;MZB;!<S![$h*r?%ww2wK"#~o@p"+pE)&Y: (3;"/o:]!FXS[K}"iFgF-CCwiJSIW$<%-I"JzQwB`@\zlg1-.$Q C>NQQCXi +2c%qS<Ib[BTQi{VhCoX'jH#"xW3{Bvg#O 4% qbtxtjbumCY&KRJ#G C7=6YE["s-cAt2Y,"5-fw`}xfp=`gxQb ]u3dw)8rq7F Ox 3 C[D#B~O7LLZ Wu#J}ygkF?Y@0%O #7H 2A:yjS`Rc? j*r0jQg}zh;q;[qSu@Fk*-u8j8gxo gnacqnSL\*{SRkD0jarf`a,oh 9 S[azOFv^nqgegx1P*"+\D$Q! 3 "K%\BQ5Q JC *K3.K~*;Sugqxx're$x!q? +H#!(raVna b;0X7Veu2[SII7FhJ n#@(07+L`07$2ag$( 0@$ WX!IoubOy49@@?IZxFF#7QB< -x<-~-`-h=`h`-j?ILY`"YZ ?^ D $=7\*;-K: V=OBK 8S7a1R8{xR!R[y9V;9W9XH9@!B*qAFRr7g)rP3Z\ {fnPHK3==La:3L(c#))-h8K!f0 K%4' V' F *x,nPo1XRbrW8PP8*^Lyv-h#ia9x arVJnnLLV'hH[BexB}8Z1I7*B7gr?*+0 SzqV*$qHkv2+2Ach3^ryYxKk{^BkuvOPOWO`D\D"?%Znc8HKh:V1kD%v-I3qKATP|>1 l4d:P 7   xv {< \  [  TdYX *Z0U5%k_pk? 7--O\gaSu1L|eT4zdo# cq tq"m+zj2 A:3QxJ\ijS\/A#xa`l8}R&t!F_@G |n0 #  2   n  . x  u P 0   1  dx  9 f  Tp ag=T|Pb  WA en b +D J   7 [   #Lfx!2z>$8nAVQ Qi1:#`{iCZX/?; )-V]T7gkE0Oy_9sdiLarbM6SQ8)PG1zoMsETNI  '3 p    % _ !7!@!  '[7f g2  U    /a. '   % [ $GovRWa@FhW@0f<%wc#K B  . 8    kf #Q|V h e ~M 9   b   u H  ti  L [ B    0 5 Wd@9.b19X~(5HAsn `r-!#M@DO3=iP@!#a>B#'AT P #ux a[dbTxi[kW Jg H   t  ,!i"-"8"!! g9^}Gk o !  7  & 2   TNr=  g.M7 $/i(S    s 7%ycg0Mj"Hv^Q, *w8{.:LkDP|<r$8/L;=:2<}OS>>s~/f=H 1y:Oa5H esCL#/p Mzxv1Hs}Nn=f)"J|YX6G%. 4 ^T lC ^ 5 P ` >  $   Z t\H "N5;B **(IbR~[vozve{nDr>iq/?B4I*.?v44Q|h]f`1&&tHc}5A4\)5'F*-4{'Tz_ %.{K1?>3Y3m V^z*FLSS'o +HE`9\*~xlE\AY`{R`}lMMmK<H%<{G!4$C^b@8=KhT )e_dglcM&?MSG|m-4]!y'fu|4hh?j* ,Y-7T\%54,,raxf]Q>,*q{6=m3~1L[*z*ml#ZT ?I@wC)UW2_uber}\oYuY<E-'`B V;/zN!UK i"}QE"fDYI6'V-jrvaLiIf"r,ZD X9 525Q3r73WKpjyagv{z+9l252C<ZwH\JwUc}xK<>j[2 ls6fIiB%ph+L"n,+DT[Z_c(+&)r>g) esokwI=6'qj6&VmACyAO&J-k!  &3#H6q3Y(EG)KWL  O?"xy^x 1Qkhp SP{S8evbl[iz%@k%~If1,T! ;<!k*S%;+ 8[T;uyxz[rn!-!  C hF9KLvv*7Y0L? 8~im*`AG) 3 =A#)7# y=nv'Z0iASk(iZ%X[ir!cz,  ]]2K+% <=,,=M51[D fQpPP.[hkzbe7o# kk`@{4qg=0:*xHkEv-6.}A%,q\ Se@@tJqy[[A /"{EYd fuo%if >p7Vd-_fu 4u0 Hg$4WY;7YkBW~2Z !5%++9P'IJ[Z182iMJXPaITqyP8InZW0H v CxFhhxHLF#Pxuzr`e Y,;S+swFrOfR~$ E[JVZ}Jvp2J$PhaOXWqneXkhz`BS<biBeWX4998xI0ZCa#'4Ahf`#B-n : 1k1q:1rXOfW8~?4D?;%YW9?((JZP[8Jyn[hv}^aCe17LSWBh@z rC$<z; I[-`neg`H8Q( n i1-!Iu;ugW'y!1}!`7Z[hLa9aZWe`}^}7gB}ZP!y$W`z!z(gg4[ W@WX<;070 Vyr-<y<#x!#S(V10}*i-b^v <$ qzPQF!XP4nqxhxx $(9*$42+^vub7XgnqiWOie?Fv8a1FZa?y<J`ak2Hv :D73r:kn*0[8fu84ZN%2X*xct| pX3u'=AhIyfKun~^  {"-o?F=78"'oZcbn9K@Z }VOQ eySY}i- Z'h?(#7u YY1o4W*,-)3VIW-#jJ[  DY3y3KF1q)hA*fc 1P972hh*a90<Zg`X^iX!.I=(BKS31(z vxCP#J1\D!c 'B1y`PZqa{Og=Y7a8V\a~(I!W1 '$S0?2<QP0hgy'LSK"(("2[ZP$ y}h .; r%XOo+OVaKC-c\'WZC/H4cg = p  ?Y bPVqm X  ox A C p]  kW1x9S"CaU.^]QbgD?KR>CK Q_e ,L =h za  7  i dFy\%W    )} ZI , N Uq  Ma#z:  Z ' J  X   i  N    f cN  N u [ / - G~  )" ' { !>DelpbTuE%c DUcuOj~YU<}sE)%"z-EdwmPnRj0/8 &[ *v H$ l-\+ n6R/ br 8 ##%&'!(k(+v'a&d$" (   . (a   ~ Q 4d5Wf^   l XM ~  I]/y2IY_bPBPY rRm/aTHy',X 0XH=L@~n>\Q]@EY/(ySo )bQ5K5Kwu?? i\@vxYEHZ:RZ*aR ] E 3J R rjT9} ; u P"y@_rWn1`nP [~k)X_^c75Zi((I_5Zt-NVx_$SN>L\Nxdjt86DVYfU' 1qndIN9U  ' e 0  \e\cjD$V17[eZe I j .G )    S (3gN` s A q L 0  U u< wbxCKVMLh#ZDCmnN)"Y'q |I /Bq`6L-m`k{aj&M$]d$1Mv1=t#[A1%:W/X2NCt]%=O6CAKe`j\%D@3n%~cXUj%3'`XcVDl\=I,vXZ%y$9ra^oxk? (IC% N>]iz>\6sNt2}2\itbbtY>"iq[%hE; o-h"z@b)yHPi7  ~@'@F PUw~vJimrYVV;uvu%cL~-;1ZKcDLIMZ27*fZQ V=I ry=)R-Hp<1>g4v4Gkd^L[  .Ii/`EN~Q  ?x"FS{~'z9*JB Yy%-^]@\^? c:*YYZE& f[pp`Qu;p*j,#A6&Ec"b%%u9Js!?&@;; /MM $.CGe=[|RIl(."6W(fCfu"v*p *]aJv ,}CU}@b'KDg D]g )40|m-kRB 6t:v]o.uJ 4;etfKVscQ, _hKHFS Zn^r `W{L%+qQ'0(l s'OQ-I]mUi/TtUJG= qmX3ozQzpb7|fxUUuxroy x*h2bv uw+bQz"[ix$4M:,j3:6I>&fUs4' *YSak} !g"xgl8$.J va{;yI*CH8B #+@Wr<~ D +zO+P(0gra-"BQvUqEG#`H$q;`unP!Zx 1'<LxxPnSvqP0'!o- H884h@2O kXyy1nSkSgPxVV3JZ?eZ;2;v$u{1y*P Bxu2QvvVWyZ9b!,cC;5$,15}<SW8B9OCOO++B-k4oFgr4S?@ P!X onjSOY3Iu ):N0VRjQauvAyx{#^6qRq$1e;8H:7W7"='VH=~~3OHjH :n/~Eqinj>umUVgG~n`p6]qz 71LyL 9 o ;eq00r?I^q`;PkfWaO=vYy`FxYbZFP y~WVH_un)qAq)*"I 8uIYq^PA)nI y;1KPk\?P:aD7nh r! [! W%1<8r2{srC"<Tb9lJZjb[:qgi[t]Y:&lN%cRxE"b-wY{NUU,w{={AT)l[MCp*ifD9`kZ24O uDWK7,)80O0BiN 0d bR!@97s02 G)@@`=RUY:COORGb)`U0>[txpi]%VL;"?D8f~IOCL?oabiZ`'F#-279nqLnxxXuzgOQLx9* ouxOfW"gxY-  g~F {*H4v`)rKhgP0%n=L  *PFRj~0 RK 8`gccxn=7y71kO~V0~nK {+v7r~k ^SYryFfrkYLgnu8^AkoZc:WcDASH?@qHZ2H?H;kxeH?`{X{B<1X [J@JhC(g?xkvbnVk# u<IXok9nPy?uqgv 2 +M,D2!@hwyhZ@ 2,=CG+J. 89*y[$}1W(-a(`2HJk@J$'aei H4 -84 i40J''(!H9-7 HFV870Z7LW4#XHP%+2 % +*18(K ;+"X[.J3S!, p9=8*!Wa a[9y =3G28.}yhBQe<vB`eIkIVh2egeXL?ak*@ <;`'AmrmH`YfpA')%N+"]J3mzu=0%[[-|do/TN2XQHqsl6N0`:s^&  WB}d  ^  M F4k  JY yL;Lxv2-vJ=(u_[|=UeM@ 1r6znmLHS1DfaW* swi!2FT.q[]r22F> l<3 M$   O f  v pb { G R 6  {x 7+ g   bkBb m ~  X Ow\r;{ E b EiP[- fv  #*_lc -0s4[w%z8qD8\"GwFNE ^,%7f_" ?aNrS-L&@JF4UWU]v*<12?y {>uty`2eF:vY!IZ9SvsJ@ILW,CqBV2*CH9%. ' ;#0L %  n} !"d#S$$%9 $$ #c" 9i # } B sA  @ n   Iv 6  v ; o.~[@[=I3{2?9 3O,o'6 .\6Uy}UK/5 Q!70t7u{cE5yOI7&HvBa4 Dq O0La69z g6/ - x3|xJ   ( 8 Py k 9      H  L 3 % r65k +# p  h ' #W@FEsy&f g.@5M-s]Q|5&H{ fC=P'J5Wyk(Z=7O P:-qf[M~A+\V`Ikwdk*:_  K+hne(<, 4>   C [}  <    W\  b  5(C5gqbP7    #s T    6 hj !19X%\ x x U T1o48& Jx-x/r)Z ^YJ'QP_:)e pv7-u=f(]Oc=J|T\>Ui{moQ8.k5Ix`_i_C y G<$4x$ y @,  k"k$&'(W(~(d'&$\" $ h, |[ n  F  vm u.w!9|i av M +  c ,  Yc[C Q1J|[r%xB:mmvDfX]@05B4: }.$p]T4 FD9Y b !=   >n   L 9 ~  +^m J   :)m3{o e%ujOC'ef?e) ;JhgK1Y xK ]%J,lo UX;rr1C"hFSzAi7b=)E5]r`?<\1; T  F  =gslb BUiLd83  , D [* h >  F"   O i s V TH# Q w xp  Z\cKJ=A/+%$3zaG!y, KtQ2 {`p ] @#&wY@`OA 2R.y7?)&4d~rwl;cO@8."1"/1j/]{\asW

    v?+1  n 9,N02EH xJ%9qK!\Zv$:# Oi7?ADtFC0 C/}fa}_osK\mFowsvlWA^t_{ G>l>_AaAv{ 8B% N2*42aZ 'F<2 LS?C VJ('oQ?8q y*F0Q+kqey+ <..1~k{ z@XC1<PKhwb[,[.+_o;fPk{_r\wvaTP;boJ1{" Gk kih<[OS;yH<"! ex~+8vCyrRPDL'? " )=BV{LQzyi# B!b;Xanah% J+r2bx{gH9[$~5+3bK<3PLyy}L[JC BI2yjx\f;y?SKW'D: ""#:' L)B#K PDW#oy%0=OtnY=9XLRruWgfQ^@\:n-xYRP40H.8}0MB* xH6A*,qyq%*4,HhS{rW\=1?' SWB  ~7`n`@q~ w!7 C`Y7GOO>=iz#)m08v1{4`7CF 8IJoz9# !XB %M\"*PW+B*.IB[PJWlM= <D*%.* }iQ<0!5+rabgghr`nfIOOH?@`O0=1 W7{*V*g)x3*KK1V*"LAa A'V:7o~?y%yB`BSgSg'JqBgO?J[f@Z^\}qL xqh Ja['HrJ- *! 0'V 31A-4n 7W'?0Q[P-%F;FIZ74) 7'"  PLS-FfW h`q!YFPg\344 7 0,R%q) qF)q)nP\v`;#^F#?oOPnBjCz$ !ZhiXk@0++ # B!ao"no W;OLi $}, @  u$@ hehLXP$!z-P7h0X+LL<Pi;4W< {vgW?DPA7PnvYVkKH"WWAOHkOr 0 C X4n2*CgZePov ([2~ My@r"Doh9o<P{[TG~JG8Mr.W2;J SMDk$$=98uuurnnWar^oW`(gO``uI408L#yvAWnugfO\g^`xco?@biy 2(-WW<@qP4(k,uy<Gr!PrTGZW{{B5@.\WbPwDP,$M,+oq`WuS?BZHq*V Z2? {~S^BB-4K8IY7yO*H"-BWR  %' Z HA"PO84,B7KfWR"O'HOD`%fV;4AyPYFFSv"ZDo\`Wcu\n^';OK3F-S~ ^=v nyvy`qiWBkoxrv~%:FZA~ c=%x-L~PrPVxk +* 4i7;b<?*Qyhrv!!07FuOV`WCebLrO` Om9][fZ#$>:,z|7g~+D4L  ~ g 00 9 3 ( 9  | 2J VCHV[z-EzZ*nAV80uSM+T69Wvw?+dc.;E#68/N<xWl:V[QS0D]/k?k M mH) M  N  ' )T T UO     [  ]] p  z  vX ( < " }ofS V A  C   rDQr > P]AX[LYmb*  9b!B{nR6jgg9x}OY3!/ EV D7 K> uS_c^ K4Bm#8:n*%qf"bw5hwA  >   ') > 7  3!(! !=!9!J    L B   jq V xqY [ E &'  JM y7<{8+SSwpJuq @f :)Ew~BPPOtFT+ej$BcfxU|n@@jCRfK`@R 0a&K`{b   F=w[{gQp7=]MfeY yH( wyO]cBmaPioU~kt}>B#ec$y2? P8@ O ;5[k1J .  n_iu 8mIqrE>`):AXAi?5y%~  4 7  _d E D  )  2bv21P/}kYp=F+~pDc:v<{IP'p*8'9F/k7 qMqYY D BRqjun?oM-0 9~Laq eKkvm7ZiNpe-ME2ARg %.#<0ITE'(2DY%U2/9'Ws JwlM=kskk1s_@(*H$*B~1@,e1XC+a=Lu4uoNf d~AiNqHmNj]mA`Mp{s[X]wQH[ql2">YDQAE/A=)%/k/+p5R3%39 bWe-4BL%#y'8v==x?^Y8I3L# ;ou?7nVOOg>LmL:a)L2H#`&c2R`7/6:670-@OYN%H+Z=3$zQioi, Mi,mtCRqA{%-Jc\}R Y3'*,#k_!A$HXw TPzZen grYfDvrW84YzwR|+[pOV&XH3@97-fb~c ":W=`X9xw9+Q<IhIgayvivo 7B Lro y12gZ!" 83(DY^K1xx#9k<(gQw]@j/V))F=GG5v.?]K& 5%a==8(,!WWUl/F<[} e[hy"(Ch9GVpn#@?,B3V W,YZR`k{r\,)% (-F7;bLk,LYu:KjoGoIopBcrrhkB  ~2F3[%ZP j1iuYR@&p~|Y z"Ui`&Q@2 @0V O)3+>G:9\:^o>qXXIP)bOu**8cOiqrS_orsT 9*DUcU~KToHTHWXHl9,p6c:JwYbD,:j=]9]J"+[=]zpXicvoCb*""="nqyQ+C;S?(kZWYLh:\hIjyr\yy!c<` L4%R4,%IY~k*(ZbQxb[412x @WF2PP@I28Po@Wu+H9 8, B*8 youHx37j-^aBLSPQb`F-#-@ ne z y~k+CJ'lIO*WzoV^<~ZoX=r\Mw!zankaP2zxXPZCS(Ig-V-#98JQS;1#y{^V{\^y8uWyugg3v^`\R u'PFZ,gf' ?%j^%=7I;j\17)L RB A-WA= 4)7uc\RPIx#kr ~ayc Vf%\Z:a*vLL*IVSZInO1q3VKf;r8'k Y8ZDIhR8VVO%^qq{'v #4`\#\,o-?3fx=`)OrDL~vxu*#28 x(x -IB49 ^ 2O'oSb}kukvvkPu^oxPeW#'4r^kkugSnirznozabxazVhCn0[(!ZO*F44?70+7( YW cu'2S4 J1?^x{0$q7~Q#<ZPIOW;XexXy2qygo#2zg--azJ-r'Lk2a Q VvW?rF'Qqy@uFn[JV+Xi u4VX?LqOO02@?9?COb'C(*9O#$(F2 $-1vxB^uOunI``nkv"jc^:\^\x"`,`W#3hS:o3gB W*#j4BP PKR^%K~LuKo$! !91@IZ2Jg^hLWCX4uIQ!<.@oF*:{sI /   #H#A5L+  ,   5D~JT1q7`1QF!Ps"l=\"YQHubM|jm\,I9fr))uH6/JB;foo8w$?spcM2o0Y]sa]dWHrc sE&    `I A ?    ,  3 P   } a   "axkiEM1`M{"c 3{JBW q #  ,9 p4yXW=v7a\/LDJe-hxQ9]MnIL4l[K7 0Eigz6] =r:U^L Gx3SI,FjA'Pn'5C!>D;8fo!=M\i# h' Nc    A t  3> [ * +r. Z  e":% '(T(W(LA'H&1J$"zP  ?    D> "  _ R v(; Nwl&KjQ{$}B*qx08{?LZXe84(i}" $f^+?R'?&5Ih k!$ =*4GJ~;)+%Ccf`;kk-t$e6Ijn{h!FZIU!!~ | VVF1 O&Br D M   ! ",V".#a$$$$$b#A"!( AkxRiG  R  +   Z 9 2*4]U Oe'A'[|8#(ww+yvx=5zhjEcm7,X}b3IJc,,D</FyNZ*~Bm-ABMx1 M_a.]{q@\o>}~ .:D" s u(i b , CW !y"x")"v"o"q]!>!b1  I =   , m  G  MS )m 8 f - qY:Cl&t?auPiG06{eg5Sd]Gar3 \x{\-AWsSRynQt}U9P=92'Z {iVUvq3 =< HJX~|9 [2 , {      W 1 9jl 0   )(      i \  0     u  bT |2rp?Hkr`@vjd*/piA@na[h2#E T.x3|(5">_na1&v^/Rly~aD+l4aN-h%{(U {f 3 [ w $  n C   8 g  k W? u * 0   L  fZeugB K ?    t  K j  Xk \   Gj  ]-1 C-xDON]p1Nh}z<*ZS9@]9n53* d#O#Yndiv3BY=_wI*Q5qwZrJ M0+Cv/4DDG-SPi=ik B2   9>  j n d < ) !V$Q Vn-b9rO7ur&T;    V g d` D :@  'YQl|Z'><k2B;TlpT+\WkrRRO WrF/i <6\\IXjTwmzSWTy6W &uf4*=LIYP<Ji Zb3CQbkiX@ U,z ~uqk Ox%kl) &$+"`,}a]C\=6+C-A2ElmB-l+ N:b"fpiKyH2+o lzsJJQ;SWZ=Q@\[,2rJ8K:Z"-JX~(Y(~wXaN2^=JV b5i.xI0 qYjYKZhRj`\kXE%;v#>Sp 4e/9;uMf m/t"7v1e }=a sh  lpwq@ON 7*V4qNHqhIq74j`D%  Ic3DS@(~IDP*Oz@G@K'9i<6Z^CMJ !6}"I4R%RA5r.3$`~;Dc.XDm6n5D.Yyc'vz[%y%7EHB;hn B"kZr j:b,6R{:a.]0Y0N$MuPw|ncoOoVh`BS{ 1(}%SkP"D2=r McSz+0)'-4."0+C22_|qzZ@O% ti`\g\>[=,K3b+A],-U\,cT5xpgcHJQ9KA+eEE,Te/r 8 @ f;V,0,90O- guKI 905G)v,N1 ev@^i;k$/G8W!LGkk| y7k %A<K4'_effx3n2:1BiG=2KWT J9Am  A z/#ZqV6RwBdmU0SB psRN,YKvi5Yqn{1Sk}hJR8{r4/CgX @i%)WMTgrbg1F1/64"C\gFVaEg]}"HuD"8YK?i\9AQIPCy@ne D!hCTRmi-# @'c4DDC{cD w;k#3+zn[tBK@Y5rnins`ZKBc%?H:;Z<WjxI j')c0% _Omq_[( #KNIY::Vvz)BF-B~bk;iho2DzkTs* panheJ1yC ZG~8n\vVVRJa'k+L30fBY:`)cSHOO8 =-387=8qI\L *Wrr:c~#YfRA-P-=B`BkW`,cxV_Cu@:Y0w!HnY-0= f6 # )7o81^j:^r`L SxFX 7P}zXQr*,BCPoqC@qC`8`D1~ #kj{fKa~g`o/"6E10-NL_VG{bufH2POuV~]zN_nj~'3Z\A #KFfSvfSkA\gYn:YFDy1W0uPa'D:{DhL7SZ\y{fDR11'FAF W A Bo"*H* 4%F1?ORH8Vv;-SrK{xjaVo%Ba'*;F#71IS'1%1#443:O1%YV31I*-;;=Hu:I[Y^i`]RD|j;DH?HY'\g"qxDa34Bo,KFg3k8VWRKnauSVRVhfuZ(0<2*bH4XV 1;HB(zfzZ;rspr_WXyvXG =PQC  "*XD;(!rKhloX9@[$u *bv ; vkh J7 ykKcxY?P"hHhxg\SOgfyVnPHL3ZHOfv7oVO?{cj~f *qH!a1rVe^ue8P\X@_P.D9$Ib<l+XKbb{wzw MDiGr@sZ[2PIDn+?1h`Qbq;O9`1{^)O)DY gSY|ug[VzqXkOK"VY *"4r^fO34SS n h '9#$*2-9CHJQ@2r8[ZbhO`q}Zbobe?qOgF^ZW(}7e o?`Oi[eH!1<vnrV?+nj1=;OgDP?qB1F "4Dh:Zk:I0n{^#Kk)yu"*gyc^Wo0#^g {x%8y? =?A4"Lc1k^DjurcY8\HKK 0O7 78DFkfnf;BSK{'1)R$;*7F4-- "$LBqOH0H X0BSL# ! ?HShV4 iFyP<(9B2X9!Bk;ZWkae`xi`F9OqP`4*$(h' `#H2 `P  '7   qyFfj'kSAKnxvSKhPK6a"+]4PqgfOV|L&?  ' ] n!  F : r *   4    z)}B1| qQ[sk904d_1qC&,4K~.6K Yz 4BZf`C ]rUSg^xS,7'oVxy Uj8- 5rg n E<D  .b i 2 `c  Y ! \ V     5 lu 9j&=  y H ` g   A   S.&cH5i f   & . #ixx"]E.]U:*2F*-TQJMT+ed6&9 ve!Wx jLf|0$}x'!WF A(pyOZI(:5Xq3j:L~-FFl_ p3{uy c9\9 W$ U zXZ GE  HR n5oXt\`Rij\HX=oG  xA ' |  gm 9 8  O <4 1 Y qZ2nYbaJvK b8:oyW8/y1%t}$SW IwnWe ^^yxYAsWV?l]5C+L_-" 3jnRcCro (b^Lq-6X6b\" psv!;# ! xk.3dn01i7ixE=-: 5C?&Tp(009``  $ ;  jk b  ! Y l x;    1i     } kI)]<A4TadRTy ZgMr, ) 7  ) ! } aJA:B7yi~7"I1:Gh*$6bW5e#Z mf}Ri|l8S$2[aqEd55nM*F<82n1n%zsU{y Q>L8 M  M e [ X b >h N@ _    & K  m      H O J ,/  K ~ G .D SxY)%j<`Z 9b QZB[ Sq_+L [A p{}QrG  'bA9ludhOV=Sj \;k?F|^A 5@,~\ 3"v[OnZ'%KSl Z:o5Rm+jY{ 5\6njN0t Vdu-EV05 " |] + Wsq%28E ^Za*Mc&:eGGkzjEU'zgR:wi$+y6&T[],}e?\c0qG|"-w *xv`ruRRHD:"=;KHo1ux3$_bh}m8KQ ! . ^k( l8ZrW\.S<3YD`= t4AW[UC|gP+yH:t#A"W-60p0(>(z" f:Hw0'voao?KC3bk!]6Exmj'C>gRIj-W,5?a_6N~2#,'KB"8J$(AH5g$7wnX,{x[QtGU0lWM?j=J<{]3 jbp:W=3Ayk+2 iaI hWjqI]IdHU9Lf~DO~Q[^p?6p(Q`pY!bJ !\o"=P1'99,{~5(e Qif3;2 gPq[In-S bQekW XQ5a+on_IKay~QJS<D=waT_p[=JGJa5c=DC^~^W7Q7!B .RyR^`P)0~L^N6oe<@w_c}0PB[1#otw((QA3d" 'O {DaF:ZfuVAW-@Pgz!$#k oS?o.`<vJz =1%D"bb"AzKDv-93\c Jr2khc9p\fbD%MQ sCrcMZcQi}[}zJu4;Hh j^ga{ufhoAPAFF'7#Q_~|gwp~izqw,H3AK%{7\Ar{q$X}! Gbki9_JZ['zg9o<Q=Ai/W%W-S5X<4ikXAcLc1lOcFiOxM["2bxXPFC+$(~yBV$r#nV)k%N| __Rjjt[YAiK3 3ON2>`J&b3]GU`Ym`+:>>=Q[i-H6x9R`g)#0 frKZWcj9xVCcC#(DW?8?RZ30r((yq{*"f{Gr3a TOF3vX uHn"xB jHB7% o7 Jg9";F;-8"  yY"~#f3gVhH=HVBw"7:yu`Y ,'H0O+jnrvyIyVo^eQiO5;@ lu~[$2Z5[JR[jgtJ`lm"MX&j]EM9JmYH<2)M9&Q) R5D{{~v2;sP\bQ .J*C X2#C`WIy?W3vOAZuDm|6d0 J- i2!:+-@[+(!J xd/XCKQiVOxxqj*%,3 ,g {IS=~r7 ;1[rO["ikI;3Gf[vMh((B<<K1"C  +,~ppwM9 L8Xg[#X<`a=8RH43ZW IVnyBh-^Rx#L`Bk)u,S?R-8L%gqDh?WOV77* nLPn \'Yv0^n:~fr`L^BjfWfy1('8Q4Cgu7V@V#Z7zX1Wy`g^a+![g$+cZ3f\h\wTl~s_fzfJs5wT @%.TM883Wr_Q\L9*(8kQiXXWo?x?oZ:7g *"r0AH%a_x('!!( `up[[=[Edg~tKC&nG&[ !u!:UX AYO||80:;+D2x1FhVZQq< C[T0((a@Lya.Hox2[<H04qP!?0' e B ;OOa4[L$k(!{7YS;SqY\RII1I-)nAA~? WI:3 - 7- ZZ?h V 8 fKxv#^B7!' k$ao  b.JMI^[ P!7(WBJ@87*^+IvPD9=Q=-1^DQ5gC_xbVQ,I$Q2"8#T0(B+k1[ jx={ky~174HnIZSyj!cv qn:k 7K`==_??e}KbCLy _x[ hY _',I8 ' : , <! ? i  6 }   h& !s k -  < =:-*&<[N"@J5k{umzJwe.]!y5SKZpOKLW* `LF:M(!'BVH)'`%fP~17|b'~L~;te^X 9W + D s/ ;4  h*     Q  g A p l N R <   < [  R ; {  Z cX GS  i  &EW& ,  H v ) ~   zX  oL&;6uTo8mrWnJ3[)"YZ-^383fF u6B/-7&m5\K6r)l-E?k?+k2r_o \@F`1z[ S:`'+ &,'<  U X T& t i _ !"a"="R"oS""" "B"i"l"q'! u KuM    X  }  4 hP  @  ` ZT7Tg-~kxz ge3|^h.>dB[y2pIt;4zh%IzK%mbU9P7^'';3AZE < q2;k,d5/&k5S{, 3}>RY #   5 u  , &P  9  R i     d Y Y! v n(}x|KC 7u 4CNV:<36R3v4|:x B?Rc|=0`VUy3U!bQB, >rA/~ &L@QiK=/g+,D)MRN i 6T $ & 6[ a\HuOz=V\I[v_T 8 4 O  . T ) ,  j 2  p LJ yp  4klA*A   73 / #F,/ %b}->[JdNMPVewS3L vZ:1K|@Th7E#>A@Asv$e;95p)p|&/$]M G.D@X-*gv+n L U]4t&z[-a FQ   } 3 j Qx      % 0 Y e P 9 ` ` 7 2 !  A} AU G u/ O    8 VE>b5^P/| H;=)x$(f>Ao!xONX]9v#u;\$^jS#.V|I2{z`AgLc`?3Y~E] +iYT 135(Hq !q\O , 3-d6mIAGFT ?m ^P8u-eVCLG8kT1kn[.]+5oe6TesuTZr,e@82_A~GA n:a8r+{@kXKc!bW6_ u:%S33Gs,SJyBN9 b(vJZ, xqxn= 0Kqo(?>GIV }co.kUa6S-yu]S7jscqA:3B**4>=LNU{]VeV_avl|l8'J+|FW{V`x| x1(+!K2T1,/$5KlllNg`4yn'r@iWfTsaw!}22b[jte m-U:,=YQO[wJ:eXmjqceiAE6 TNhpjF70afZPp1;c!E!b8|8a/bWo]OUrO yWiJ+5S=WhZpB`(!J9*fBr""qp{k1z~hl<  ! i`;O~WHqO#Bh a)An*:Aw`RwG0/ [x._UTtHJ<\mU30@wuzR2p&`NHH&2KiYmnig,1Hj4PHV Jxr<B3l8WapMy%{JfPih",Y\\t gtfNh:D>23sCbX%!s{wi,. kbFX`;~fnnFV"n]0#0wwoc~ [v&AU{:@vHRNMmvR~`!"Vm_3*')ZZh? 'aon` 0VXq3 W TfBSCnqF[Dk=bzriiVsoS(o<e+!9(;72^o-h;a8j'ZB?{k\*,z/RKQ3w(Rd]->K.'pP^2,l!\o@[c}tXl-!AHd7bOqbBKx7g` IB DD~v*$ * gkL4^x8SDP& A%85bqFFC^yoWvGi@2%o7D,^nB7$-mgX,Q!:n)t0  ph !d@HzN"3:g1VA@ZiONuOO@2Qnfw~beX4v*Z:PYS{oS`[3!J9Kh Sv *Xs%s<o}{i-pZ~LiSwQ8ZSSZX-qI-n+y ;OPh$ $'[!h- r20r-! WS "*yq  9fWo s~K7bW.I$@h2B{h_Ma@}(1VV o "4n+Q[L$;rZH[n%uzx9 ZzvOxnFu(IP^P-L1y`cnqjovhrh4*,jVZ %Zk`S*LWAABI^S`,7n#Oj{hj7#BfV q DLk ^ y1h4)4:j0YkWg{xZD'hA:'h W8$0WR#r-r*y(~nr?bX,$.;r@BiS\K1SG1vC~8csDfSPyi(G9sCM=BP XLqS@x-e@W #L)LVKL=)`gPu#' ,1Of-uf7d_wzRzm#Y>(fE2uiRAVY qRRE9zQ  08jYcou '99vOySuQ e1" K5}nqJ??`vy}$avx[ggOaI}uSb`+ #142g jkRcL=gIoIf)`LkDR:7*, * %##  =A ^~Hr?x"Anr*Z\Px2^IkRSy$7 4-^I-1z5%_u }ghr `byB}$y;^V*b9oO@@2S;B-C';( 144 !SZ`erXBn$2LB* e*9n XH2@ uOZzg[uroyJoa0C!  u?~O**$SF: r8~8~9L@xIF^9 j0QuyWi}Qo`HrIQX$qgnxhiv^V^vB`1B;HV<}o B2I8< 2?@I1 2[[B?+<X S4!x!u-Z-rg?Q(9 rhgocgPrxRv~^gH8{YPIFW? jF4Y rPq01::o1A, Dg=[FPi=b3:DLgVuhB-fKu8KoiA`qF0D -F?Du\40Kc*$'4-+#8!yxrhnnr\WcxHj){;=u\;c%FUr((Oo.E& -56gWf7jePv RKk;h N F v +    z @z  q $'&{W)Jo @jCwb MoPKfYZ83 b?p /&&mUvnFb1"OeetlnH-W'YbVrKKU1 vX - u  X g3 vR !"! +  Krui&(H(PU p hm < IU K c+  r  ~ H 69  oy? I<%Q(k0NrEL_Z:XB|Kr_z j+-gr#ZVx[5#QB9xy::F' ^SbuW]ExIwVG"+a=&YhIFr_6,S T$ttJ"FE3px"-030i%^ZYKv[j+tPQ:p@!iCl;i}P4f7?vA#IR+ 7s@ * < #:  2 !" !"X!9! A2~>W baL 7A 8  2 E  j WDYn]OeFgLNAl&~-$4QS2@dIrg.lxkR^<. \|o|{yT`&[N2FKMc?e *_Jxt!GA'trr {V&zz?yF_7Uhzzo  `. ; Jf w*  uGKcSHe^]0wp  o   MA )k 1 H d  [kW=J=9eB  i O)  7  KP   # o   GR(Z<xR[otVCOkkdig)@?[ @un;5asLW i -bF*,c&^;unT\o1htz.eeo,w  Z8X <    zbd{6B:60>#8   hL  X L  z Cm   FuR84`b)v  IU & 4? ! FoR:7 '/Zl;%z:$7X:|@<{\>hSRJT@^e:I=`:4D=$[6R-w#\Y'K#xVi{ s^Qlu70?$al[wN2:xz2' RkL@cY+?lE\mF5k[d? km4 8"ZGzRK~RH52wFP~B l>v)obX_xI:V"6F()zdwAS-sNAc)$M] <6[sJMZ8-!-@EJLn( 'y5Sr\[i]k>V ^X VRmnO `B!XI@g^^a3  C:iJh %>00BzG6La_;%_PaSd;@+4`S}U+8pJW2<4XqGnQye\|XyB;4Xll:fSdE| 4t\~ v"p%c,b%Kr:UA/5L0)N1c_`>oSnLj1UAvFD^/YS_i(-E3xUtmPPHA4 41L K4y $ Au:')P '+a~ZuyZJgL08<Ia!V^I#HO " "o@JEp[UH"yjq'1\o~pKE3mY]p_ht8Whw0:g-R?a'qRF^ZFn rnuB`SKWuhV! 4Z)PBF^%*!\;X5==+PwZvaf[agr`_bfv;;<SF*V 7 rq`J<; nHH ""4q{fW?' gb+KN[d0\`U?iWPjbYxm{47 *@ !8!24Q'F?4zD;Z_W!=I .J)bMk2olrD<ck0M QD&&/987 %W1!(!EimN,?4o4V?;k(L)WhH;:E=tAHQ7[f`@Eu Lz-Y^V;Y:`UaGfdyx{nYzf\!,011AP\V jBYF[*[(1o^+V e8iriVkz  19( Xf_J=$cB WaZS=,(!"D($5Xg_W\?3 I#XIz2\QvJ $Wf4rwlWI_@a.f=S7 R- %e~mefxN0]!6#C#gFeH8#2#(20/=2-JwvoSFq0YyrW{qDyYrV(I9I?Snh{[Vn'' HiZI1z|y`Sn7OO!V![N-t7:1R23G@Hbt=H"7KV="): [Q AVbU]#8O%~17YI?Ky4:-#87^2R94z%'eRz"^SW:O'J?8LhrbnOz<x@[xrr^z}LV^oxe iaH! gqxnQ?0'L'V$ 0#D8**Ra?7;R^o{8^q!$$'!9-[(V8@ZC8 O8e!87rz2(M~D"c1l.MWPcsvr+ D>$]K<2Kj[&wHw:cY=N2$ {DQo!r*K;p_Q!$2%DyyZ}okXvg^eZ^?kqxS X'J [Q!*cv0 uouufokS{<i-HICn !JO0CHCIx# o kJX`CHVaJ`Z40-?O^oL[i rh V2kn~{n\WxY^nf\AW:D%I-=FH:K 4#: 0`A %*-4\'"1*F0:L)-0h?SF8Ykj~rg~y~{un~4 (#@ *$^k`~juh~{H^1L:Vy?~o~vh{k~yYkY`IZg^k\aoWfjSfOhgR^hOWfRrSn?KYDHjZD{La7yy~DfSRFf{B OOOjO=)FSKhP -LHR8B#*Hi73fF\F^n\nSu\hzPY:U^irzyLuRzHnVg,gU&9x3KS#? "R8#g6jbs!l q+V?>u-_>A9Y@f*FU  9G G @H  _n x ; < h {  y IH   ]  Z9 7"c5Hdk:Cfw"v'1Su@xA)t_OEK}B|/OO56}ezK&[hH$\[iL$UmtjH NfbSIog\ 8lJ:  iOwk   : ?    V 2Spy%Zhz$(B8    Im $  J   l0 o Ff [ 4jE ;  V N / j  uG61xLmh]t", b`A=G@. 8WOHKNbtz,[hAW<]>F*u0LHN-66'PS`mu:HtQkcJ'xe E0c!-L|J56$pB3(uQb}o"k?f ~i%   EZ `\ )>!K@"&u"#$w%G2%%,&t&P%R%%$#"@!(ix,Q*     # 2 1 G> r   H 1 ? B  9o@T@>99?Bj\x 7R% [[X`CsgB9n.N>j;F;7 W)+hP"_TG>k"Orj W;"]r^NC4k4Z?9Q*;|W|/ DQ7adz laPRfbA til NltG?Z-X9A\:\V?*jhZoaJwL(lC$C5u] m{Q    0CqmA9y  o [ @vQPv r[  tE & 5 ] lL P   u d X G  k   gq  OQ   d @ /x  p kj Y VX  X@  Pr H   qU4@ w@gmz[|7OAm7"KW2f`\7z\42;~Nev-]e ! p02i\.+ikn[}0?,=*q*{Z8 nx  C F A !+"h"""!\$ fap* 8  / o  O  G V 8x agO58  $   }_ T~@<aK:Grnht6rCc hC|B(J V6.Rnk]dd-}Mz}wlRlGDibD)k-Q inj#~I*I+`e CSv.&h0{))8O;>OlV|=i}u(]SY 4vK[y#%'l:9>S4P!iy~;iIP+0fPnKK=%lXk5_"+yw\Ne=yalfKv+DM?gTzFc?a^+(Da)27-ZCvX_@[8w{m +JkE"u c Xs ]/U z@JR/hP@6 _My;T87NE'B-r}[q1>IcKL`OlfB= phnD<q8VpiA4> f|ye7x'5$7|:ua]kMx}5LinL[LzEV!@K0R3HdGRpx3oy4%L 27iHvyBGz`5bo5x9E,;\K\IwEtkd" %D$RNQ/O)a 4 b[B<<8Ho8'H \ckOLF )h3eub"kW\w%}Yy{?x-wH-,qI#~H%7G;YY2p+U);C,fn&aBF*=`Y8p=z@`cYF tw~uiQnwKg=`OmwqD=q2u`*e0";"JV?=" dVQ~vpYUu|Yj)=pn ?=uhv*L(F\HyqHVFn`[x SC7WwSo2PWrbqHP   ii;3+n$bahPq^0`H2-VoDk^AB7 Xmtx[q[Qzf_n>HqHE=V`](Q9+0Y"OV diKJgYV:7SL%8 ('DfB7;;9 ['[C`oy<(<~ 1Ts5DT2b%_N@U~izz'>4&-I*y\i9 v=^a}XRU+,upf;IB#mPg0NgwR-=fm65]NI!rs,7yIR\UX10{yfyIv | (zK;j-.`<&V#RaFP 9[ fY@  )  $ -0=E } _M>{gr7).|UEaqD  h  H 0    < ;   yT0# {YYb@ !hB@zDC-{F xYpXi\fh.L; iMLOL"-q=fij/C]~r>-sX%b1Dis/>Z^0lI99v6YP 9cu^GKL)i;mI6v^J adA*qJ Y@8  xv!$&`'())(M((~'!'%$3#b! hPfS < .a %    Y   ( + 2dej/6m'E$I{nWuh{+ONalDox&;mN$~ 9aQGhI]sT!!c2BqU0q/ 8 #m^_~nLN-iBv;il4K    9 3 | [ :    >  P  } U ZU * BR   ?1  +n4u>_WUR/T   PB : \  N e  VX 5 (R ?_A^hi%yg9 [C cxuRf|]R,&?%"f bi=+ID\P6:e[WhsROm;kQ|Y2PT GC L +x L' `H il$,J<K  e  n7 m   S  2  } p 7CyRB{B c C N :  W x% cyqx ^z.Vt]-h|=Mu <!1 PYR3L?%iVLPZ0;',)?-<0\ w0`n rD(8 "DraSvl/9drMa9M>H | G>S0aqM=bo(+ iW*P$*x-2+J!hvVhot%i*;9QIB?(a;*f(aKlva ZAk//9wtmiU][J5d?*lQ?[pE6@v",zTh-Tn7Z~X^6LIe K'@=pVb=nui~[v__1 m 3z/q}drhpK/*ll1Lzic|nNxjuIII< L]8z^H'k'ed;EE:SuU@h1 5 Jp"Rj ,;;!ZU ^'hdlwV0yRtj]@'ixmh } z[ E-kNz\ej>;&-0+)<)Y)[;<K`VwiOYOEH)\ceQzj@)7*BS:GU7%D>Y_zmLN}\~pff@j<ajdY7>]YZd]u;y:d%L=OOYL>I;q=Kk1"&0_tOs UE\"iQw(CQ  }^2QH9q^~Ai0 KT0}lI6"z6%'GcoTt&)N/6"[!0did{,cKa 1r I<-WbMD%Qb G=+bC*1P8Wyvbzf{!!wiJ2I3CJ1 h- AkLYK870'gX~RY=]_R + (p=vIy'[%[o2' zd ^6}'Q5e.t2\09 YFg=V^xS++5([Sa[lirnuFIgF/`")uNAwMTu{KN`txeltHR):]&^W7;[c%07;"bO#uy]S>vXK& uqm[ 9=~]we{awv~c}MGN^}I~i#(7Ow_bftmAjj@=PSo$4h8K~"y2! B $)4g7cip}R[sObOhVF?1vjhs=^qfq+ C{T*# xxu781B $ rIA?ury{k8uuL\orok=nYB~ocV^u j;*$B<  1H+iXX<C}gXxWCJI+znQvHiQO!;ZCJPoworyB1'9sBwu8C2G= }W'4+4 rvaL't]]fXi7+G/_NOp_b j-kaeC4;KIWK!`;81Tf*RKvikp*3;[2QLzX]^$V,^UypzlYxx$=gl+l:, &zLXa@[G5* yvZo--V y0@@npv_pjat[PNpD!nWq1=nDK5Ktw8Vivs~ {,VCcAWP@%+gEbhu#'j^?rHh~vu7^=n;P^cj -;?[-roz $2=GWB5Dwfziw[k[kBC8+ $ZViv1g'zenh;+- ~?u+*ac%~~znc?,* \H,-: y;BH+J1-@ILyJ9bZ80iC-b1x1. }gyg}ynyhQi[H4ab go(OZIJ2!Q^Veor$Q[4?(B(^0r iL0 'WR*BR;KL u0r%Vy8 ,;vhovh?HFSF)ZOcj   !#O ;*ZHX OQ VaF`I(1 J0VaIaVVv^SrZ^n0 Vq^9WV`o?zVvoq( C3ukg74v* }0Z `Pa4ryBj8F `)?;hvVq8\Fy=-P`0\ 7"^:^=aD A:7DZ4=%`hKRPW"'4A*KOf+0@S qVXBLHi^WZZ*iQe*$@$(x}aW[ 8$kO+~ !ocu?qK~vAP Z=^cjygYZ;OukP`^)Rh q-:`jv{#o DAV S-, AV ig?vH'S"jVVBIXDPjvg BFgn@;7Qnxaqe4#'!?0$?" f!P`q${@;-?W[< 7WaFV8<CVZVhX^boOJv`7bFOvIHx1e+B ' C9 < !  xyxhS 8?joWrO0c %0HH4O)4-OISku 9Zkz;JXyznviraoC}^ .DvrvwIG\Jc3b<DTD38iaqqiFP3^]G ql[Qs0PBBn a  C ( % ,o  ~h !+  i fD?cS~h/`e1`O|fz&U[sD']'-" `42nk T8rOaETNefTzi 7/-< a$'?>Z[_H)qe`-C} ^  v;M  V <  )   2 ? H S   QB x  1 oW  1  M  Hg '  f +  @ R "  n +j,  B~  ? -,S SYFd^ _9IBkfln Pn#\bZHrIVh5udDZAsT,KfC7(c %pAx?vp @*u?q+o1WN6r3LRz' }BDY B _c_ 5      p@p~F 9 #! !+!)!"  { y 2r/3z2n  H  ]! V L{ p Fw _ SM@M   T mcZ$n|X2zy,k wC. $;L:fZdj"iyP HDH*Ua avgvOm%cvtsk 2i\KAwTf :%C@zM[%TV()]:uEw//=u .;!zh#ZgC4G"};L  < "( $&7*'D(-)=(('8'&&%# "!nWo*Y"F  ) E/ )   r  'a  0 N  Ne + JphpP@ZV"C'dcL3WhRNg^,a`2_M@5KA5D ZVnxMU,]jl~m-}aCC Z~d{P?euk  ENyu o   fBKs=#w'~eP 6[,v   K  $   Nx   ~O % M l k A I Q E ^J  o  'zd e ] B d d   * e uR Zc/EW|{#'}KJ;%0"e/oW+ i]V, iMT+N4aCI.Uj/o KsJx?&eNJUZ,_)]Y0|xH#ee@`I` S U j  {k  Y U1 | ? H<#%kd,h)WT ]&PDEc r K y  Ao   U 85c'"]3<s(58}Reun({%I| X5&1P_"ky>;io4iMMk''zDYdx*c]1E]Ql7=c-@&,n wLgZZ/K]FY0ZAjz'Wu|-: (jR(Cucu-gG>p c72qPpHD" qXe2 s/vHk^g5C/ 1(e9ZY-.5];I\rSLhs|FWC>@$4+L5Pz'-!C?N>I4okV[}ns+!?)<hRV004X;~cy oWHK4o+JWHaivBQN/=w "KEM&%vvzLv7_ruL=~A(C Il\|=s11yGnVva3A=-@_TM&< <*1,-N/>c/c9'Gr&TDx+X5"/=_(\Fw}>4Hfgx8nLS hysh} T zZbY-IQ{HT[:; (-X eGc;Y,j$e_wbw`f_RZQwN0'u RA|y9N@rd4$5+_q]h =4/dtm=L:_GD-Xv=`5A22i1t A+0#u!v!FA3+fG3jO]XUw]wzd9x! "28:P7~=oV2yAY@03CbZ0Q2JQRQii~.x.tPX\8GIPY?\P<= >0[E9"PBB;$2!J$8Iy  qj~}HuA=,7k ID=)n":w [(2dijy3D@< " }fG"6 u!}W].9 _(n9=t~}."t)XQy mnE`x:gG2GZR`kokAB=437xW 7B@7{-?@eh}QCG"zg?(@ }qiW#;{DoIN[ RwfQyVodFpX[ywot@Q(68l[Pz8J}Oj -3j+SmAw`]HtZ{Yq 0F#:1[g rFzv"2@cQaGvMwrl9isA$zwzqbZhgyCznP<KZ!aX@@VeICnBhq4IHqH1AJO//N0!+J+/2:[Ch6f=2z\ifV2ThN6F)W9QTD 85 "^"ZrOVaE| 29i:7#'<uW(Q1hIvVxx}e`iJab "PRDxGsbJWpsz.\q"UbibK-kz b[<hS =4 Z4u1i8 C -70 'Ha7I`"?B\aZ\HYq4``YX\mVx^R`GW+o!{ ^;)""Yd+ OS8?a9oX*CVXvyX^-$4! F aaKX\DS$ 3%$Xl@=Tz@+%{5 @,, xxyqC^4QiCF74B$cVW%k-BC'X#[0])9%Q  Q!K#) 6+,K0J,80B&Wy\G*Ynb:zyqx#($hOPS0aySaSz?n`oo C*,8%!C(9Jl3*M;\y;%8vh3 8  9k@i4FaBFX,   ^Vf3QH}AV\yD-W:W`kckq^rInZI`cgh\Y%n:Z 8Y?FxP[-_?xW`ZHoxwOmjZWH'rvHD-fKnKKIPh(;8P#<8H 0CuaLI(8CH8@7Qg[JI2(P4?WQ-;?zhb< v[[;h;(@;S@uWFZ-;0 u~yr7kQ<X[In{J~SJVxoznZveVqqvzu^kySvy$$ QZeL`C`1WIVX;xZrvW^FQ XyPQ`}niOJJIP(8W<ha[eBX8z0bX}#Pe8CH3"1%#oA :'W3*,O%' xN wjz|%*" ;?V=SHyZfcx719PhJ8Xzv2} !!r\z*_XSskS5;*G<sBQ+a8aZJfh SP9^Ja0#1J*OV-+VSQC'kY)1DAF0PWFR#LL?xxFYFuB "D0*O 1*'A*)V \ =\k n- 81$ $8F#440F0JZCX?77WiIv;gWg0a$WbI;;S !B 7C1 a8 ( # v~yuZKB?#OD<7HSrT ZFi-D@ ~SMVE ? kN)c3[V0pjtn  @zMM8yy    o ;  % rW W  4 4    !  W  I     B:`7_qcWf?Z!zfiPZGnkP|"U\;uGu#qO#*_)U1GjQ O^{)\sjPUz3N$3y"X+l*n/ ).#9|,k9rSAaOVz[~@3g- P  Iy #B%q'1('%(<(V)(w(S{(.( 7'&%8$J"!Qf1 `    hx     ( W u:h\:"3!;e4T.QPD4%ri8bAdD#`-%z6Z| oc>fSLTKH BZ-s<4$$fA fIyyn2ni'F~l $u ad>L   #  K1zL"WA A 6 ) N[ \ r ^  k O , L  8e Ah    m    7^  Vg   5  n   tp   ~ `B"J]+*i/*EpN(dAEVSj!36hpE'1HDz xL{k*gO5,WP1O] i W) 2   bG: 8  CZ TP }   ? z ? 8 1 3 ~ P ~z  W ~W R 8y '6  T } x  F A  0j j sWTZW3z`<~F X Ixgki/9 o?}S7tk=ZTD2 JWmTr>uiC+mgq,eFE 6-:mPk 8M`JVbSo>[Bw.a{:0v5W:1CJ<-/d-;>js8Ko f[ +(Zoa; UD^%orJL-?Q *l(W6LF=s\vijZad a 4I^@g2DD I M}u yx4;^L[$=?ZLSbSr?hq6uhX('#77 x7VnkHVWBH7i^xyxI8K.X:" +2=m;(N*98"y(1),\!=!.! Gxsi`U]M@_Yvq+-93:Hx9>|@E!KB2:G-R^RanJHEd0eeWrb^JyyyV;p_@H7Jp6lV_d*4{RX#1;&-7:-9[XNtg"wU%m#:` 07^|[M}/T(!(Y8S$"!1f $OOF@0i1vv`yZOXi?5ID[y^J H<11/^m'Y4'3&c"&P2(1} s2f6(GC36!)6`O+_@@N[cc~V^_?`Xo.CHG-,OKnlU/W,CpiN+F@TJWP!ohYMntESk:aUM =)$rG; q1u1?amF0Y^X'zA7}i6r1rM?Z"> CP4|biNgik Vkdu+lZC+@PWoAi!2lH6RYu| LR87{84F $;I@1Bz=BC@Gk8HT-2 ~{y~aZ<J=*7yJOLVa7L uF=;=Y&uE&>AC+" X"FDQ6T ,) P6 AW"X9Mhv/-)U=NnUOgxmB=*u0# a(0#DiDDWQgqu-gJb2]mzs{ibbmKyH]YkiV9?-F6<?50xyML a#((\^B%;%=3F@nx0=R/:YX{A74/F:&-x~Ej6( J)@ 3>6+(`_A]/@XwYfq 4K3;O'I1+[@8QJ9,*%T1<?Ch2ZiUZ>qr}ViZxx! }TlslxcsoTg\VeE%zz1IGOViQXq@Y]['xKH>pkdcKb A QOUu~1njh,a00#fR,~Hku 0e-O2[O(J 2B Hg`PPZ'uohyQ17zx2h,xJK}zbI3v;}T5oO$o25!T0<.FyW5(;Hs$C _S   W`YqxS\Sh^[C*$wfgK*3 t|nH+t~miqXuCn_VE[9)nC4ZYxV8oZ(HOQcxlq%xX*S-kr-:<rl6GXmmKqu[emlmD*HY62_3C~CiQ*=/:$&/=gJN  ~M8<I D2(hQ^28+bS~1hkA ~E2-[G]/ F("  <(#I)3)|fA"=g--g0~?=x g\FDvn74+L+^<Z a*uJk'q'zBBXX1ZBLuWXZ0}Q9yi;yO Z x8g B ?4(LX-;-^ vfDhOZ\4H',-*11 `Sj% ?*0%`8C  ""%-'HoAAokYaYVyPPQ( @*-+<WXkkL0FPg*!2 Z$b!iX #<qASqyqrohK,%jFf{DxO=I0g;%vjx7o8)#{~rPRIRL`?, md8nL0agE]6~;x )v*XD9OnJ+7reJzq/Q *{K6M)T D$CJBPS[_zTzsoh<riXIJ+<L+QpW+ :3a1xK3\y1CSOk<*28Bc=+QQ[3{\"ZD22Qa9a$@P+O< 2+ !( !cB\O{Kj:gRYIPOfk~~;+1- @Bx?J`uuJQ*K!  ,;K"("!!;19Co83BWqJQi[}XO!Lke9Q JHS (70HB!77LF1vZH; ;R*F,*% [~xu^ikn\wBiuHRnKp"i'VzI8DmRmHwL]zOG>2NKX *#,S """DP?Ak k4SH7hO*-Vv(D=(\'H$0##D:\%2B u0>JAsF}<INnvD=Ugq7Hy7   A U          N7 9 . 6/d6^u't.vg **=yT`^A0,}oQb#Y0S=CI)Mwz{QC5 }pGY[-r{q%cv"ihb{Q{MIk,  qkV: y 5 { X  ; ] ]H I A t b   ) <" > J b    &V FQ Q ** r    _! - M1 I 3 " p o ZF  Qj ><tG#p*3Gwh;!/# @ZuaA[2eU"f4}4$.(8;FC;k6v}MH7D$-h .>>CW|>NOF ]m=mqJ5o 0V.kZ+g!L(: ~0)Q ^ +  k:BF?V 'o p  /!C!U!!!( " C]i'QD>b,O z]     Y M X  .  uk<z2z r|A 7Z&GbnZgX~ 'qMR \{ CvZ$m]p -CMcw xED^'o{i w  ^  T u5k" \x8 ' f  > hs l{/kiu5[SY4NFZNi)dbh 9'K0 ]2O *|pK?D*/aZYWYZ|$T?NGQp!(aDl pF}+"2fR~Ltv^zThvYvS`G3rvZwiZw\ #> R r= b ]  D   s t  ' , D ] 3 M4 _ r   5 <M = Y   4|YmQ#!A(*d|a]{tnZ&;g;9__OE:E E~Iap{SuQXjW3wktD`X6Z A 1A1\/##>K;oj8|'K{y @/]pCT-=i)aN,_%AL{0E]uy?Xx#<V[7Jio }*$C#+GqKBM~.ZBS[awu{fb{wx\ PSQ1#7X8J~7bG _-<P2#;$ QaJ? (~fu0W4%u+x=<=~?-vuS5r^Lc ZS"BI9 BA wslpCz:{3YxpvMXg3lwFkL;dMik:|`o``H#`y`q  *1 W^@@!'!-^`Cpi x`u>|tQy~o:q_3nV#m%V4@ RjUO"6XE+AjN 1?Aa#c"y ~W;;^=R`Ynu8uq@$qVk ^P`}r*(<C_!`7ypr\^c5;+3=@ ,rW[Q#qu)=R23^H:t}wh|Qu_yHN:~>w")6niNG2u7xKggfqut;FZ3"`D)K\I?W7rPg #F'?IO?ZPzQ@  98CXZTCGc[y~oQMP\Q9a{W*w$ JC\. 5&!TD?'8zxxev;h7:1=Y`n4XA[H7N! {yio{mycI<,1/X0i.HU+=QwfdY=/32;(D>=gkiRYKu'8@IZIk4@;QWvyZOu0kZyyq^V r.QXJ_ **2uuxzugh*;(S[XixyO?uVXq`Q0[1^P i ueLCJzgXH -ex!TPvTa% +20TbiJ=zbva+POi[ro1w   yv4u r{+fx qWv0FVD4%" {*x'0=a\KDz^d,t0pu'RCR/AgLf|b]][Nw2 B%8@18:?+D9 Lf ! JQ!8b#BOg8J<QP}ky^qoWQuZ+aczwsJ}ZZCeq3l2r+P$Bp}TGMlkB_cz,k*M*2KT[I*2z hoX}VyZFqHu*0v2-#`$-$?R2{+qVZ~c1JLS[C1qCqnkZgo q41kkHk%%9X.X5@Mp2 k}y}kWnzrgoSvJb0vPeQuki?geWh~Zovy^DxovHY$Z B9AC@cX?oVqnXr49LJXh8P?7r$!<+S0@o9+!{'ug*H `CVh I ?BJ$( -V!$* 'b}$u^Cbq;I9xq8H0vigQS!H''hP*+VJ-0x4J0*#1?;#q ?C7 0( P7 xiPk+viH ^1V^nHZ9Z@0b?h^<k@e@W4x}riu7020''-(;-0L*Xy`rX$(?vvFOaRZ*r#,OV:8uVSq^hPKhq( 1Hk^J9<v`hHbqkvoq 8WzqCF?iog!^hn?V)-7-nxv v, ?1  ;` ARvFKdt@mc<ZVXB   1O \ 4 7  e  hwm9aY7"jqqp7C[:. t\)kdf5E=!!X{1wili}?h! yF>>s|}i|(m6D[l}E4@q-$"8 ]D'R TzG ('k4qM&Ix*O= v/f] c1Q/3K]-Ch4hWs5=`CX3R2Kl[n8HI! -r TE%b ?=  By i8!#J$S%&Bc&&~%^$t" sCr]XQT  K |n  A n 1(  l hP 2 Z   N   ef  Gr - 0 #  ,  { l . QL `~F< ,~ c3gS[P 2+n,ggOu0^V&}:srVQ*wQ{{h^NK)%oTFe&`bbT%xhad}RJ9Ao/p9 H BiR,YA* f    al. !0!!4!!V! (*@+:l   V  8  , ( 6 M6k[zGpM, 3   H:   fh I%. |[K\f[.48@'>/TAFs'wd*>rNp6v =/5BE9`*_$V  ~<W Y  Uh `K si=,L 3   ( B  ) ( 'b1@+f}q 5    F 3     G{ T N\  6)IR Z,K l0I bUxx[s[l +r6#RM%7 7xn<J^Wpq)++5]yqj0z&X3$Qv5Kh.Bryc{Xy$y'F}(`vr{D0#*)xRAf&XwA^u> ycK\*KV4KSkqa7KmS\{]'!:.''y_ VIgGw&GLm 1$v1QJ3 +-W+9'%!? sr+4:K; AvS] )y~%\p X|8@ p}v6T$e/j^Fec*>B?qFDEiMw#x mDq]Tea O{ [Wl] .I)MiH&00|d nRRj ?`$^J1xc8Z"w: d7 vS/4/|Tv BYJPaP>7v"3K+PZA)L |e$=16E"}7{zY'O`9,~QM5 |_%kzMkx9%_.~|1~I4Dn0}CV,EB/90t-D8)*4k&b8W0aXxruIslMkhxM`b; v$3,W% b(w 2G81Q~6Z38:T25QiGf+i p<[b >`]bK&c8h*JOuLP8y;28Xf9cG*-OA XUwF/W)"DSsFSd9+G/5+^5(NP-VV.V! T^s /G XIhfUxk' SFu`< h%WS1+h@f~6+%h$h5UTk2v[Zb%+$5UlC9]I=lxieQ/;1e2gm]]+cBXizrt;2#<1@ j{ I*CimCO ~'Q%90?yeE[ol1t8<$)?yEZ-3TMv^[|eLW'64@_ykCz&| s"DKKCo|d)GfjD{u +*?i ((G^DohbSL>JT1xK}iA$$X9  Bb^uXv' K`b=)Z\YgW !i& L#g#pWAv]w\Sm{}9b}zXlwilTobg\s9"lyaB\kfyMZ(L*0 Wz?WI!vW IH=#rf)ohfcO3-?,|)_)~*=dw%GkqKr:P[)`PV?!FOYS2q7)/'2Z Wnj"aO#?@,b~uVC`71209%L0@z`vv O1'J;+"(,i hhr+b91aFvgZX*-A>/("^ HQ(WB$\X;%"*7:"V* Xk>: # =K?%Y:f00I%YIxH0# (<qV [ B-?2ig@H-@4o7qg#Xo13q^zAkVDu<?Ub*$CEgUa^ yVnR\OqOZjD`LvO~BfPWgRW=H0^^fOu98~7CxHoSQzy  #rica*so arV[ hX;gITc_$%_rb@$*2;*"x7ZC i[kXBPQ7@P":\4PjkPS4Ruyy{:FW$[L8ihB[?;Ir1^(^ `;ZgIxSI[Daa,z1 $ =)!-+-Y++&<N3p<T+KW@l%D!}XCgq?vSX?ZL'+ 9H#1!$H-I=uvhjvZv^cH?L;;nP`BcFqKkI=L);SPu'r){F{%cjnx^OD\Kh=#,YV]=~ff\u  $"B*% 3- 0;0rVVBjnW[ +Ca@\.P10J4$ ( ?5bIO1ZLxbxQHOLh@$SW[;-Q+uI 4eg9F4YZF`O:n)8Z|]~qf:G0C~x-A/H[!m)P`zfo nxk^LaHocxyxvCLVP;BOV1[Qu "+;+`4^qhB-L C! 2 1!yvB=RVyRuOHV*S:?BH |V[]&EtH`uRgvIDF:Xyntz FA<BYWW`YHF2HHVe{Jo)c}[4' oXOP{f 3d(ocN( \o?sEb>b ik^ ;9 tg .  0   Lj  #]kE_gCAI o  n _ n o  Z>}B9%Ieo;!u 3Axp_-g1B $uq-H*Gb3_z!!@.yFoHF` ]Sn ;uq>' GkY50 + !W~]  q  h 1  ^ q    rY 2 ! W  H   ( v    X ~ `q n 2s 7L @ ~  fJ    '}\1   +   F~  E  r2  #|o[uNv7\ >f)C)'g.U<}aM*O-i{v/:JNb36$=7ZNi]k[Gz~i[oeM\{]] 2uer;+b3GQEan\\&fJ=xOS;a]R 9 } }  2E !X'"#*%&7'^5(C)=V))N)#)s('2&*C$J"] 080] Suu1  ?< Q x n   1= z L  "  # dv%%hB!8eTdL4SQaQx,y$iXHw-4"PMp,fy[.I;2'WS91.Tc3CX Wdej k4-n3vyA7(@~MLcRkX.% JQ}i)k|0S4 :qYcc&Z\3AVGQ2Hd2lnuݯ|"djvqNjs}W?H f ^ } RY g+uPu] u IX - w ;  @ hAxVV-k 4  / x  8 } w  f  4 H B  1 Qz U 2 R (6Ru%' [ '"Z ~!z,KP2osn%;g%}za8mZ6Fuu-ntA`~ [W9+6QPDpylHCPB&u3b TK P-M$8)k Zm EK "|@$%2c%]%d$#h! .{$'  & P ;  x7  _ ( * -O mli L [  3  1*-'67)Cir>KgxkAz6^ @ `ehhCEhe1|}_@t1u|. ^ Rc T    $ 7  _ 5 /KQ*0_tzl}, qOi f?  1O5z]t$z 2   6  lu3wKP^d7*wR%wn!{i(pT4`i1#\[5B]Z0gu$[<{#UMW(J !~cdvZv1\ILd-9hS;:3|*  i  P > n ; 4 P_v5wu?.r; 8 q  m#  @s  3 lhl$P a>%YfVr6vtw\Ffclz;g]G^;& <2$+5?5_^hUIzS*%fI2l=FWJA m|49dZK_{^ +Z/9pzTWh0CZ~&V%ZI+ KZ@C$+uV-Pe}o>#H$uL]qqv\yO^xNFI7,a);o\I:zo~?QRzpV 69/G~q`NV|~)TGeRoC6(wQ=w~v -,;%44:#QWI?f+FHnv0x0iPFhx $I @LB Q%fQ=KDr $}obj2`>): kcZycyTio*4! oOH |tH e6 3&%eLBF5)F*=6FU0)B;rBk::Sy`SBa(;+'de(lNyIG2jW4#OPk.s b7sCh<jp DH.|>`7dv9Pspve]~-}5]@_)N_J 'Tms!T0IJ ! e7Q81|K}mgEY;h? WvvT{s"sJ <$)5<?8T.oEv>qi@hz#P S4E 347LW22WBz(c72FMu+^)k$g6u/9-w";Q9${Z+i;$Sb{fhXbvcD1K3)%T4%~znPC"uv0 ]hVp{#!OG *1;'1qn~+F9Zh(6`GVIah03Aanc*JaeXyuPnko8S L 9$8j ;OA/o"O@L0w!UANC~mWC[X9Q \N5  QXP(E1]lY{]pnx)(@7RI`^K-%~ :^PSSFx{ X$}Wkx=,.MV (sQh^G1y a3rvoK~ofzVHjP:*4jhz{qhvgFa?"?HxK3HaP0ZyIrYnv{xVPRF;rW8!`(<0gxHP y 7    @   ( (Z+X-9C(aJSvfk  3 3%+DPsP!y,vpi2\.MJKQZ$2c[ T9$C"$oQ.BiI[(Iho*B2x@q `v?QV1vofhDk)L-Hf;qBL"=PSO 3'8)4 "-7 | *L'0RaLP7u-o*uk g8#eo a[[ZV9a2Q}[}Mani2pGJ{iyfzpgzxC(M, 2Ih(oK Chk;;PXOV Ze B 2**(qcyY?oHHW~y;n7y`BSRuyj{{g 2; -O1#(( -V uV`fh8xcKBKK"HYf0n#;xDyF1DDD`\:=fO4HKA*8,S 7 1\4W=,j0yO3Ia\Sg378%* ?%7r4`{jOrn g"=OA WO'*3^BcDYHyfP4RDVLK8I47I\ kKAPIn^J{~qx!( F kH!0 [@P# I gIkiPiJz+y +nhOI42 V<JQ@qg<uyV3#3J}u#kB~$%-F#A;,uSHRIH^0B4;vBvPH-vgA{`Z ((VCHnQP }$g!(9OP,;,=@P92l@=_T<D;,9X1kwb aM3~s1<WD }zZVrB<eHXB2#rVnhcDWK=DF'RWF8?'=I):~-x?`fbmO ; - ,;'?FLK4^=f?a\gaW:83801VYr8:vfHWFPyPv~YRyWjfujP^cjaIu^x~+ - 7-8+i*VW80aP2P+@ $ *;JBH! 12q+ a*Jb9B'!BS rrax\KSOAPuju`Wn='3u ^): :r~on`Lfj^rxYrxxS* 300r\#ko <~ Z*I^V8 '#OS4 Qh9*#HQ?@CJZ7xr0^1onyo0kWhu-Fzvoa9'Zk['8ySQqna?uxxWqhLhJSW7S$4[Lug9HSgH1Sn[[IJof22y=0KF#*DLL4`WCZS4 *+;eFQ*B#inV+WJu#7,R^IiVc 9gP0+[zyn3 (G+X*{,SIQ8aBT.JB  "!S J3D }9F?HOWCr`}@u}XnhJ1hOH^z1  0oZ}nZr+}qoQ1@[x=P"7e }*Ieqe C8gL+ * ~`  YH 4cy{=rgq:y#LHA$ =; 8Qi)O*==O97 '+#2,-K,#=iV * '%' $ R? )4'0n% 1" z *Da#knrrau YKy"4D=o,'%)Fu\Z~j:^rfI\OD)fqD9 bHrx nqSr';<$!0?(!^`xi2BQu1[;i 4[H;CBrfR*##yqR@jKyRI'wfVPVr:\YOHju@_|ei_c|wMXIO ?OgD{7[ M l  ? WU [  &1S<l}+  '   u ; Uz &   S v $ a    3D  e  <? d'XS6J[{?O-4mRm!R>sG_FzT 'uffG|T(d&Wlal]!LEdN(ݢAeN:D'(hg^  {ehf  w_ "$ %%V&]%$/"v  la5 0 |. F U  D - R  gV e |Q ` g   # 1 j  [ ! / X " q  e . ]   7 +h+UV4 :AdmwdR.)7Ki $:#=YZBi=,266V4xcKojaӀKԜxx da lSZX''[ ~  b I v "2Z3( Od h q } `v ` tV'J3(H})c@j 1 .   |p; ? J M  h F|  ) :t[c 4 !    _  S  Th EFTO1IO fW/`6xdw)iy25Dg5l~XA9:tV_+ /[u?6]ߏj`,O4c'?CR?aj%t } g >n     : c  M H4  0 `  } j  w C$ 4  E#Q +  j    #k[5{R&s7[   N <  H * YTz6oY`3:W,cEw?T#9dK xx<^6'=ݞ^jB#2yCp1Nw*gj, b eB  Z 0 z I R f :Ae]rMn"8MC;Hs-K  ?R O ^ ; 0"))   Z  Pn x x z I |i   Jyj/   } ?D_l}@ teadZK` L Ep6I>*z1Cp-Sx7=`};,lWx Y  @ d g <  \9 hZZ2[,hSxl{ _ L * 22/ |t k  JZ { U mL G ' }#    U{YG$2I[@n!lmzlLU<'dpZUbD'KslqOj_Wws   J ? G  z   r)t[#.O*fLF<h7 u Jh B   &R t  m Q  T  m3 (i~@M\qnNU!)RVe6*-\Tc mjM Ag)g7>i>wb2f#xm_ub=,otmEdFh <`? 7jhs5x,}P+A\/[?RG \)U} kt|q4X}\w!8gzc/eINbw%lO=F2L*yl{w& tt\)[M& %2'/TTYgy.BT. b* uB)wp{7; +!x+  O "x\% Q  Ph%0"OF1?ghr?{o(2$X2e;Qzq{k",DA[wyo_PP'v {or{f3MG%X0S9 ^Ff4t=YpJ3T#A"=|DdV_x E'}~.hW_ 14b|,}o.8eXQy& Oxsht~'!"&^ENOV,K<<!k%%=v+y{willrrz*Zo )& \S+G*Mzpz1s2Ivs;h3(T$1;bF2+2qvoy*u2k q-P@[VH'(@ws>9+& ST4]P)nMw2_KDhozgIJl:klvs[]UjCz5~Cf3`bQ>MA/2lDC{E%+Ee}:5Q==#, {pY}RzCGJ=JZua;O`Lg{?n%1%uqnOt>Ji_&~0A@@!/+{M . 8= .a2/%/6A[wxp_p:Vuq`P '\=#vLO^hh9y_MsrzsfhXlvaJkh~ikl@;0!BI;+W.uoy773Y\-p"3p AcS|)Kk#ta1Hr7B,1-1h u8 O-YI  )cuZO2h$Q4oBzP`1#73[T}MVZqGzXSWWuh y eXOP8P` CB n;Vo <J4; '4{WkS{SucWfA) n?78?%?F%Fcco\1H0IA=oAPo-`Z8|n|QibV/ =,G"JPnhQg#11L3_-94Q\xZ~RiyoSO \ #^"\Doq9( 7VOk;auQ[_s*r2[h*+{ PLIz_1B37F "LKjf3^7* , 4n|Ft]G4Y)+)IvXgdv:ZE%[ o:^=gvftnX+tA(V,38\`1RR*r +OgSSBIF ?H44HSSP;[-bQ?*(FXr(^Zi8RrqRvy`uyvhg$*7WH#h7@Z<W*vZzP2L<ox[^ByxWgLqobouuF[igoihOQPq?2 @0$vPPck O\Su RqonDHF~ZLvkC SH IZQ(-Jhv S11+iB,5Cb(XI1[i;o;=pzPoz\h~;MDpa{vTK*1l<h+IiDG<W9MfZy SCy( L9!uQ8'HI7kWZ  ]pxn"3R;;4`a=r4c(-OV9I1+rCC4*S (!-+P e#zkgqH[^ogqqS-zPqz}za!!?Z<1 h^@-;5r1u"o,CVsZ2!Srl`+F(-$?0W0 qZk4!b<quXenaig9aqOoy$2Z9b LBL ?1 @<xz bvga X$^198{`3;uAI')Dc\A^v-jrqyuj|`8Hj^~H {=;xD3 W cL4|Rr-a yv^PVH=ooK"{rxVE!77+=-gzAQpiRpw Qz,`W'4=FR Ahjn4FqSqjkKufR 47a?k0vS[[h}}q!2(8SDIfZWc*Q@( o+HL2OJ FQkLk' zCSCL(@-; 7nq`7'y!~WPO)cf'DPWA\ x#fy\xxvS:rS4:Oo#Z(Z4J1Z #1*QI$P02W@}nn^zxan+L^Jquk}C(k vP\MM.SIJ<soX5,pb_wsfwIVhPy; iF$n4-o'B@r2-W[i}S8xHo+HXrCz1a-8SXiVk$^*@7g2@OJ^J i# }(P1 ! QFW?Le^!g0B 1P2 @^B-+!8`LCB`1V-!Z*nxy}hoXbWhIiubVak?Zq(u$v*H $<Cr?[ XbXF'';+z}^$;-!OH(~W:K j;FKAD73g xkBBPB-0Kj[t H2~tuwO~Rz]Opt gQx7A'iarV)**O YYDkOFRW vgAxZ{k0=4,n\YHyoZV cgWxFnqxu AX*^8SyWaKAqF8f83A4ara4A B{j)aY$v*")gLI:)4xj0Pa^h~B n!oC(Pg kV r`X424 2*(8VJ+  #S#V^P@07<-IX4a`X18eB2OWbqyXaZ2Q7OBL? +B#V8vvqD2Z@BV*'#^* 2hg[IoLLCnh3L<vzVOb?7vyKa\4qI^hK7Q}T5^;=dZrfS*2O[Eqe MW 3  - BQ  :       +     ] k s  p TCtLM18irU l=_h1->-<"J IUGP%rWhLd[WQ(YLw?[_d9 8[OJF+f0 5?  L + l = I[K`sW  xPQ# V a  @- oB  l   0Q  [  " c^  u{ [MF . V 1 G  ~O )v u p  =  U !/ByzbMOP8gY9c3X3N4e ` +hgNr1P}q(5OE"]7|Fa%: EJzy`K!q};'/Ck&l'42wx_ { X U lEUj o !"hw#C0##|#9""c R98t  E (u ? 3DX q 72  o      6    0 U % '1-+e`!12rFG}a;.\1,qs9BcTC$|3VhA>_\ [`lVN*3KtdO޴2ݴ2r3[v 4{G]6 dZ  V <J { LXeu{!J +  o  W7  L    .Jt}=3Bg*@ Q >   E  _@  Q J4  Pc     Wy F   /  '  L#{mQn+5b'4B&3qnE<q)O5Ni E LC >):trZN~f߶xޖڂt#DV f\rh \}L74) Tf $ [ ,` wrz^r[td r W 9   P  x z M<UIf$$v O   8t  x m: 1 l] _ "    -+  :  +{FFk5\Afnu/WNlU@;>>H%6tTok_Q+UC j y+ + fd 6  9  S 8 , 8 y K NP<RJ ]s=vkJ  ' / F 1  wH(? k C@ m ( u !   W 2 N`  v _ N T=,574Q4BYxe[ 0#-zWXV\ߒEjlهzږ{9wazWzSeXL<X,   I . U   Y  0   { ^X?{>siqiXB Z S ~ f+ y n ' Dx G 7e   x  8  ; ?   d| `  lR[xoZtU$E)LvJ`BuY"?'B t ?j9iyAb#[l 6pJw & WGGf U \ ZT:f!"#fz{6J*zX`=-]p,5cU e A >q  2yX <  ?3 - DU,Y UV}eE`+ng]$B:v] 3C; ;NQZ'4lY6#L l e     ^ ,}  |  = 7 <3R2Yv 1U[*#; B R  ? i  ~   hC  7   B D= $dK$Cd cyKq6('p/i JKq}#?NVTbEjs)~FX=3{tG#IJ2u'T .#]= &q>d-\tG  CvisQ}{" PY/[a{UO&>27>m@X!uJ_6ufx`p#BqFh{OuJc^{*p-h~Hr~^ 3 ,CX>aw[sNZE\y\k|+3F)H>[ "T|B/ *@h""+lJ"`nm7[|f#]wfz"aZ8>2)K6Rn3UpY=m%"&Gx;"*X a=^ ZK"gYg03B4\h[<ohW7r1eWS[bT[_xrkkqlxy{a[QSVk1QP+3yxa++" a; ; ^= np!h7b-BBxaDZ `RDnPRg{PgS,\Ijy-VVn^{yo-r*VW` -*4 g#qY  WB 5hg YC 4HL ESukt5' n|;KEBwNy#=0U"J\&XCT 1`oIS;+hIB!;4FKa=gA? *nvRKD_'>DO8D& R R3:BBfg#=wz x!f%K^4Q"*j`g`hJy1<93^ hIu8`!A'41MWff7=n"Zduj^?;akgW+xbI ;v?1kOk?'B^9ei18-*cip!a`LxOnn,Zx2v VFIW9*^KoOBbSCjJx+3ca`V4{0`hy( WDF 0#h{gYF|LIKVP0S"hzVZOi{ Yy@;!ob ^vb, -Ax7!GFfyr7'?@n PAL:{ " f*:%sW ZXlTJK`**`If4)+ZjfR^Jxb0qJFF~?:*G Qn{KFjj0 R`\") 5 kqU^k-[4B)K[Ct6D\@AQ#bzKF~yj:_"a8SyyIPTe9naFW Qch;sE ,`)=*hy{8j["uy U 3*bhr9Q)]bJ*%v8P'rFFKqc6KBLXSJ )N;Euf|{A1A[n882e`$a%u<x}QjU2g%*kC6i yC*\Rx5y33 p  #0?PSko]nkn3#hk7dI+^ygH 91G8{Z?ru=OF4RKW WPg47@,+ v__,`pQ9z@Hu9W45X[}n'}Z<'r4EmxIgK  OFL~`B?{>>sS (KXB*P0X fQHYY~DkE(+:Tg\=NKth"NYry{Dp;T3FwlyLmW\X+r\%}Ho%0' !=Ls PSGP~f`+5Xou2Kn#(H| %`-P)O`~mu) hn1:#99+[`gpMy@ qgu("[-7 2;2 b^_,(H?o0 LSaX '#E+ rxMw?qZ%JIFN%$KaM:P7#V:1!5 DSLgp]}Y99'[ kR0~C\>=z(UH faT~z@ XXg#1JRK B uDi^ z7P_iKS49VVyAxrKoo$P ZH?a"o3Kc2$1 U2)&iG@PV *Y30j<RXE"H5ix:Z;$OIrX7 RbIY?6yg le5 "lP$W$e; <\i?UZa1lGo.c=g7'LHo"f+KK<ay}kWk#Fr# M(W=7Ev#Y-3)G^4g:,[bfwOB<ag`r VZ U/mn;bj$*8!Z'd? RKAe"saaD2 T1ip(O~iCJJB01w*_ ';VqA~wV^qI7g#u"V0dN8)E"4~PLy Xa!a(~8kQC*MvDZ zWuI}[zo}"Gy(3!\+;!@T19kG$c%SC9.=Zlw98  X-D+bT6mJl[!$ Jr1Pig9 !J 2SFO?(i*K$OP2WnTv[;2V%_mv* ^ >EN 8q#h6vusl=\ <!8>}  K Zp5G d     < J  L { E I  y I {  |  : G $" ay[ Ct   i d     h ) * E 1B-In'>Lb7kZ#  &'@ cU|Yif UnjTEa >QVuyT<5)8F!;&<=xB hV'#`ZWz5}i Yyk Mk z=pZ<%fd}0CHFEfkQ}L5^Cl_Z.1l~bqjB?c,q;YMB  IAc A  Y}Md !@!o"&#E$%w%>l%%%> #! ' iDh-d{F L s U f  j  6 H  c  R *.   LA- rQZvZHl?{X`NiL#Viw9ze d AD[K3Jt{f@R2pi_.u ?&; T{r]5r' )߸PJXb%&A@~ 2  d u Ns !#/%&}&Q&&&t%%Z$}"*   [ Y  ~6  E  "Y "j   K     }LgQM   Z   |%  _ F  J  )  v  4   Hz F t *KAE#xcf=a;7FH=Y., !wX9OD{ V\3H(&N? jXDߖ-#\ N=j%Lqs1e9{} k@ $  uxKXp     "X#C07HY.;R  ,  + S x " ;R  J  R x ;  d jc `f   d  '3   )  w X W}sK^AkmZ5~C  ErbeQuep\Ni}jUbKxf"9DXS5dڋם" p۫o^NnU-C26;~c  _S j 1( =T&9>qji6 ) B\ T   e <0   2 X # /  B `: _Dii\CE U Bg /  # +X C t, YOS 7qY9 HV,{2_?HL@22ZgV.ߝ'_*ԥթbdI߭%i8LLTi  7  u   N  Y zt  2JBkE'SIGh%K   q  = L P    r f 5 It  9  U  ldW@+ |F{G^]L|b<^qlu%"(y|xV%%ޑL۪$ڋr z G0D e(\Y6 & e PFyf;e\2p|UMK6   & " S ^ ' xr z wzZ,$nS>cx$>+ _8 Qh%Zg~c*" O'ruL>tuLnHO4 - -%"Mj w>~|v08~v.,+k?7 HH=6#-0(28;OIr8l"xQ|1G{Fv1U/5U[X\ou ())a8ahf<='XUNP=K=hfvEc-33Uz; RQhf=?Qmz:sO@zB Sa57]Qhi7a -ES]uPZPKjRFq F'.9C/n}Qrl}ovW@7C~HMJR?E}$F-cG>  {:z:Cc K{3:sDf9MTG_<M !G`' oigvF=*'' @8nxbp`xzY#N`*CQx~#o L"yi7kCB^Q[WrJ{~ \1o\[ZK=55 s}PYTw2QCcz`QWS9F2XH%+ ('!Q_o({`88 YZ:^?CUY9= ~n_(&-Gy1F%XD^evw)6HCWx8b^VEWYe3(:Q.h>bwp -*RRgO`knjzrxxy? O~k,guE9 2=?JJaGx9YKAN";O;c/xU#"GS/^6O6^`=V!|r_=@SUYKqdH*="H |gNiNKGf-wh9FnXIYY"g7{`O4^RDnjL7F `2OVr*~084A91 F1iqPS 0(!!! 'gCIv%T`T?F24JvQ<1nVG!4Ch8JInoBD3;zq@a2e3Tk?^#J^hC-Z{oapQiJy @5h=J>.b,iaKy\l>hM[XB%)Hu ]Rt)}heT}[e{Me2)c{rv?DN{fwcK5NWo\iGaM 2;8BQ" l/;aJ2,$`!v5{~~qQ3C gZ+q04K2-(3igOYXD C9V _!A!f9Vaf(>#!d]T,0uTf[E6 -[z(E'@^qtc\Mo|/.\CF@"%c#`RYGbNRi|dRy 03g>o|unq~Nu 92Y O@gP4ZiJe\Hy3AVJ$ Vb?!ILFiHn[Ct91p|j[Oye24~^nrhW~X 7WaC \RKfi ,;iq,qkSHB,JaeiO,8019@PO$@p_Mz= v*F%P3yLP9P02CkY#<y9 ![nz0 1kjQuu4 ` uVZ\gYS?#18'h`g9~n8pSP0kg-D\``H-g Hg7z$i*z+41oM^0 Vyya9Dyspok3`=%=2% f"=3KWo5B$  ,@;rhP  a .X.rKGIySrk4qbLo}Zi4^ y' ^oi2a iVBV3;uJ8ugq-vnf0*IY9~ncbnhnK+4yVWVPJ3f 2C8B"$.KKPXbbwzrSI'!z -{J(Z#Qk*$< g YB3znp',"t,aVVwL]''q*kOO'K, `%:= j\ {cc,7`3x 0-RV4Gw<++Ikpnt 1?%aC~B[O1Q7U :U-#qAu7)W*^;oBR 1%^BxCK)6d:Xf#fm_I`KoZSa8z Woxjj`[YH@CnK"J Km3V/K(K "D 6y%z#@63i~#~ qyRVXX08j J*Y1$@OV9 ^P7C,2- ^!fy<Qq#H!4*Soo$yj+71A$AvH0k(h!7vLkg^@ZFZJa `%JJg$e@iXIxnnennL#}(b(SkS,Q";@2un".} }raeXXSk-@vV;"%%}rnyg(@$QVbF^n1^x @942*9Xn?Lr 4<u21^7?4k'X0byahH?h7q 1GY}:~'Zo8bZ@hWln!C=7((PW;./ AUq:R-l3r-z\A5< ;0zeb]u?N/]U61<kTr$3 8bQ8\=T uK | Q u    WRC#IiWFXNZuT  K G  u  P}+JD3lQpc + jN[O?+VFNDR^Pgt'bZi2x Gx!Օ0ՙֵۤ N^<6B2r C ] u5  O    W  (r  m    , ]i c }   \`A=?ck7?SC$Pz  M&0q6TW^Vv͇sܡ(a[4:>1]@~HJ dWcN]  A   98   n/  {YgX7GuAfA $} \J H !#g ? _ Q  r xm8=)z"ma/>4j %  z M ch@Ts Y%ApD$ Exm9N7z=OIO^P 8bx?jB{oҍς߶@PJMߙmqaތT HX]3X1],% 9 D H  ZBOJi M Z  ] A  =}Rmo   T   C Je Hf:x  EQ)G9\  2J B AN @ h Gj S!7NV0@;jGg\x"tKݾ4۬.هl}ھ'W8'v+ czI$2oU>FUk^   D   u  !   52Q&7="[i4^ ;B  + o > +=vpp/<= 0 R V,   a  3257Weg_UyD>0.c{߈wOqLbbKLA?H`'Gc I  S "i ? Y ]  Yq  : b e  H 2   m X o , *  'JRpuf~8E0*xOGd,y*gHxsge8K5{./F&sKjT)mw9Pct"tS| A a; kT </XN#0#cK6Y>$ lyG.;Vy!HWKVLtNN3d>4)[274V MG>zj!mAi N#= /w-HFC{ -$[w.a439pM]s>HexNkR,1!znZMnzHr0P# h{*Wqwj0A#(f`/d5_f'WWW8gl_[ ?0'eD4 !JSeZzJgGy}%P5c~ E zmz ^$  aeqvqwza o[ryPrlKN)~=JzswJw$[ i{ 2\T5nz9'OH=!")lN@@i}&58 5C6<ZlT]u^]#O)(#@0AJO_!A@jQ])[Fx`gqqL!e;}8WpIcW=I[Cz=3h;;_ w7NaGLSEu1>rnLlctuf6IB/f'.nIEpE1d_Mw- EHP}[oh<W  sCP[0vJ[c&`?V`)r4$;W4}c|oSMxCT}+"kkuET}C`=~tn~YJ wKEN]<:%+CAA{%[jDq>T=" kQ=@_*+o.u*zCI1!!;05a"MBb~c_P f`Y ?c?[Lp_._GEz"=>_zqRgB *;g_,j m"j%z4wOCqq=ECJC(~K:99C mpa ~W"^_I?_A=Dz\iP?XGXetyP}CugJ!5P]ben.+Su62?"1 c6hiFh>OUiu gi[[|*48hqrPSL^,'kI+bSabbFz4+uev(yuXgSQS3P"9LDai+{S9 iqMZ;Z% Q4#?qk,~?V% wYV[A`0:2E6NnjxQK@|dE7OG###Xu'z %S3InF-iZg#<(<h "hiM<Bk {9jcR> 6$Dc9 l&82!*  Tc;=IDMh9Jk=$ nn+ ?yP C2[<opZk'D !b[S o$vzuW ++5 G3y1,MyC3x+WM_wryH?-^.X$! '*ab9 (Pa#q4xj?Fjk^?2Vybah C1y[@7-xx+Ve2 qk^; + aX"$IKv%enx9*V(ov!8S`43 ~  IBV| X` u1 V$ aa7x:Zk4FF2a1Cz#WF+zoO Cu}Lg'*4VB4g12'L`xP; krBc({u`vogW~kSrB`A)  |yFgb"w`x~JU n"cNp S8^DnukLn2z8an} Qg(S0?h8ha9@a20#W$QF?L2 7hka *-HL4o r{08B[ 0hS {a9x8IC1ZA~0j7- @B1 !Xi'?J(QLB0#J^xzazaroZ\+$\G..ZBz$\ho eaPLX"2C+9 * !9i}?Ia)j#I -RVK kv;Z8 @?SCrPSQ1HC+$(# -*7}SHJO0@'oWg CTTwOH 8vPWkB?$C CSqc=Vk,"vx%4##yhP^"8\3Yu%f4= rH 'ch`SjkagFq^F1(jq8IO-OO9Q0aBX1kQ78J9[niekOvr;-vVyy^ -$^ !kn~4\%AIBZ?y)nOA?3o]x#b_?K;|Uu1A3 d~b~|X]AEqgp `hrV0x{??Ff`^g 4'IOLSrc9<Z$ RoKPF1 oWOB %L5 ّvքT܆r܅Ԓ7ܡ"Y۪?߂&y)[@ , 0  E ac3"p`R@7#Zwr3D&(LQuOyVO/w:v"  < ) _  8  w  r Y  B N  2(  K :` 3 0  ^ J Av     L R R} {>,K {6{rjc^WOA~7y0{*{)~'vvqr{xogaZWSPLKIIHKKIFBDDHDBABHIDH"L*K,F#A;1' LK* vP<k!*(*8CDMXi {zw oXD3\=* okbZbqvuvxukebu[gVXI@2'  ukg`SIA3u%r y%v1q,jVKHB3 ug[]XU~R_x *%KKnv $1?@QLe`}u}xo^XB$ ugK3#r o r ~?q1-bZ%Gf=glT5kQ;,h@vnaWI0- k\O:#qcRA3t%`H )zcmAQ+yFoeWT^w/},+fY'jQHq*b 2AWqzlwN\+C1*{zkfXJII;=858B931+q`vQX?4( xV8q`L1`>Y3T1 !.28VMnhyGVjbO,@iU}{jo]kAS)CC;8"   zzvy{ofTWWfy$lX8 zLq'k#@Y{28# /=mfX K1PSf$Pqa{'Vc*xpq| 4L #2$CHnr+ Qc,~K\ffrb=$fJ.xooL^@H1@;98;I2?+7VAg*=3d6pO,g'eWQap k2t ,^ oJnz  ,-Sr~. Qv,2v ilkb\D=r=[8P(=(  Le-1fw4 ~I!

    R1{>/ `s\(~r1"q3(oIgib $8%=L8D1B`aa+^?"wK9('vSd\hw}!Wr!V~ x;Av +@zu T3rKjr>_5]lG*kVB-9@1B19#=$y-+'$ $ ~ kP$eIp4w ?+$h=P2((DJH&:o.S&tRwV^_SyfPEIZS,rbsJ4kfz++cgW8vI@W~21vbTG1ZK\v} Cu0 k q+c2MCwMl+mT5m tJW \OqDHp>ouiK6.gO^ ;j(9i<[/E$T s3Fml(Pg.u&X,wCSq[;L YB:VU "AWiIu9,!h$f Z>]AoHq HdjM5_ ^yh x2dM)y;6 gf,B{</?>f0T6qBX=\TVC'pJJSPBKIV[U+~j>_e&pa?[9`"A!fnKVm2Zp*zhMaQ;/v!-c`f6l2Sl.`[i(RmDW'.Bt._`Jh_^@Sw-q_,z*H2x?PV>p.6$nr vD@ohF~2%z)uv+lKnjcxog$g$,jKi@ g Wp)H^R$w;;stxh6*nR@9jv$iEQEM=  %=@>,[q &_i;x#VIK:x*iQKs x2jk-a7%Z9,c&3>q#@;@= b ;[@}}(aJF{O [{Y~:\!# 34,e9 lK^j`1PQh[bHxYc{8W";gHLm{=6^Tgo9@L >(pq o:hO&g) j{e$c rgGTnD^N[9eoJ5~ <?B&{} G~<:qTBrl-q;~\PHVz>ec5=F[E"s{C<Y1p!zwCj,sQ<Naf%>Qmn}Q8iGn2!B/if~zGlP~[mP7KDE Zc^(v(MjpS`'gs+'i0+=_:W7'6QCc= x13\9pbgos>*X70vp 10q '-V9!b u( Z*u2!~_Vu[<0mH^ k\zdB'tObGV :(Q"D<QV[EUB"nO}>4{L+0b\PR667?0O\vqVYYAA"K8Cn>KZdfunINNha5s(Br.{MS>$qx_J hJ @PZKV+(Zd2#R$d|5"0h*xJ/5kZ/r38,"E2Z? wS3;XJV/S 1\Y @gpOY`0`?)|G#RQNuiKm[Y  F(%uL~AL4c 12(JHN$=@ AhVeDOj`r"8r7SynbC=,@~2:X:x;KjO~H8 pcNuG J-KfR{~0<V=6#`Z*VCJz+P$hr \]{r h2zzHp}`&{fh, ~Qrskjb7s;dT_G4eS@8wVQ})#kq0a "YB'v~0BP_,i>-h 3hr);[+}}L3VY^,(Pds(|? F5fufIc~ 5'r<!9%DX}xFK0adi 6%,E""d2r/Z!q~-oF"G)6@9BQzV3x<pc7f1:%VH1 wHO8 !)?-uRijKp"8RrPH"^ Z"u[9(#18!@LIxz*1 -?X2Js=ioC*8,2Qv^iJDjG^a;1o(oVBVWvR,B(3h9SSy;9 v<<C%[Bf\t+%xg1B-XF%ifG1=< V.2^`cW~An%or[bzw.J. KyEe X0/Y~SP|y#k?fYNvG\:O;,;1EH,' M<pGtaa]:DPqFLuOz@t#9"x)h9f`~Kn]8oxHu -Z^K8u d"@]``"pQAVR~nV?z*m3WP'F@ ~7O KJ?P<@YCZRIM  .Zqq^rux0l$CG 57J84V %v*K7I^B~Qkg*^g0buBSWoa0'2;O"(v"z T(P5ib.}25Ob^ ^$2i+*0\iI2J* 10ekJ41*#;;g|`Z0u8)YY;YOJvtr":O8*Yo)~)~"hI8K9@'3! *Boh(fWQ orKf5B=JGTps3vZD_K5y8bblvf<3X \t/>\33 {.$K#0vQ?H P +$!O@07;FqA*OQntKbRi:F"3A\XB= )g `J=pH(@Q/wof 71iHh 6|G'ako` Chg2Tp5y H2=]w{<N,=EaM[GQ\Jlh{=P (2,3 9 z.   y <h8ibx$ +78r[zCY,IOHwH}]TgI> UO=[HR |T: {}_o8}@w:zjQsiI5Z9K+ eIzJu DMT wb@ 9S@  zn8(e} i + kI  qH %0A;=a- 3)iCxJnVK~_pd~O `AQ ]?_ 2N-W=nzcPW#Xa 6><kk=C. *!f8#_;.1WKyPe=k@Gy>JqchWKJQ{X'7KH#q7 RFDkA SyLj`h#D,]:)O_3~nHqQ J9!M<vw8LB! u0;o zg.< @I$wp@U_kz cXru^z2 # # y)bQ\% H3hY83~pbum= ?P: }y(+\<Weaycq0rv;V4'SVqhy$C(Pqh?Hn~'n7-{ Bh)K;**VRKOB:'-D;n |3K0HR B' c"~\L3 6#DVO#og4- DgS`Yv fI*ZxcoLq # ++?'1 #r(y7ZP#PF $($*!Z($W%R)HjAn3L'Oj(H'Z-BxDPq<jI[IP n@-~# HZ$ K^;; {o~r=1v1VOox{q^K3uH\%CY?bW)go}Y?$= % z02{$4Zk\mDI'^;`y |  vh ^   W [zc \vB(m%g`&f/y Nm+gyx' IWn Ewp;C+J+ p@xFr@y?m?s\9W@dX+#Dpp,6].3-@r<6.wm]YUgbJ[u6,A$?MJRZv /   R _ n u Xi ck AQ (J  A <H}=sW*Y9r$WI " " 1 G  6) \ U }  yw $-d e>mC,) Z,Y}L>.,6Jg#0N*@2],r"k9 Ow  rAJ}ooWkm$Cp)},,:H<Jm6~S6"n)xqG`'lq4YA1[B?O{ O%@k$UUJ4G1/`Nd'Qy8t,.O H[yy~X2 Y } /|  / g:A:[NFh  ^}Bv: @g)w1KKU3yG(\&.,8jl&LU[=$>x 9  _ l ?    -   RU85SPnon;&fdG a id(tUe|W1!v~2rBmVyqF\zO 5A $^ 3p  6 \  J $ _3 C h\#=2V X *P#K:^AA/ ;Iw09I{:pX6E~(P3{!(=g IF-!D  f ! 4 f  f  J $ " :  aQTGJw}yT<X"B ^HK?cjxlq Rw!&]Vi#kaql_3\TO p   Ph /   ). L`d5Ytw[WG zvn{`*uH`  x K(;S'AAca [ %  0   n A   U] ! C#b^oI IEJ%%0SaL-p?4LI <"Vu33\E)n s <  Rj  2- gx ~ [\ r*   ~ zCM">Ki;J}na$#9nCn|>IT[.fc.,UrN jr+ gKa-CM /5 # -  @ ne 7G   d &Bgx <x=7 u. wYzW3i]e;sj&Zs8OyQzOR L3v3{L"<7\CBo]~\&z"o#\k R|8YB28id h,o1#Xr}lX3# kF F !} { i  - w J Gh ?f 2 o5m{MZ.\@L2u fm=i*UV6A-(NGl 6 mWBT o{k,@  f  M_ 6 <H{Je|=w>CD;0|W",mz&_Om]htGCSy4b/Aifo;XRAA1Wu/E_# NNEn$M$P]<8NY='-@kibgvIZ zo\jVC1Wv0Xq7(77Q;( 1+Hnvb;8y2eMhf'r#92+#!a'9H4;IL k *+q(Sy. sMQXT@z*a-vr`s]\$B+(wCP[CZ!G;"$ 2pGTs\li~"wr<H[qIb~"gI0rV#Egp>-_v !s we~yWedNVIJQj\`3yH K"h=veoW`err+ V9qxP 9=5nZT [;Ih8uP-i9Ho`R4?`;x0`$y+^B$$o} "C%4!2*}Fzeq([}4qFq[vn9<ac(L'HCvz =VnXXuv'PqBo^F[PwhoH @z,!  4qg( o?\h4DWgQ\r[WxHVWZ?f#\7SCvj;I~i`G54D~+{X p 7    h wI   (c  []x}K<d *x2v</9-}m^G(mR!mC~l J9BrDAnIHKxYylhdr#z . c9%)TzbzSHYqWIh{:@ 3#cC<-ykn( p,>e?|X' z2n5   rAJ a   2 ,    P Z @HLBF4s\   Vp ^ f    hn  W_z5I D 3 }) 4  3O  ? w~A.;O/hi>`n?xp6o'_g~JYL07g`\ *NHh~[gP:bj6 #H~mh! .. >  QwV[>g  2 H k UKuW3, *TZ8:=/Ed L c   9  {   )  J)  Dm4 q{A{pCwhA3jCI_8!G@#hMt7Z|>^L)7q=jvh 5j{>G]QLkeWZQjLHguh:YK\ e  *i #<V-Y&XnLA: ?   " . yz9THA3rU &   # 6n  0 T l  F  Y/ wk  q _    wd_YQ$)`:Pn !dy 1y! Mx!Fd3"$   J ] 4q ) e [ *X  | r  .~ E tx W[T?D2g]TwlvFU!)`ZL0 T'ATF-L/PSWXA*F?*mD3i!z<7Y[ L#dFV^gU7*i S e C >  5 7u  P  mp B  "  W ?)*3J=tJ\h+8Qp;z;WmH2[N\6a_Q\b -Ja y[#y_RzQGb8jY;jdcodvr"r&a1zli  2&o7R_j]{QANp0:b,H u `L\J{,JU>0+ cedMo}2 | o- Tck?'Ef_aHWz'oSx7^KP/H_?! 4g@7aki2;QKa+8^XQC %%+k3 zk 9 srF|rT$L^vF %|F'VVRm[ixO>e;4&,_PnH*%K ^~ hEj!6@Gn7R9@qJ)K { cH 1SV@QGf5E&ppXiTh2!=   DwU[b:JgQyvE?!A"1k f&>';v/ 2,-M6c7E>k`0'*LglF=T=SIS) MlQ[8KkJ a3pO[/}WJ@['!e+@[GoaXhsRUL % L'Kqhoga0+o2 jvyv'S71 =I0uuv"yqk "%8gvk 78i4H9zq[`3eO<Q^4+XgJ9KCsX;z;Ia1>~Xw=mUC2$O_ IX[J!o7Pw@sN?&v?+)6GdOE3!2;0gJi A^ 9Eg Uy{R< U{ /R9 (2/:&450M7L@jN+VYZFC X/-y[Rpx0v 0`uDIRHIP1Vyqan<  N : < ? K ' Y  8Q / CAp4|Cdf  |0OGH 'WRDh O4kYhD^;)HwfgC a# qOsv`N92O{QaI)=X/ aM_^.X!FCL!!&/4ifBV%W.b _d^`Da} 0>='\vJ44_jsJ |A dKVdt\km6SGS(<h~=IBWgA=DVvX up4< z2vxfHW4 P;uEK4Z 0;>^dZmq+f*q VF.a+Et:M1A"%.L]M^R H{5   J j z [ '  ^ S S; 5<$\tfiL,e\/hP$B* [k#u0Nx1H1|eT`l9Ti[IABK 69t,fH<78jSSY 9x529 Bu8$,)XY.0f:b7eU3c]HXb]Aji3f'Kg:U.y-#i[>GH] 2iDyJIknu]UHxRaOHx'Jk0l]wkZheu*G[x1Wrs}MKX {^R6]p>yG`I:7Q%FrE X76e"@7)  KD}b(Dk!gq?E #b\]z[`i/6~}d,^ r?r@in RK J3W)S- j'_-smY" Yo[;c ;I+{r)=G < _#@ qiHpumjdx0WAk^{BH; ztVVV&3 ~m{[^~0\/5CL` vzt UPPh0Xm:~ #%@~h<( G@{$'+n;iP ={*W$q!v=;V }Q3|{[GX}pzU-O{"q(<[9[M[W=on4\ON`([/Q rl5 DZIO A'DBWqv;Hqx#-W+*lS]9yeqtR3 zM;CS_aC9[F=kR,W6'2U"HZ (sm eT,37B;&o'nUem_Jng AvIBn =,i )Mvn8\Q-imq5RP`xjCg9V`rigb]R?J1VJg6N lX1Z[y+[k!iHB#1j7h;h70 1JDVv @o+%fvT%+fC1x$a?n$Lq*v/Q]e0I-s} "p{,g;([L X[_Bs{v{y8J  g7r%c*_@[@+ (Jsq-@"sw9|Q _%IEU3'h#; <j/4\k`8WutRY}|SH N6P `a$1D\U{&4-dcw+ i@@\9m!;N'EmA=9i):_TBQ F8=D+}";3$6\J '+jF0aEojX451m.UG_R"r IsL@$t+ CPc~O|B7Fv?:L'CZ7NS-6Fhi/DIm~F[iD wJS!rZx :Lc,W%AlLn3~) |Q|8\}B?AE}T#yBuhTMBPG2zg[:HzX^#)z>"V *Xb|:{@Z^7Qjmi(z+(zga90wb]Yu( [uX2XC;X8BZK!QahOR (y~eY!}_W!CenzdzZ[yUsdzdi!rg Wk!G{Ez:3!AuG+$iC8[`7?0'Q3,1z2g,}ZMn0`Vu,z2azQc!,zqIn!vg~v=TB(M25:.Aw%{,R/<aD$Qq?1$!\OXm=6pl?+|>-1nCy}`B5j$Xh2[BZ)p^x!&X;X + 8Y1a@3S NFZu:8x4,L?VY)cu1^xg`S28W@c Uab^m L2^!lS D lP!s(iP_s}yKT!@w-Pn#!9Ws(33<t v&PU0+_ >' 8I%;AxsGAcH?"-k>Rv#]n4kL@aLa83^ C1; ruz)Gjoj0`wtx:V`Lojn\H- %`B*IXWL`XV^yH( F1CV`2qu ,yVB@Ho ruhr-L3oJC}kC (<WIPT`vuccsVQ?vhIb2\lTJfk[vcV*S~R\V= FBF-+$JfR%jxxloejivHqJu9j IRZv`# p #QIz[~ T:as!  Xb~Qy;,$hvVz;B?PJ2  yk~j\S4 :1;ugBu1F( 33(jVh  V~ZS{af!-O0 $ ;~$q[\WIQ=CB F`? IC41;q_ndDff7K - 8:5KvGut_lOpmd Hitx`FQ (xkk~qFg g SoBKP-1Z*IA  83;HKIVuhcr\7~SkI~acru(392/+[P2cgnhu9g9n_h{J|Qc@?YAFZa 8 j~L?ojzIKHxHuJM %XiyQaOKXxJcB6.;%pf%=C=CBf=T47KH 8"^qi*3Fo5K:3c>x|.KT2{%Xo_o"n+=MTeh@ %N:Z^> 1{dnyf)9LFq\ % <\ \ @ $ C " ,J8.,!qP!o &e  e e T44&qh+3"[~ccs'2m_# SmFS)V;)xAv^  Dztm,:nld/W}!z8&@lDhkMri-9`h*, 0%qn9\.:SCqrRgS7e%* QcWuCcf9,?R=N!= Nat3 5[M#u /_Ml{]AA)s*TQ g)@N/+bZ yY ^ Y*   n  O @ q]Xn:=t"NQdc6a}:<NXwL>/I*Iv;,A+m<*F8-]jI*a}9jaD9ZbJ(Pa5 #G Lc Y U/Qkdho'UdQGG{#~3Q    ]'#?$ A6 +v#p!Xx^w[ -Sa$-]kN. m0w`VTqKHck CjD,>hz Hecwy)FD)n-)Z Z{%3 3g{*[T9)sz.o, ,D5<*V a!7O*Oo?k-hI1cX#5X9vU8niSHLD)aA4Baxu!94#\ XFr:'t \h ;{BW [IU3OJ]t29rALI\0))p%[!&y@ :N>]UnqAis1fG,yi &9K90NKQ\} jw'kAygV-k<@?9zuQ;<I?+'o^*-`-u oyv!J"!zDI2}lDbsKI{W+ 38;95wD<@V P}JS1bqoP@1LP<*^hBfIqvkko 3rA1 )znXK7P;:" =Lk=I8yZo\q1D=LY7*-FnPW:417QZ =: cFh [XIB;2-kQi* ""@XZ^Iy,}9%`V@W7O2P*nk# +h QD;oBAS{9jRqf7u#mA# @t=e-Y]CW_2A: 6n1RFzXFB<v#B+'v\O0uF4Z4K@3H^hr*S0x` 49S@8J%@bu[8XCa} .BWa8qT^Q#S;HV:u^'u#W{*aXo}}$!Qn B0 $R"V vcDuBS F= :^*I^^ q ?%RAg7KWa(($lDfI2;Bz~,S 3!w_;$={DTsSZICuZP+T9Gg W8? ?S2` i4v+C  [ab#C;LBn9XJ[yFB,f{c`;)VO ^ ?jpX9!t~vp%f8z7nDu`dm0xrS8;fIh-Z8*1^ 8z\u$X ,HK13ZrbP1Q4b$+ *QD+<4D^)L'3r~'k}!Zb!p9YhPRsqfsI{V7y!BAOyxLf-0f&veR=y-*7O[V^'1w(I6@>Ugv;:kAvNKyNMu'T622!Oh2[\L[*,LB!$\(kFBKK KqHLBYj (?X 8q;aL2qxKQE=z/fi]pN|V0Hz*a0Yo*P{+"a*!-u#{9Ey/K=S= =qQY`]Vd*]t|i_R<60!EMt-?3IEwb =s[ I "N>pp5:fL>E :3AQs0QhB$0H^'KOoyjZW"#F xY^j+{7uej4] F},Sy oe:u ^t+|DF3b_E c *71T     } 5 0C3c!'HNTc1kXE zCh<D)kW~s\~=i+n0vJePCa ?iXT(Pf }+|L3wU_[;f$X)xz;Oq%}.D [/6+dlMU.~@jp`Q9qAm){[|T(JxF*N97 5 ] , * 6 wP |6 g /  \d $ C<SqT@C9Z<4Y{y!9-OVX(2=FuNK)J9%AWkT/6TWNe]12 4I 'dG#F8BP/V $kkJ{$$Gu{b k}Xr\Z%*a #Z_GT:YGd/a3At(w4 -J6<,BEh0  K  #  $ gH  Si` p  b Z  Li $( r>!%<v$k@!a94XrKoVV \h)hop/<X8y7(n\< LFcv2 Vu;[lp&.dP-{NENH,=}:O !V"K9:xEPlvPM=p7a=~~~Hol*  `  Q. aM 6 J 3  0  i [  b mh ^ +f  qA  (RK"/1$[OopjTb=Qw2'OKwr21-oqGhdUMH*>Oz7 SE& LUviN?rLs6ZV^$DQ X1;%T:jD>bf4O4r0" ^  Nb,Y G o < `< <  Y~ ] w wZ +%  BQ +p Iu >}  +  sQ m _ 2 < -+ $EwOCYb5u FEi 9_L?4W_5 J k_T)q,22S ;xNgl*[Q^ZpEx2t! $TJ3..v? -U"Oj^\.iG)^'3CE/0Fc>KN"yYRN~N8.TeO Q+{EY7)4 + ^  $ + . T !y | ua $SioD;mmGZq^\.`l9@U?55l(G3Lpy+#L(yc&3H|:0rAAD8&v22n!!xP8-3[GI_E{]+9tSZVUH  W`yb| U|!`>{De)kY43edwC.\gSe?943jy!0U~@AXFMJTlG5K1dkH?:6"FB8T}HA|hf!`S[/9l="-r2^0 tt=! ;1{bK]S X)PC7JU!@Bdis04wn'uzj KG*Me<T56MFL?`WG.GZSi02j oKVWW-)uL4>]?ZZVroC }\)*@    {n'/~ 2i6fs~x;$k 72 09a(gPryxh2ghGwGC9#vv~B=f^BcuuxSaVf2Z[5kZJ7JVnn<S$ ,*WnPIi'`-8JhrnL}k  3.sCyh{kf}G8$B2qPuHa^Oc9",4R#7PvW?h}PQ[ }nZ+O}u}F8FkgixF{V4fvL04:'PH?IY ;*,8^ZYh{YVDO~Z]Du=nAFnc[onYBLI|d%K`u\i#% q zjqp0dtKj'n @C^@70v!S`<$PFr#^FnFX$<4124}!y +b  C2v(. B+[h$BzZMF(vWg"izW8 1"0vggxyr*=BPhW^D{1r^yhaA) uRSA gkR%kcqqcg\k` RoP)DBWH- DL`ro~rv~7HVV`nyub J2K+1,5J.13X*f+Ja<0!rZPv@xX1H(@O?`-n<Quq}u^7  yK aZ'`7aRB;::"%)77#)f,FRRZH O ?9Qk9" .kJ;_o(@$+ [ fBCGbS91(2;k;oXor(zfBp=%xL yGs c(voZOyLC7Q#H+!L9O@f71'yY: #0,-DtnI%8? a,7gud WWf-"P{-x-o-v1ko'2@@2}!r.H *Ou`rJzBC y}r}a(L$W?oaV? u`H8vFr oq8$vgLaPk ^F:D, "L W-`L o-o`?3v\+'!yr`Fu'f u\OP:P DV{x,Rac`a:\oy~xh2QJZyRo(F;2#`-Ba*@'^(* #+kCvIXibB J#L=a*xb494$n^=YY^1o4{xy ! @28(-o{Jnrrkg@1 F !rXZy#\$k1I!a^vVh#SV^o`F (4rL*P@qWx*f3imULWZ8WR8Z\c""H4 8A"K? mfLY HVN3ua-O;0n:?qWFf` ?;XB![ @X8V!$-<k +ukX,v\%,$aG i(*;eiW qVB #Qzo#iQPk`<-4''SF *yQxOg<^'7F7S`1ki8eJIgB$*O<Xq[0V1SS088L<40!9Hz!WoQy*Q2Q+iKwbgQXk#[ B474W#J SgIH'2;?{oj+ADn*`F~v``Y`VSg9oK\YhPff4eHCZ@iQo KGrH2-I6):Epb2z-XO S~_Rfh&D9,![_r ~{dE.@b:~8w=q<|~ ~CDMs1 c|~kh{VQwY =   ^2 G W5m#Y " ? J @ }   $ * X 6  D / gfU!lUT:hcJrKsGHAPeV !XxB\{{VOJ _9Lt)wav?f-%gyJYz!;Qf[|+1Y?Y":0b {hdE8( 6^Q.QVw< W G  #Cqf\*,   ]o  } m sM j)Aqy?]wNHT[sSk['DiD%R3YRXd,> Paiz;Q+I`tB'}.IUgw&~tvPk z;i%Z?@[6P[xlOoF}s5:= l90!"k.mx, |Kt@oQ1aJ${cFg{{'HPC^P5 E7Sw%=zo ]iLSr d  Y xe ;A-.<Y   H J \^ (ZYp\g#qL3MTd! BiNxJ/IEN!C1b1!Wv!CwHY*R4$33| mAE;V,SZEn4ZB"n*UipGO64% nsy_JO-:iH   F _   ;xM3)#%s(   Ef h {' ,    F  i T T eh km     [ =j 5H +   b e*[, OOb[;P3?qRr,R;lXX}&+-~G}C Rw0+hJ+y$ QXsO6nRE'B%JB SmBi1a"JQ'gYT 6y+ bQzH+ r'1^uC.R=+~: .jmpt9US/u9q+= K y.2+z47W}R8*g&u)c hX1*1=xlSyl>r.9boOJp3k%D'Z5)c$w$'e:S u ch   >=  ~ ~ !s !  N V 6 }m  *lK4-S2mTcq&3K  7 $ c   (    :  A"wy:`DK(!H%^"/Z=tNW1G;dA"FYYqU4OG wk CT%Y])\`T,7UU,WhNqVD?=;b;Nfw@xcz!z]eD6ZD4)if"kOOCg^fJ![l9O9u@ aFX)S~d_i3x9I[n17OH@O a/_ d   m ?   YW_LOam#};.8 pXT1442[*DUHUApY_-='fS+f=kB-N^ywd|Lzd}<90\6oRAn~{RaCvD9xLVAnVy4@YK`NT@__S]4f6%i6zxHZP?  0uw =O7` Tfx&$7L<>&<f}xXOO!-=qFMDZ}lS8Df`i{X@zrBB,=*{{MTF(b00x?B?jdeV1_8 [utKuyZ]'d?&ne5  &T_6Kw)Cm"H7h*SiMgs,MZcj{t #"NS?&HSAYePhl > AY.5Y;dAq$@c(\&b4V@tZR@=C-(Oq^{})d )8:qS{*0 +#O!J+okIK)IK*h0WkrG E6+jSxeyZH1tPBj_7EOVXR-Q 9B9!yeC($(+2A)XKp]|H@Vd3=?AAJ;U*/=?GW V'8.@4M8?6Z@i;;E4>8^;rvrG2l(l#=[3nWg!P<*'0Vyu}qzx;k2VPLaikhooqn;_3Sfw*ZBkykzocIKeaS +zBH}V^e 1agR@(`hl@p?^h.)}TQP\ m%Q"U8\syO=)Y:vXt1FabB"Wqo y"y(3 _@{{T`b HQ )H{3jJlA>=><<Dc<DoJ13%@i+uHO`+?(\= O*oHe`I1X( 23G<qL0PCIbnL}inVoWoayyg^o!-<;9H0`oa"72uPO1H iAXbDJ02biV~",B(z*g5 +%P2,WB Xh (+,* y_cf+ W4vH VO1Y-p9EJi23}/K wMi^_l_pc![uFYBFn y-R#7:Wg- ~r?;%H,;KZ7vLVHhnO-eq~'?* j+*4 #*+oa E.b8y60:DTm@K kXr}eW' * 4{Lt7Xm fgd[+v^}Dy{qOQ!t SL!&)Em5>x>R*}./=s[b jcC v#,y,k}7\hj']`P7~jp{lrbr/% 7URojmto|`zjh)L %}^=jJ^=C3&c9vI(kLyAC2YZ^h`, } l(@THq|`di#S?M vl!=K"U5miz 7BO{JkXhjr9qn31ihx' N   E ' , : G ?  F o ! i  2   p N0  !h t g>Y=F{OY6~[tzN6/ )w{Jizy2RQ*!Z3: pVJ6-V]VK11! +Y'kF Z+(L_J1^qn$FLM_ FvCt8^J~TkPlGE2A64kc! 3 . ZQAK;q     Wu   o f %0   [#9#)-( jwGuG:4YNY|S ?Y)JqoDt2k2zo\P`q"K}jolFQEHDA;xUv?]@$u}.MFhuxC._|Tl@T+N(=e4m^Fh^~u!~PKK1<5 {=&-:fAk\]_S ]k  W } ty m s M O  = y } wI $ l|xo.f{m?Ft k$V<{-HP[y;92 0 *1-8x3h0;EN_-fEhTmm4UAEfQi@[=F-gqZbz+#*N:}Xz.+oZsl'#KcZ < CB*R2;Ry  + B6 u  N  c{ 7bD^%W<C$8!] cp <cV']96Z#]{bC(W2@- g4@ AX]-l}x`Z:(6A>L,:`#jUcb<5KyW01`7jF'~S*2K^EN9dK.EGKeU_60ij6ArmFN\(i0.;:yy7 uB+XBu_' B=ru+v30)W4'-H . }2q XH U - j   O4  j ZD A Y Bo  ?     8R   m    /D2zc xr S/5{W+vl%?!i^-y!1fLx]VLe+V1 #5 q.xoK %o;J- O>&~4j6{zI@y}k'}v1 \-,(*bZ LQ @   `X ~  lR9 {,w [   ?  HO,9M6_?OH3mq&,S2xLxLEI~nS@74O a|c.,%7 T]Vy \@{{)A;]qaX:pIXp,?I.tKj,KyH:Xw]+Y~Bmi8f5z6n!!b(P/O 2  i 3=D>a $ |J T! T .&WS"j { Y $i 3  z b Oz 7q +  l E  B /sOGSN7 H$OA=C}M~3./jZU:+4Hx ?hNy|CYzK<$W!ZDeHJaW6?s$~5c8;N]>b<wKzAYxh.<8yY>W<v2-{MK s FBL< 5h\kq[ [=Rls~iq7 ]tf/wXv oaqZGO{'FbfiXL]IYy=uo<@  6 m 7      h {,  o_  M1:^ioKpS n  8  5 pr  F ~ y n L    wSc"=-BK o`' D-dG+g) i]ouD0;x7)()+TJ>{6wf?) ZEahk4u\c%cYtXTi2e[ N5>*Tn k^(@NZ%VZO. U4F)d9Z]4$z7eMqjCE|YH:h|.EnX?z,cK_00O`1 Z?$<uZ=l]9  3-_mRec0Q,%*O&KRc. 3IS "yMPOx [HV(c2 "JOC1~JoOAI~4(nr"*P0oID8f1W~#% t]y-F.f jpd7^<2ylTP@?6(L5([[i%t@ NTmPsF)7k jWin20ZLo?8<$ h :g[x`0,\E_kw|r&>+U5@4@$h.q7N) :&% wZ:>Y7}B>4K/{~pJY=%w&5*ysahzyOLvk0*B0B28* HP?g- rovx^;# }4a`H[1y.B%\c{X\ikBb(i1CP ss(hk4i}y .b"p5yC[kwZG{=pKJ( *; 2I8 r 3Q(1WOQIn@;\b4yb}Qe-<# xo ygxV4*L;jr!JO# ub [VouC[PqhhvhqqubFL9I; zxOyQjxuSr(%FY34SvZDWVq3zL_FmH78VYqILB0B)'*%8BSR^I`gjcyhY?Yho^xvjgLII''3-# `S ^=4)xf~S;`Fr)~,xRc<; LX-i% 3;5Q8w~ 6-"nhLeP*Kz a X*= <-P`8uXxo;$'~?=\YF o a%Yw|uwwG!G-{G9^oQ,"8=iNQph("bD8`66_L{2h]|@-[\/zDc;<iCeXLHS8?;O`-[ vKvL4"z6 $-*M) m5Q3" rztkR;B NAHS"=RxxBwc}]c/9S_Ss96f0b B(d8gae}IE`7oo-W=3cyD=(eUGqB@.9QRcJ2Diw"(s!wYzYbF\5&-o5m -`=_*0",H$a`Z-@)0RaVm,S!U(<# T{Ia.=~5 Sy> 1F (E8$.0 `+@ ,E$'E5@>6/;&WJ !^3`YIcA=f`shnJ n+[S{g$4Seg-P M 8  &8 `m            G ?  &N<}Jhm~Cc@=XRXH+ I 3PKG2=F@#X@btv4U%zYuluzd11;?]1!@FGFJ[ yHk^ D1>[qiVAq0{9l6CV6C6t~wlQ/XTM ny3/ 6 \  y, q F r Q #  1# qG oD ?X 9r 9g  R '  D~ 5 )cQ;J$lpw}DJ*9 {N&6a$l+*}I V7u6fR,*),, (q>4d&Ks[Qr*e;?c+f Y5(Y9v!FM_-|RyigNcl/(q+hy'. nZU>98`x T J  G ] XJ v    _J  D TOY>ED z%N:?N6mN l,I@$ g X`4Kz=|+L-L>>4 s6DAK%2,_Mpvh_dC:4 <3]'Nv`)2tAo di=DG>9|hk2J_Y| J f  w< q  . 0 8   d @ ~,   V~%SxC zy4-p)MlO=!/n[r<o-;1~h~`jaN=5P.gK#]I<*}sOEr*~l. l6EJp} ;rro y3v'5WIrn`5dn Wc?p UT 2'@Z\3dPfW3D{J8ws a Mgz, 5 h5 !EqR-|,enhlXz'.o CkOM_,1edCF6yH(jtSY5n pJ:89 ]>gA^:L< u`p &5  i   @s X:'/:o ;] - u o3 leZ 6 a  o O # KS8Ugm X Jl IH3W{6Y7 I*=<47e%J *  71e&}6n?3   :  4 ^ s p wIok[ A3)/WhZ]U # H  $?[SVs9EuHZ8h`".Ox4:= Dkh[X_y5*42v+QhN gub9T`'),7ZcTIDv+;N L ac)vDnvLbP!K}o:2".?ozf>/}8A  ~& i  A  O l5  Y\]r=( J+O      m&  I  B3+6 K  D   7 t ) G ( f M XceJ Cr% 2[F-Qol . nzwB\7@eE62{9P~ 0X&Z2E*r<-!;:un(d} p     B   M .lX r + [  PM<7 $7x#MR* Fn q) +|  Q  hrT~ %M 2I*_#FF{g5P [|qb SZR0qn jN9:#C]A0eg #&G 4Lq+,q8,+#_+wDK/>4BA T Jwc=K    4 6   Z ' . 'V V+ T@c  Z _ Z / v   +A {{{ho  U  b2YTqhqua*JIvK#p~cO e_i),xO<=kf| 8y ~ 93/]yF$G9D~Y">P h-nk%}TN XLn@M@^K}okq h/G/e<jDw+]R8SI&~8*frca7l,"XW4H : RpH{! o%Z\{0b W,b<" Y* ]%d-q"*y=v#9g8-$CKDVK( z Cb&_dN@=5D HiH K*2i?f!"@"q:7a,! !e)1rc&c--TlP 3Y3^';^IZc-yS54YC|ItBMj/@%FQ`!\V\H~zdNOW=axor4vj;J7cSM^<2P$}; Z$v$ *xZ\-==K@.<u#@rggv! 7EQ_Ht8O$O {< ]lN>JiEuTEVWYKW>gsKU#/M J^Bi(Z3A`./_}!!(|T1;.8) 7ia%c=9**]X7_+ZvZ9aO(~2 Q)`E7E7-A!)R$&=kM<23?'UF6G;84bNW |gey56PwfG" } IXp{h^[l[t_'AkLS3n :Oh$SQ7{1b7SVyy_-yS_+o $rsv+$N>>9&`\p9$6}[{}}D>)%5 X<<D9[K+ T3;/*: Xz#igTxy+/ " ^4H:w>0bd_H_a{F(R{8_?VOCA>;qnI'K I# _V# jO~dYO~ #Vg*f"t7*w~7P;$jFFHYg'oov8M^8 avaHKK#v3$sG<~ 1f $qo0k0-7@f_X=*B,4-nH X[Q.I5Ia~(@$YqqfaZjn;Qjn)ykDrJ3B'1?yT.RGngr$ynXpQ^h@T>HC<B9:U5lg%y =[~/9q4^92Lxg<CMVH(ac x1wh2)J7(V{J>j9lE$,!gaO nc 8PFo@z]e,lEnTeaz)Y9qEx;S3ETS$K <';h egEJ[HQL"IpX&S_f7OSja):m # 4 J ' m d  pIx#lD2f2=z \)k8` LV IFx PFEerj?sHH>x4m8!bZ?uj PX])V3-Mpj Z:zcDTxQ',]rwY:/VRB.l7kS;\R"XYr h {){@ N    ]  { M   c 9# g z ] r C k~)w 3[*Hxuc:Kq-Ifcw>1dhL)HOe ^kA>.JY[kQx 6oyyfDODb7qKYZQ;{IZcJ*Vx4"x\D C n!X~5~(A`l HwS dV*uZd[yC'!@w )*Hb <H_q]]@ZnHVJ!<  b V )     \ E  @ v 3 qy/=owjUk`Z-|2UlDwI \Javprilkyf<Q([=5BEi{VMyW)'gFKy"" r3MqR84BgtE"6BBxUs>1#\='05D#fFJ ->32^o%|lusV$!XA> uxq) <  ! Z 9  YX 9 F  M?dxG6Av"Z\#"i}Q,`e+} k)`cze Mi70*q\jQP 8Z}9 }tz 9CXsqGS_x;Ko++kZgyC)TA6orhY1D0c*k)c>MC\D$${# + 4 P=j}/pHU v  F 5 X*  2|  v   j 8f*x R 2 KW J o {jA2zp>$ XrkF~lQU &ZhHK?IwU=@i"+eN4ouKS*'LEY)k)jc,% \,w0-7?fVaDrrrg2lJhW y)P!C,i=TN.YFN~!(T?m?U:Bi zK8 ` 5 [ pZ * o $ ^ e w C 0: 0R XP wC p1 l a  ~ R  X(Tq!  u@ W x  } FI S70"Gd0GpEycX?q7a2PC'Fq}aAX3tP dNbb8LqO~r>{Wx\%`&(cI{>bD>c ^>w8}^.d~Ai= % SeV2GI)L!P:$`Nf  Z .}} H , = * ) xO q k 1 h L  a  / J8 zcYv-  ^ &       @ n 6 z g j@ V< ? f  % )   W e  3  5G hrQ8xotqoyq};{XW:-,v8q`av.6y|%VS0O'edd{Y #>bSb% ;?3y[+?nEl 7 ku FQ Ur z .   t  ]  w  &>qD,  D bA  y 7   Z h B o      L 9   [ dO ]i   6 } tX   | c6'8b6  oBg4/ij|jzVH&=!vP"[ML!E nll~>$f'@;YxGH]%l^uBBxZz?D| 63d um '   L B /<  > _@ 0  _ 91^D r  8 v %v  d  .. + * 5  J # Xp a  ; A A ]  ( , <] Y -_ (L kt0<&3ii1 Jgb#x]&DqO]D7F1a Df{X|l#TVKZV \z3;L#!nhLA&~w.uGtweQPnoO.-M.MUA,mq&#E^"<P)e=hp=tAhCfq9m`u~Y8xYB{H x1cBW'Z2e5""b(.2ZpaQfMhf[roXB+    wyzrJ;y[?H#+-BCt+Fl,nq5# S4 sp T775,]^lq d^exa.Vx.D\vo-iqx/ z3*}65V_z!X ' ) wCJH[aou1 I^2.P%;2"Ksh9~Uig%-)33 H70@%04.B PJ~UaD]w9JKpfO|wamKbqxypWift!4~_ANVqKIB4ff}hb'n~HBf'RD p#XZKcSIH# FB<h!%%X@P(oHBG*$g%[^?7nXRCgXO~JeH'28# 0$;B7 40AYg;Fg"OgBq4n 9XBS( ,*,22ri0 g#y0\qfWW,%xK K?6O>>="YN y~od`g [AZo,VWIW0?V;gPyOkS^ryg;f-`1cZkZfVoZagu *?QV@F@Qyug$!y^q@+[nng**O8j~3~ YWaSg"8LL- izH_Ef &+)(&VzRHYw71:-Z7 gv)R 7  or@~$uj`:jxH8(  ~b{`BZW(L}@Q e9-cu~aa)vhu`%3#Lk^%x,|HOjxKifb,8?BRufX0g:HRx0:Vc7yK"j-cqa#k0`eC x(20 K$zJha{VvW"XsT-RMD%xaIvpB*2BIhzqC(r ^X8eLXSeHH8!Br L;u 8A8vk,{ R! )f~ZZnPWRIS8:*4 R @?`?~0* 'Ve+,"S{3yc~wi" 9   niihoaB=7@7DhBxBbP8 ggyagC4+\\r{Kkqrvh=f *S'a3L08Ru";1 ,!L8=S0O8LDOnvR 7"#XPf4p:TjiWb8=H!PfQl <JunxvnoXz~(kpf=aG{{\rWkcs\siCZ9~;Iy9( e8:H&XK!h^M,1D$wDv/%^7JhS]Zrh`W;@P 8c^jOwEb(!P -(t4tU3.9PQ)k14<#1!#E^}sU{~l}bU<,:`<J< 00F {ba. ekRVtf#8Xd6+'R)lYkL zyNPP[gbgv~gw8}zUT[WNi^nz 9XMl9z +>z[/? , -HFgIyIrv^I'\"7 %Y~\[[ZL. TT  @    *   Z 8 5  F  l ' oyX'~!H|rG!1RzqS2O'k'gO=A` 00j[nM~jY3EV!' +) <&n:dX!ubu4vU.%~WYDy6R9p0[{z +RFAFqg 5 #. $# .jx5"G:Jn5M-"% jG$aLIt6M1,TY>e'HscIb'SgYaAW>`:BdYSpiQ. 1 62I5M\)@4,1}g 4r   @ sN 7uq;I'z9?0,g;Ng;|;5,&RWwj]V;gmzY=uNvizQcqbs@#JD\r0}So0]] /  $   N w5B{|0;m[SX-RaP) ir=v m!ZJ'#D/3zL%".bTRU~vd@epkH8A .=ag_X2x_KE*2) 4Eg'X3{]6 v  -f  /  N > 3   o ;(   t !H   .p  VT EUU)K Oj>-Kn )  I`   G k@7r89DSbcMSvym:x\g [pn/EefA;='y>fDgr1gB--6GZdTB|FVHr l84j (QwzfKX@Z^$DB Z= k' , " L-,|?V} !   kN i  gN } I< a 7 Qq e [r1 | ! Ey$M{N+/i#"=y,fxkVmNrF13i Qm=9,hgE/.+~V_ >)WaO;F:Ba,\`yW) O%(| nTN#Kd#n R/SP]@/gU=O[L]RN>i E w < .V  TPLB 1 "   6 (  G4  *  `G G j< 6_%h&"$btRYh9U\|^ra>#-s :zUT ^ ? 1T5ZMU/%=FI65%vkZzibmv@aQS#@'N1ev1R*>-E0h- ]\;" 'x aqn hX T]     O x   :    Z 1   S J1 +(:g;  Oe  p &5 * #  o G]  ~ 9 O~  J e n B o t0  = t_"35$FJ]vkk<rn|O7mg sOjaU/dZ;lD-%rGRz q,&_..:Qa,|evC?Bx m 'v cYDE) I  3  ~         (  Ls LJ  1    l {# m a  i' f  6h @ Y  K Y } #-ruAi(bRF@;rwgy`, g?UT> VfDmr1H {iU$-J~s_E;ik>OShA DWcw+i[O Nx;~znVd3]s'RLZ(D/B|6Z47F:g[ RGGXi$s*;+ ; FIu|7Iy T3@,DcY\_sS-z#t\b}\gsQw/22+PiBk$++x^v#W0kxSZpR0/hsJ<W(rvn8j Xcq5l~_KX2rXb6ri' -$RCW-la{=1x'6~& _MwhT|b0*z<eqN.o_R,RjK~UrcU~$0)7&$ LS/x&mSzd<E-"RPQHn/s 5"okw~NpEk6P%v@{DcpII!&I|XW25xM> 5FS`5;Sopr|zuJgEG g4q,C&t]g3+g6+Ucg[))6yDqi [-zWI hywX(qA[GR6Ni)I^[{OrH?oD3qKZ;[QK(jz`CtuH[xq 3?D6@LN1%0 022'G0t"BF #71\Z334V#~`Cbnyvx*b;+yD\pa~kkw2C_2SG2=B  ,T;;7Je CP`yRSjKB1pi!]]REnu~g@tszw\6~f`"(2"VS[Lml^[PrNAk/sUGGr_.u%v"k/Qich)=NNSi=VR\01B[y}oboer_b.BW (;CyV~<hWW*a@  `84c%*y ?hIPV9vYUq:b|PV:J%g["YfNfd]b ,YBqPKR^oFqVcxfk2 HFgbIboe  +=(eJvMC1gVL! bFQg4yHYZq*;A-Z_CnizNmd&Q6$NJQ"D quZW$'gf=tG!}p!f[O-]hy^pMa5Q-)  &!FD:"\=y@p.<L   0 X V|n>  U  T AK;Y@(`yq7v:_@U 6r!`]_BD.LGmwO<4%8^a(R,epaOHHSrK+ tFo6* (]b"j}2 $u jv ?w   r     ,   7U  e  y7v_jpQKIM5#*v QM= KA a.bH S 8A   e{IT3 9y: KrKE:"Z0 /YBjZ\/xI0a{d,XlbjtVvDz\X?<=Js^"`&,L=nc H 4>aVw|!L,q3wW_23,$"#] Sq }  6  GI;P] M > W/X  J I +M zK`//yU 0y A R ~< K\DQ  _ Y Q  w  nY 7 K]hrbaKI8]p=)62>e;nKX.HHP )b0<*Q Ax I!$LGG< N#(B@wk<RI0x^B70h^{W *!zhB/J z kK X| 1 = e )G M Cy ^wP:=i/0mAsA5   ,  Pe /c  C { !& U -  ,$|Y@=G6{Y+1$o eFj>n DXRk&6]EVZBqk~_'?-0?S%mG>tRvnn<LaeS"b(3 6] BG k?^w/u!hh12zdyc~#q^%4%=Zu 6 6 ;d @ h 69 =    g8 f n )r  j f  T 7g ,4  C  u o _o25X7:Wm' ,K)(WjvPyRVK/[Ge ls8O5j/gb=NtH(lGs5 6R,O.ht Ps;S)*)4(XGUNtGug490}0W  N  W5[w\R k Z b |7 {  Z N Bt?M#]7&-j|UU6't+G ]z52QShdn -[edI7%;Ld >d]k<; `]gH{|LvxlqYlx -KYx:EeWnGNH+|>b$f?eQw5lH*Coe5Y|@to*N)O`$f4 @'qSCJ~+i?@'->){VsYB) S";B|0Tb7{0n4(qN:<K^H%h.K9h3wXGbyh#FnuQG`}1W /.!Q=f"! 5'e>),^t ]6]Y|-?6NBOik\ 1azxg GlfvJsxlH9HKU95]T6"e5$vTII2z b<zz}?Y0gL_+|Ii3_[]#_w(]"jV&`<.7 rQA)E;">*-Z#XR`+~00-hZ(K]}FMHK^g+?*[2AKs KOU0OEAL[x1E;I^(+|W7zVf#e^i_NbetqOG"0!A?  kwY#p [T\)ekJ0\$}kWKuqn:' <KJ]@DINVqI=QqWS8Wy80 4y HLi8b"^ )x#oCCKC;Qh;~[hBZZiZI#Io \i+r%$_HqT6H:{\=;\{hb@m"O.~N D@7L \tIm+IZmsdw]_NPrhK"bLBk8^h?-I*f{^WPY\\YBB -I-H *wp@E i{NpMt5KQ [8T\mw6yRAmQi2Y@Ou!!~#+zd]];" KZa R:r #ezv;B+C9z<au5eF??9QoG9gxgxkfv}+k#c77=3L=1 8qYK~d@i6--R>>>"-KM^3\7KHPgH(-D`\hT\)262Q^}Uv6@_GG@g   I;?8cZg{n``[C^y*(l!iP*9~B4$ykWuS`uRvH0" 0= gx:h8 #nuEA twsul5>8Ii_xo[NQ]aGKiwOoy3-i)Y0f %^@^eI}r} P2 $ar `nGPc  oaPb *vwKgZQnJ2<98V9("J!(?,X@Q;OS @hkae`X;S+?'PL7RgvuqSakZ qL*PB-1xH_Hp[qCjCb>6"]7V~pRXp|*,38 --8?Y8V, 'P:Vo $Wig}!(*;2f_fov/9> +wK[z%khbawiCP2;y2cGo(Ty!2QS;3Cl@=,2xP;bzQ kZqLgIv-RYf~I; 0[g'038.AVCY!q9P<~ @(Q5%J`>,N$N :2*TC@SXpZivfX@9(,9{1~ h< y,z,bVL'2L22kJV<<'0 u'q+v o kafPOByPKy;a 3 A ;4VB3 ~tiq[]V`pzxw  -)8Bjoy' 4@*# -P ;$ZgIQ-FgHnFJqq}oqHZx^qnqkVqoZbHqiyegi^OZa?a?qSZXB$e!P47@W9^ aCV+$#'8 + qf%1^,,cLOWuY)?d)t*0~pGp[uu % )40AK7717'7*?jjh 2FP+;ObFiehi;xZz  ^;a<z$^<Q'xj#*"k13 LL4j: t[2 2)h@GbORPPN03iP{rLkyvW+vSQ#C L`rfOuHaI8-jOaTeP3'.4YCMK!bS ?kX)~)-0f%e ] _[ve@|!Ki %Apac!uz="$oC ;bL*R 9u@5[c=H2lc=(zOOy, wU< }NJtHbG@eU* l _ c / x      . x YA  ? / ;}oHg7~MlHg|D rY GlwY}<W2E$9-dLt   / J I y { \m ' pb4 -"J52?8@_Kr]`%g6nxz4hfX2*iTfVgGBgThIBFZ-]\:@ A9a !5  **    \wA N!V! "1F"!"!L N0WQ  ; *    2r 2b  j ZH A   d   z 6       ap`*C`ud8 Zu#RQPlTd&Z    _ $ M `!$]YLl z#$F6+w/Y88 ?Pi;b- X'4q-n%h^yPX[AiFJG,.f1y,QA_k {]]$=C@BQ>>yQ%|F'r  <~ 5 / G cN A R Z  }   y! ' K   d$ r u C2"%Ci.TG`~e7Jcg{~S fgGlD|A> }?-s=gaR,66; Y/{+!JllUk!yh* 9p4fH]o80<+q*.$\U gj'j$;e 6 ~6Oq ~ ^ Z { V  ZI } q J  N    ,      |  bS  & t p 1 n M8d6OZJ."w%Py-Yjy,lU.T)/dvHRd>1+ =|Rt"TJ:3/Y J=D/w=0G2TWJ[=+lzY~[o" #L`_KZmL5PXh8qG@Ym;[-b4c]f.@;?T;>;Z1?c.KIg70t-}HNW 3M`n0WHnFngP8D-3GS]5[) 2c,l2Aj~= H!F'K9!2a>[tM. x9V a\{Xhu1n3A-im-Xv=,WcN b\j8bS g/IQ 1F0HJpivdNNv;xln`SO[8f3Y3jT//pb.c8"1Q--4a17v$R7)Hq+^# ZhkR='=A6~W"=`d0*/ )N, {^9,.%_s^f,.loal/ GK Dt#=XH'=-n0AW`u K@On\{:7"gP),)5?!5*zj$ xb@ #+/e<Fz,Q|NZ_Fi1^H"yrv|uAs-n klze^p((S5sc//2 %)9'%81UwvM y[@U.Q}_aMKDP=aX{l\6}i \#6>`0*=kZ7>Sq3d89y]l,V<G%E:ia\~m})+H5'TWJ oM o'`)r9Rrf}?|9;J F(g("02o]yQ>5: >B6\y]EZ0E}e; n*rXq\DM@*  M@X4} VRVkFg3]U-O[u{ [M@K@jVi ' Z%-Sn,-k\#;@3[FZggjh`ink !9J CG9 y[riWTkG . $07+VBK--xjZFF Rt)bzqJV(tW<5A_W^vfG\yW>f'h *O{ ^ 9!Z'[X^IWPBg*nJP !;k aSobp\kalZvD\M"&A>pwlTssX92&q}M@o<-qP`;\\=SK; ;HVDugj~@+7( z~`G{BL,O01 8QNKq HJYQWPhBW$Iezh Pv  5$TC;"KX zW<lca~vQ@<J!+v3yQTT9xOZDQ9XS xyO\W\Z837b]NfKQ 2)#92 /U>C9bOG)C)2!KI]LXL|nJ`=jKj #%04O($ @H;QX7P<8% *s*o53Z;5yw/i \((Tt/UeR9cA  l\P~yvlakKaCh;.M[wQ8f%oD3cIvQSZ3hIuhkD9V$[9`3Lc$$!(!%xFB<-xyg?:{%#B#41'fgKqFPFBo8;HxguZOhkvxx}C8$9+X;i+W8"a,M;fGrB.{hofK;Bl{{yh\b++2rnS<e2IFV-+ 9O(# kqxvkuuuFv7`*c:jDRYr^~8O0VD1 Y3P=#z=J7t@ng|wX6fu`iZF#) gf=#xB~0 ^'#$ S1$@XeiLL<P-9 kx FfIFg1##|gqX||gVwKV-HigxuUQ_Kn|`!mE[C_A0m@ G /" @fJq`A=`HX"O ;"O#S#B7Y{kcQH7$2k91qy}q{vko<:!8`OZ{z0M{3/K`h:?kBbu)n]<KJLd 5/ihI\@,* ya\a'ZHo}FpdJF{@?=+l:G-%, ]ZrKEq!QU5 {zXX&k.3 5.NVHK#.xO% ]Q }N ^ I ; .iNk#&)WRC9YO`<&>Y>&_|av-(;I ,%ZW]d0qt -9K`Kix8xfZ'yIgcg+~_ cow>r:I|G&A>dAHU~oMjljj:jr eYv X>>>Kx|!?i}|^=ATk;<f+  Dr'?7Kv'Aj Cb 0  59   u < kZ3p<a`      /(x m  '3k5jqtezU=]H{0004A,OBu4GaA$ 8&C,b- x< L Vu 2.]#kdX\ak`rO{`|Vx Tx+#S&zwu}~ymj8]Q3>]D{9dcNTS@AQ%#x<m<   ,   hiH#\ 0    99   Z 7/{&s^3m~@y >#q/A29"q* =(Eo3p\{]f0 v se wi"(2Jg `~P+iNd{6tL'}5{@>Q4S*']1#s a 25 9K *+BO *jP!V!$ku'HDYt "I, e=4  0K V $ { b B ? H   A  1   2 E s   U $  l  I .`m ;B   8 }   t s  #; A|o7Y!t$c mf?.*_8{tc ma/oC42SX`i^LY.?Cu}U4xj`rkWe)K@lBg0&leS= t;LaR%OGK txy  }  <  >  k Y_ Y; d: 7* A U h( Z R E O E  8 Bx f z j $ l h :F X 2  9q>nAJKE%|?Ln~bI5 (xrK8KS-]uzp6}- tafEyOI{G# TNS!`.;->e!tj'W$]Lkk?WG[_}+(b~GH]x7 -$! S3;Ty<<XCg&E:jcQJ` HjNzo\S2MB=SJ1+1<Lv!oPh0`fScSAIhKx= X`CU:Vn#(3 Z)t"A !&UG#N H>b3zK+N' c;{"<S [yT8W3`8*OSTdpfqN-y[km~E\RM>YzCy"^6I)#UafR0SFRrDxKAKL-8 BI72-< ov%BS7-, Q\}#Si8a7sVcCZ>u-t"oOYG8|G  $"?lE- 8V 41) rtrD,ij>/)%KQ: W MC}O X[(kc*uq:\I^dRn[@p~7V:nf7lI@ID18!zyg_^cZFD =1 U8\@{8T( !+DD6TwVwww@dmiQIwk# x3q\;akP*0,CL\Kxk;{rcwk*-k;wOkVT@@J#' ;*OyH4?H3]!pt~w]0w[ii8.f"~ e1c"N o cos #E--0#:KufpGX,*RI0710P`Sy- cO8fSQxiyO<; G + %8 "*!<h S q^r1$yQu' j%,=D[O] Ro~0[U> H*Yq/R+n"Y7!A+NE7C[ppYm^@1' ?^uic*L0X$ib'COiQ;nanZg}krri <i Q $c$93i3l]E [ =Hr9G1P@3\Hhliuiu=fx8J;yszCO7^^C <W00J CQ j{vjHP '7FPFFLZvz*L~u8=:%a1RH=c~H?L?# $(I8X"=58*K%_$[,\ "+y1!X_(I"!(3[K o=SJ+^2C"v32<$P^84YA 10` A'uD*'7jFj6|3EuQA-bwb_>_@G"@Ytw+_!#[p>]V([4HtRxIX'iBpkWuW9VLHX{ar@((BrPz Qyl; $( lozc3 % (2 . =.qS Wbq[Ong909Jq \L4VxZPf\jY1zRu:mJzQ)"xb2[3: t])&C3XgAjQ_O~iR>| +6(:0GjVJx:7w3N&nK#L1A0?"j;I?cFkf~uS~1I8JO*; 2B+Z9h8HiQ4*^?zrv3+hJ+D;.3!  !WKlX_{Z.Z" "\5sD5"oqr`xiVSLo^kIvOrXaa++uP`  -SvrZPa'fFZ'vD3:=^"W, RL\\ShH\uB4*0q8F77 B5h,k~fiPlpJA[qm-N9-)& ~ ,y\_vhh hM(zh( byS#;2#gr[u'9I+8XO?b19#u0 #' g?{PB: 'K#Y""67?Wc"mz-PM$w+U.b]@ l]sEqSgbD s$queZy*1~:P~m,8~%ew6M8A Fc'@#hYeP\,% D49<9^.^2{Qe/&Y/{(lJrbM ^fK"'S\ aQ36;&Z?t`hhkxH&072$0%EH[w3T0HJ&A/:">)2\0qX}p.9&(:;cJSISqJ'=@'x-G!&-4\Qi9]H a//'ovU>UU m9xF|5zIiw O&SYf_+Ky%0#HjxF#q@C3# 6Hq9#_~J#fo Y#, | Mf Zj Fr a $    y [ QGRH[tvR/B+;RkQF1vL'0 D#}C(5 ]c/MwCAq[~;_/+cJu'k Yg. oC#W"!$JNA+M)I-#6 A<Tv=;Zui')`0 (FWx.= <wDzIc ZbqH%qzF|t 1)z-]3;<}+F/eW2[$P0e5r._~ylSzH-Y<{!cK}l%@&4Y%T+FJ@i3 P   ;+[DGw3hlH      ( BdyAO2i[bpKY[R@6)\I! w_/F*7W <5i"4dqE F6<Z4F! U/]OuHn:h$>rfqn~*YunnEk)=D<T{-)` &  '~ D  C Ht Xj (o 3  a V#&GI2nx<rljAx0fL||T    * [L q 7 2 z -3C;W1WSBt'XOn.:-UzI"j]V{=H!x 7Cor $&INOS YvYgf ;"Ni8+{jx)\fn)MaC\#  )/ ~ \  b | h "     UC O =  [)    /_{=h  " 7 il   -o7dnn~yQa)4~Z8{oK+$ -qDGzZ+kV&l_<{>4eaW*.%b\k4QYS3SNLiw [&; -]dO*[ ToTHdzZq^;{<<\S$g\g r d +  ! b :D + \  w G;   6 G t 3X h   d Z   s &j @  c  ^m eU ;F%/Q~wA^Gt]tA&.!q)B K8;.6~%YJx=LK=$LBS( ==SWW#K;Tt7]^iZ7vH9kcy8!;PJ f Am"FZh e p MX Ti v ^ I i .  S Q O6k$rY;h>  r \ H 8)  mR  |g@KCKD3 -q[\hiI@pw.<7b~Myc x(rN15NkZ/S63R?YFZrIN::H>$+M{9;SLbeW$I@E ,89{:#-1iq;7p=: 4oL^u2{~QQ9T]jg.m U { u [ Z S 5 Mua*xCVTwC_ +2{i= '~h=BrYJ7kz#L>9& n\(o F8% >-2Ni Om neb_T2co#-OFqn}v$2 B ++IpPoyw~p*}gXSJ4G"BM2j+RYHrjFC0$@&< '0 {hVOZk)vg H-Y=r!ffAa^hk 1 H;RR L :k'RBg0: 0 fgcO?%BI"vxHL-8O3xp]_)! I HLL=I3uW%v`{ovrjy, )DKFS0 ;7O,0HUaH);H,)PKY^?{'^^h{~hC0<BMJ ,Xo<vs@Xi}:*0Pr-az$7.7Ph+!c"J7>"+BsaXl. 2$:S% %)7-d/:9Z" :& z5KMy5 5Jy6MQ]3QsX$S[TC9=;=ePHbIbOgLFK'c[tipEum b@ 3aTCnyGgFSszn} 1hyw(KtMNX?c9J|J0nZZ?Bq  F01aC'Z8o9_B<ey`yvi_ghiz^TLkPu"q+e Q;yr%}zx?P2^BZ;`2Q2H4' 2urH8^`o=a SrPv0j* B)tqqwupugUmUUNqxwif B  h%v)vI$g<^} 3PW K%KJ{r /R9eYt`{Nljmx{}zjs5A-6=CAMslKX2T!iQZ*I85 rrShbFfP"3;{VA|j=]-2R`~U=Q@VR9Q03VJfQf07R#zd _i 1u SSSyZ7`kkxH(S 9f~p! 8(hz0f^ha[C. nv"Rh(Hg'"i|bbj[RH92-K36"A"2&3[N[}wX+#!Cum>tU  K4m06/"Hu',= BK;oKSj{v0auk!X8MJ!BcTP22PgieB8 RPa`Vo`)V`hR,I{WfkvvxzZf?wP^xip |$8(<B I-[gZZBWh2* @eD% .Gv"39X/"&>\+K)J 3C&N>c& +  %+lXTDI1@5$3.!GB K\lThGJ`kWzr[HW*`@<C*!o~YkLZAk8I1"i_~|z]KJi[WYA1*P j3BAVy(+OP+(PPo4bQ-@nIr%319IC;\Sa\_ w %bIbl\aBa*^8a3B ^a8ZS#'aWW?2+!#kORP\qWu7q=ZkuBA'g[pbG]/ #)VQ["]ddw*]z%D B07A=f v)ff?x ~ 1{^nL4qBvuSc'FwL&DB 2%3=9W+1OGr Ar@wGD 8\^k{BHOiF0(/[k g4hQdpdm^cy{ie6 D+vBKv3t"EM9k &)6#$\9&;i`BJ""Efu[a| vThB$xP.@]/~# _=-V 9_q~A|y;Mf`rAI^QALBI?/?Nx+_wgs~oco/W` 3Nw<#KAK2 8HoFIJh 3hoo~yrQ+z0;KtV`;  #  -  A 6q _ u _ A_ J  !  [m / sm"Y"4lMkN'=j*zvj{p<~8qiqQ1- K hLfB),nMnX]Jke {nTKZRkVntcKMgA>-%=5.{NFbn T"UTO~B{{;\3t$3;|E/ww`T(3_T\VbW#WR fPj>t\s [/PvP)q\.lN?I?\fQ;+ls> ]mH}<0cp%P% _`Au< al-X}jtE1H9^6[2+bq Q{Oa}=5/c:GFGo=i gl}iZdz ?Zg. Yi&p j{C{/YjLSZ6S 5 w( = L~ dZ W9ts Qj? |<%zc&O6QRg}N:v1hkJ9q?<X?oaH8vIBIo&`K{k _b$p1qtPG>v&cUTUNce cG@^Ssr:H2;Kk! 2SZ?V'BGx C\" X TT 1 {;( y9  ,   @ N ?    \ F  "FoYS  @ 4  NJ ; # W W !  d  v J [k 3,%C;A'%'"S[SJ]I*4@Q)W#fFUZXAA?wa D { b(V1tdK  3 e   T 9 X J   pj   lN  nq5lQ g   ^ -  W [ B U jU -_ i }J  m * _ m   Du i\8$7mEdIc |.4`j&/6x T =Az9V a}1X (5,tJ]n(0Jz p+l;. ItedUc]7@y<<3I / yO} ?   ^Z  i ~ =  q E:f|i@S I  ` ! W , K D 5 v M )    Y W% U v ~p K] s u U 9=   eo;(:Nw72p8bL }0e7EB?qHVZ"Y[cHS$EEJdd!#qci4bDw)FU:w %ZdKt4uSuIf] U#}ky^-"9 /- p6]^z7yje - S<._  f z g | w A  *1   )!  N w ! # K8 d Z  W \ i,   ~ g E"   }z O2j|0q*l5MAhp;}YIT ylX` 1pO1Qf&Iq2UKVDC.FIj:"* [By$KMj'Rgb vz@_[[}IL8vInBW5]]|X>9zX_QEgz-AAQ|VG>gO-Cz20%7j2F#L+L?  -73|JwNRb!|w#>:#DIcP,** :vVAn%1[:&\`&O,D\ -:B'W(H40M3CFW -LneVZLqqku%FpvarjA 1v (0<`1Pq5Sv$s:GUD;fu .D W&[Sk4s  &E]O 94Roe`l<$w5M&{LS_qI%XMT3s\2p"{&e%9:>2=&,J%vsBQaTD!(+9+ `v B'C?H+9@(xx\RW=ajB 8; zigY!_ 2+&Q^@.2')1'!,o .'DWTFD?Gf #A7gpwwt-\Ocku8#SQ}h%c"l _&bwS%3Mv%P/[ as~o\5J+Po=iBJ %bPJO<?r'P*gq0c\0"H:ER"39JN/#/ A3sps& =#3RVAREN[jXw 4,, *?BY:W;PVya 9ahgr([,Q llM c%$ <9_Tpsp5, I9_9{y\bWkpo_3yy($!B5W[X!1;ku+[ SHIqaLc*-0-{'" c`~ckj'Ir~Pq\vqZ!vHFSWS!9I?VQW+2@(B=;%aJ~$W(s"K(h\obihkZ[Xz\S%!.1@! XykfWpb2bX  yIcPA`oF)0 g'%|UAG&ppm):]>72 &X/X/gu|#;:Zk::;Wrr4qu(^-r+h!v?Z?kVe*PHk%*, K"@8DJ(5CT\_oTc{zSD*$ rorZIQOCSZQF-x(S;-cYYnJVgX|j(qi !F#(7CAdpq|+1QQLYnrk*Pa@Q8X!S([(9*$1;DZhDW{yh1=k.1$l935* brOxiBJ1xJu2}ehf{ykHFFv~LrYZ\d`nBmZj~v%a vg ' *?V[QZQeozxry`k bk9.o;<G23iwfrcPGTzPaaK{ cB  iMkS1} xz`x`bJb4<##$07(; ~xrvyBAR^vfV7' 0' " -"#B" :^^yL^{ku 8D)0PH\?10L ``8  2B+-?Qi[}xqonehPuo^qS(aq^Iq1^24H]q#d4*t~T8 d6bK\j6JAi7?IN6X`>h]k>A7D;!&vpSJ>S+{ !AHWg;N.D.K\  r"1 k^X!dt=k`6"~eD/wD""Lhp8H6S1I_}HJ85%nyFSK FS7 9p"yaQ!egL:5;\&tKM3RI tRlr[LTv}XUm- v"#Xcf[_l KeNnxu-}| V  H 7 & :`gFrDw0  g m >0 A _ VX"FV:p4hfu3}fw'%i2+ 4{rd ~=M++e+,E3L|6Xgq/9d$AB1++\#O!&F%;" oh3*4Ij{ c>_P5N6 DrKX9,1v9q_^Sx{KW.u @PHuUkCbc   )  psz   9  u7   z= Hj2Qe']=eI}S#9!7Y1?Y( pwl8G RoClK0Z<9*rr-sgz'X nIIV@FV8OR"Il&sd.;ET] \J [ * fu  N  O    1 / #\MWfc>; oWh-C}F}Mt9v%*G9zW+UDk30q=wH/U%39va+,/?M@>h)"/ ,zzzZM1WMKuuF9'8B  ? T y -L%%~f0zCNz"=|!2+f0q&3@` $. ]? LT 7o $c8 cSb/W#yW`-X@|ig`$#A+o[M9W8D2.1rlIN~A9V";pE48 [2 v1S$ r?QZZZ/RhB#67>;5UWSrw|dnk|S:7'mDzYb/_"<c+'SmWkuVtJ9Jbc9!@@J8#,rGM ?YmUJynV!sT (/8ruHKKY,-(").u'UON-A +%!'(Ti,Qt[isaeU6JExOHhrno{SZDPS= kUS/#@E /u`JN9)!/J/_<|== |W(WP+(UU dbgI.f_r7J T`|,Kge,Y:gs & %/# 6;>;jN0;UG=D@7nBB4oS8.&0EY1K$XN q]N;K33([CMXVkWX*W!  g7u3q,@jO[+9#p# 36(KGXY%!RJ1CoUz7BCSXSWf^5-IZ_I<l3~9X=+-/[YYU<N`%> whziM5985Q<hb2H0V C0['hg~Vu;v |u\fWFyy H)1K \?L8e-OH[-Wi 1M\DkoTA[%$%a"K"2s@kW;yQbv^H[D[I*<$ I ?0J%F*+gU|q`gJFfkUK:'[VqqfxtjGiUt_O+"+2=7b&YAACE9C6xiRz#wG_0!tg()#"&YXd#u,p;A\`v *ZxrQ0!@*-JVZ`-vFkxZiSL?[ H^u q0*1#z[LnCR?KCVAAB" I"?`dH|@t00 ]: -eow"@]JQ:fUO#: IKH0F0%~?k[J((9?-(Wv"yIP%QuQohy[JM[axp~hrkS`Qk33uPJJI$ OvJ<S1qB+09CZ3yyoZaY;L-8*-) g=futJfd=(0& >AvFbIk2_!iok~z&9%%:C\Dem:E]N]pXpx9<9/"tgK+k ybhz@rIaGoyiFPFoQSh*XQX oxoR^:F,{vjWdZ|ct~u]cx: 3 :A1 ',F;r3;RFFKrk`oxuuvu3qFVqjK=^0' ;  L*\!P OP4w?Z,^ptUs'BSj, |<tc$ - 6~ (   `  d = t  | \ d O I x z 8  Db  +q W  m eI   '}[E NQHt9kKN>C.)$H#[r&UrvzL3 Z#7X%0 Qo@%fLo(?8p;a= {2A.f.X-Y;mEagLc.V1h-W,o @Vs)1xRyzmiI * , PApR 7 -  $ 8 c Kk l ~   oI b (!   WhY H F  ^  JEjwDJ2DoDGhW A--2KT(GEeA$DY *iXId`9*^-+RSM. ? v<O c>lczn{bIca k =; K,]c |L)6R }N F  Vg>@63 3"Y{t[M}yQ|9*[Pr$K)5l)sCK*glu^L{{[L(t ~7][2NTWJ*3sA4Hi Ut~!ZH} E& !"S,T ?  - d9 %  G x       w x Y  t  N  { 3  jw 7 f 0 T hk,0]^~<6g;at-&S@JN,DKC) e\t@8\4xuHA bf!$ k,8 O=Mty AT/2u7 i/`w1H5#NFT -r#Q-e%pB?$)&! ,fgYC7G oy#q[nhyZ9Sf@PUw'n&D[y7m k6ID d   , o J D t   z v  m  t o 8k L f D , r z w qt+7A"2Ny81&aNjAu,eWk[#i B!^- 8;9pO#\=r|f+/vkZZSPyTfrq]k6gLxvfq =Ii}aLXBouu#2u'Poq{`o^ ObYPhg^?fI\of JKQUnARY+;p*[Zb8f{s{rla3Mp QM**;p@p8k.G+ Zhbzzf\ZH< 84"xUv&HH7*K4Y- 3A(& !!9'GY>&0YQ=HKt[gptx`qYqcCHm02' --:OXaUZ_KU=]HYg`kgv~nQAhzxycachqc0"47-O\h*n Vnj n7"^ Znf"~ySDyZ43o,uf0A ?;*#?3Z3agAjr,mn7J1RP&4y ln<] qH\\;avQmHI v1=K6{Dqww kwj q-]H-Afj0|C<}vz68_7X%v?nih+$Q_f  <:TYSL{>uyj Ck41[8L.XUMo5[`9xAY^w;Hi`g&`gxc9LB3?E5BrD0;`J:9B3$ sp/\;K*Wi<3v gNNH[,1Nv,W5@Th1(AGTy~  %Q'!-@@_VsCmRG}0mi_g| p+`N> 31%R-Z`?jfqWhr L[XZ8u8Gr;zQs:mlMfi[vKXvX"M;b"K*?W+g C }C+S9O7F^{!RW71-%3 t")w%]1?P\qnIR`{Snyr'-7?8BAHfJ3P8?^;V`O[XykCSIzyu!29J*c2iWsuuFX$i-v<b'5"$ `vFnI9LH*!SIoxI* qzufGXEbK0+:&m ]w-x)b0`K4P)A\uhoo~\o{joq1`h - n`-OO' L#I2YL`nbFL<~:$-:xqL8~Y=>GOJ: F#  ?KH?-q1=1-zx]3w dg@2>f:Qpb;1 7P0rIrhh`kPKjI\)Io#Ox9P+yWoXikhspzup`sMVyz?9< ^xFL7|_Ep~&9Q03i'%%OL` B3gI7k1xYV r3Z =#xg{|[QqKF5*FWeSs"(G I8@<f3~ =.!5 >R -bzzPQ1rwo`PXS4^rZIV8C*7*Ve^XS^ q-neV@+'h={VD1tRdnt"*'0L #IW:vR3:)ABD O7#* JNuI=~8~B?qF8Zq{IRx#ajD`R,0Z04iPO%  +LKHCol\rR\` zK q? u4T0 5|Gu  GB 5 \ B : H > ~  Z c  Z   a \ %k  ~ 5/  d 7 }c:3*xJX y ! 9 H 2 A } k Z  3   5Wyt<!0fE/p~7XZ UM8[{:q0a2 Y`Vj`_GK8LimM.VhWQ`DL-$yh;| q2/t*A7xwX) FIl (m 'c eR( ]W /D   @[ ~ y .  I ^  WD   x  I  ^  y_<Z  7 : 2f  .dHi{&2/pT aH n'Cz4,.+n_1Z'% giNe RI\L\OkxoX:i+b#a~kTl{>cLB.j?P~[3   2 o  V A  ! 8  d /  |zc2-q- ; ;  0p {w *$9$y  _ Y@   + OJg(9c}u'X VFj| udT?>.+V@W@r=nGD$T^ 1x#wxhlGg*$d\)!G&g("=X;V+W- -  ;  I    r !   hh 5 H#  M v A SdZ:i7cE_=Q*ADX:L]j-H|#U/qzc. [T<8vM=:y'  . N v \   Q)el1 7AAW5tPucXaU.EEd5e4&}aZ<xqDx163U}~hfR0.+{?L#Of,.6DyNmM, bTa5.U D  ; fYG k(Rj,B[ ( `    'e aJA43T$Y#B   r :, V v wE?^$hL&5<=I-liOl .r\?N~]6\eH8b# X 5Pa)*rNi~9lx'; sv`h hL[=J0oaj qiz`~,y x9Yj C  9I6Wqp/?  o d f 3 |K/jgB_I=g W-H1_l)r Q4P\Ft"b%PI"'D[u *%3^niFm?fd~1vm+rh"YN98O6  ZX G   '   ? 4 w 6 uYM){&JKFcJC;(2Kh,LWxK&P B pJo)tb6{TsFhTe>6/3Vj1^0Wk#V (9bJk %%,-UlUq L>Y EQmUpIMh=Z%40k[`eY{-q<:>X=GU`nJwC-$^Wq??r=L3|fddXHOwQ-~=LK E 6y BLa3 V B0)0*@ 7H@ nqfJA)9p5X9IXa%?QXo([R!N`ddn'^{,;^;(*O h;P!9\{CK C[Qz R\- rQC%z*aHqrzyPu#hKB5b`(L(|wkl-tAhM{,:=isvJv)| E4C6/8h[a(+DopD \ 6z]lZ'.# [OV0<@gz[_+ejj)k{%1@Gcnh_~I_BoN|&yT*[eM,fs,_/;\P+!h;{aDuZ-_XOk6\ER2# 3#%  '6&" 7g:H;WDO`rr%aH~##'8q+L@xkBJ0gyu*9;=oakJz0@bK2Xc M2J( uuW  hvv\gYnZ`KfgWIZ%V-;xnR u",vo DC<7?ifqY`VqrWxJ{@^KJ~'k7svgbD/6% S*!BI=c8hW@Il8C c,oWI_C(uu[-(Q+*s~cQ(9gxP#C'"B0b]7X|t0jK=C]Ep6! }Uy(#maYAbG>@R!Om%OOUj9X; QFV!nXW:} $PI(O!q* "\w~zc3rrsv H)5{: ;J.3wk;,!^ kyiSnvXL-$ ${qf-`G!!60m`^y::|NbHmbu#473"a%')"?FZRZOkvnWq 7B!\Vfv+K4m"60o 2 IOa~XzSSquRhv8K*#SXqvvJL[WfXzan/Mlj)b8@S[h2k *P<'  #8=*HfSP7j'A#AzujUC3"AmHZkqfYox^c~W"O:+X":>=AUgijB)?jr<^L1By94  '?$F9*O1ZIoOi2ZSoaS[y[PW Q72I v4FFoHe0b'eCaJiZI?1Ln[C^ 01QH0J b2< 1XbgF4LrXk^F~Fn0uerhfYu .! (8LFZW(kI}VFx[P808CFS* ~o vOVRK-;) 0:k7' -`P;01#LqV1^?-P=^Fo!1+ J-*[F4B21I+V7+ 8o;a$O181*;'2'@01W8C?7IP;[I**4(4*@74*!4 -98 *80Ce#h H (*B711! 9+!F *77!  4 '( 944HL21@(#'vvqhnrZ`k\h~n~gvnvy  2g!Z$SJ!J$74X X+*84FHSV8I(*B2 ( # #!F1+I 1!*?Q$S1'  yj`j{Sr~!*`Qug?u#*@#I- 9H y# $[7 9 uVIchj`gyux3ggvAP7-0\*8;01 # PL 1D\FVg\hcu FHP!k;y7Z?[[bHP+8kCv9[ZreuOnJJvo$! "%",!!"Q'$^a0kv4^{`K~kgaHgYaPrZkKaoq?a4PB:*q;L*A=\L\cSjBcIh g1yjr #uFZh: 3HrRZHV%Yx4o g1Sy (($ k"l K8B$* !%+%1  v^;9#La*b =p6Jm2_{jSVl=Y< 4   ?s\Fq@o8)J9 Zqv<#(q- a8i-G"MwnK!0yXA|&5N/G(i? xLs$P$5*Bg]W5K?_kQy9g5CHY |e:%`^4%YT;S^jq;8   )}S` q%Kc*2_T   /  L5  V 74 "    =F   / V   B MYEG{};t .`b(>|%-|I#Z`0[=}dpikwrO.2sY%K][vlzu3z5 >3*Lj2^iB,8?\ J6*^= W o UC] Mf  !; 8L U ' 7 ~ ^D: +  ` D d 4S[?w<jWi2$za`8L47iOdY `4 /6j7btEh  cVO+dX&>]@r" MEKxLJokZ.4a'r/_2,CI B vc | _/   P?e p !/ a _  g \w4(u:zzBzMyiX'aa4++[< *~o{lMc/5uhTL W=?Su"W9(j:j@K,fnWJ<#"$1*(vIY}AH%MHPje.glV!iS  n n~P/  )  U*  P 7 Z [  h R  u  >  ( | 9   B  )   + " < |H )G i th %X ! 5 $oEn+=R[1ZjL2<8e C;MzELq-cctYeuG@-75)[0aQV5Q1k*9qWy~VbE(z,hj:o4;=H`i!9d?CumQRCi}"QA59 vi+M!qMw_w0 }MwS6@?:1rVDTQdRru8XI}@;A    b  h  D@ U@ W + ` n  J d  + % /+y Y ar `  (/ g--BGw!9-Jk5jU!?!u2)\)]DPHocTW;v]U3BB>zs/E{gn0h0YW@eO u`hS[s+U7KVIkLwjqakh~:% ?T16eJ\",V)X~= "KW!P -vBZD8B ;=# := |J!N],XD_)"=yn0ar:XJ66NpS;a,"<*b_hpypz>zzrrZS-MaI*;*D  ""G ~%@Hh4sL;\GrSb{ 4.'*;}7vIxBBFZ-[2Ob}grayhfBb `}zzQCeZOq=!wAI x`C8-}+o!g "XNDQ8PGcO{gws||7fhc?0VIIj)4gFqh\ufg~ 8CHi aJbvfr[.WXu1`JPjX! w{sjylhD8*WTyJe0$/$2(rgYI+hy^dexDdNaM|K7'j,DTD2rY{ "/| /K}NhIV/Ou?z1$rkr]8s7I* Z ]3M{WU\_lh +>+,CC Y.S7,-#6_ok|_xDPfA t _%w L*''6,i6$[$\3g^yrV8L<#'0#B#0y@ hy-+r 0!Knz^uc%xh$mR YzgxuR8v4uP`hPL$--e7SWPMvLiSx~STklcw  ro9$ WP;aKSKJ,zDS klMMw9UYDEHwJpD-5+C2z,ylQ ieJzz}<rPR?q7XRC|mUjwa~zug ~Y$tx4fyR;:?F#{#)'S v'hWF^vuvyuuoF^}vOCVIre7ccZP P8 k0h**[nJL (9M}K9%z<u y.y VLxuoS$@;qX#ogO9B4u`y ;F'CW *<0-+!!B(L0C7I8 $#(W1' -#w~_#@>|UcD|Gqh:q7  @  `$ 0 c    8#pvOt YXM 9oh W4B$Hh5$xm'={10 uQn?OnK f )fW Z{/g'g\HRX#ML7 <  h GW!9JzcZAD  u " Y s 2T f ? f  <u U t   R6 v    *"   Ix   =b@]t ,,~OPGSX]h  hpc.<AW~c90myW  t 1 9]Xov 5f EC d  y Q O:%x W  o ?  : w '(c*WQUF<T@  ;SE 4WN P_N!4^LK78Bu3M z]x28oysQ+r%\Qy\5mxZ 6  P & o J   / ( gN mN t_ jI H? ,#   _ T f  qy\&>QYH#!B(O~4.AUsq-=\>] q M9iEt:YHQ1;6kqeXa?* oc6 /z5$|Dd3t5\X{`5rScN2 n  v Vl f f w 0 @p ,  | % .x?i   B 6 l bS 8'   V = :ZUwae h`voA?O5xG!)U1->$!x{^1c 51]8])INF16^Si9G=m  T J H nY q Gp 1 f   0 T_ X)On#|  `%r$;F[^Z'>ElOrDmqu0)nl+.u6= lc? iS &*fB) Owk|d3rbwjs?r{xjl#&K7xEdy){l+kv (;s?x-;w;^zzG^Z_%~T%j&=Dy  E S n w y  $ ? $ u$ u4 kW wF [A FA  ' -EJr?85<+Ap.,'@nLB%+ip+( u3vw+&?B`!F{5I o(CY B $+&!T_ryxkre4xIjm}Yk<^G'ySd8Q9wh 7YOn [BPs=\)>'@  7>YyWvs88>?+so$ruRqO#/* s"l>a%WO9*-8f V7hWTsf~ws3t()/XA)`D8`O*#6>3XRXo=^Co`U~Jrq`R3))@C GU),)DuVov";47PZIuq[Ig1 q4^*rja4jInyqnh^y# 1# avoa[P9$kVFg= ]) n+p"aS[Vi}:)?X}}M(/u~|didO5A!O }. V z-}PG&QV'^w~  #4632 O,Q2H:jHoj{Y*~@i[n4*4o[!uWWvCH97HW1JBH[UKbkfcfQGGB,   %#D_dNIj -V" 0ME?-P>CFPMAL-7!C+8BK{TyQKMqPSh28T,CDD=.*T%`%B(<,1:;Myykc;MGSCaDgSaIH3 uxOO0ZH 1F-I-p_f]UYjG39Zy; "VR%x|mNu|z~b`nqO3xb~wnu 3AHnI `u $ *0? 8'hZ$h@v` y?7P;(b z !xnuXH9?+?#z0uu xz` #2V?cLB%;IOO A01   )"LhKYRaq` #*8+*+0VQO@^q 0BSZio*+S9rwo "9*!   ykh3u%z,"a^2 S"a H! # !+ 9v[LxOW<-'$2 $+'*$ 870qu~n`hHhP`WV;O-; 0 =#**?B01';174,LK%'=Yo7vhuS`hvfV{aq{y SB^*HIVLVgugg~qfi:tZJhc_h_KLcR=q7t8)?= ,AR-*FDFnh%K:POOZ^o{q - #x 9{xaoK-?qAK0 "in]XRdNNixx~p|XN|ftijda{~ka~PajYu04 *4<Q`BV(+S}$v248XXq  nbZPbZ^V@F1vVWe( } Se#O4C-z}SOQIg949*uo ?FW<bn[X[`7buh X*I2CZX`@P rW; 74 *1<W7F+$' 2+ SC([8$8!!'9n(cCCP^bxJ*<JQL4<!!S!u {8<7S(S0H!APfco ggrL8 1B3A-7IyqjA-7yO\Lx\qu{fc\Bj4{DLnuSffh\fa a;1ASVIBK^hZhK38%;^gryucuk`SL-jCa`xvriq;O7yW'$+O^IZgu[kgqvevohV#79@`WB9! #! {urkn^RZPqF^*"4v0c;KO3Z'Y P%h)qk)n,g#y7=Hg`4ro < 9-C?BC`JZCbh$3  ;KvoqvWP(`9aSXF[2H2;7 <2F9F9<[@QFb*0 8 ;x4g^c29Ia9^i ?7O! <0S[Sq7-ZvZnq^^gZ^nbqxeoHPV2I2Ihe`BF;917#7^`{aaroSYV#ZvZ{kRrKqR^qK\^\j;DaOukhY{\ZuZ v`q^HYVR`KYxhk{^`Paf8ggo`uj{vvx`kfv\A^?n1v:,Lf8;I;DYk\AVxxjxfq~vzo|{PxKfc^^n|O1tvvk 0(a;OiyZM!*zbvo[< rgL<*@ +<jakc`v`uV`~Vf\HguP3vj%nKKj;7"*0#Q6~y( &e[$!!,tU.ik/CfgJ]nv I e   Z DA0cojyJi$$PC#*$v*-2y?t:L6V#xx}=\@!6R6%"9dw"Tg"N8S5m{MH lK]LfVk     H? `l D f d ` \       =w  (  5c&Y  bU 4 9  V    '  . =" '  ]y>C^=A(4B)R#s?F{zahcfRG,+~(bAouCu 6b5 @?v!]beP!([|5h[gWA3 q>2s<\x *U  (e I( L4 #   K w     5  d U 5  r CU L+3` z  Q "  OY\;29O5 (Cn O|I@3YKwz5;Wq\: +XF q#qw @U*ZL;5j{ Jt]u  V#m-lTf6d$d_HD-Np7  ) vu1`'hAoB3`c      PDZK0)l!~{s* lAq)1EYh#E"c&l+bP@9eW0K"M6U5gs6tG$^$P|SL;;."%{ 5A\$^H4 W-%J{<k|\$w- 4 R >xpr2oDYjvazk : szU ? ; RU i  v p0 v  T@  ] d     t ])wx00E#g/'%\@Nu .Ldsd<'vMcFcpX(gBpiSAG4!$<0NFi~cW_e{q 6\9icq\TK$-m [<|uz#`p/'r i  o!   X 9 Y oL I  pU  t 7 R  Fj J H(  ~ = ? h -z{3' HxC 9G;n^xEI 5vfKxSo)-n$!:&SO/ G*[vP" )d/tqp @T%hWy._e7^CDs(K]PP1 7zmx-9_Gz$0 3 +zB ,  #n9VImJ@4qN^*II.w2_K( s2axP>w[_E$ iBxP 2 ?2jYQW,?n%p*ag__k ?@uqvF'hMG {A z4D7x*~#jEJ0J:U77EwgbU~-7GENnYqtFYIHbBy` g+kbsDoZ(@#a$S$j:J-dRHB0B %-% " ,=)BRgqk``PtZ]f@q7Zaf!fXG@x.]@ =7KA9VX)=3y_is8.mP9F%a"v fL| PL"Z=hcF@9cMq.V?x[WV)4 , ,s yohMTo;ay""#Q4qPy k`LxJ* ^8 ujY)6A6)"!17`Ou0<XxB {07Ig Kz'1;Qdbh F;7Qv1|[}{/9Y j9h^;9p^aM eyhsyGQI {XgOC1JH>Eaf/s<s_o*K   oh!uhXC$1*%nxou\H7 ! " #J(E@KGfnx# :344PI:KLShZhZqcjh+Ig* !;+42@JhcfrowMG,v.~3o2o<@l([ir[f*X(C@![[+11;8   O}WHX9!^?;X'S- }kx ^XP' uZZRL")#3 ('(72Leaux[iHq~"=5(SO+k,e;^%5=fTBDJQ_QQh K(I\c~JM2BPZK*f5{8{{a[bTuiv1b5@JCkyukFnIqc14'Y(W0-={qD^; %wmwtiqR ;` r 0"):#LP kcjo-219F}qubPZrqb#!g*OyF`ZSCLOO(}(v80;ycyx^u?k7c-LA81-3K yh?4"u#m8=*G# 7-C&6/" :6:Ewp0J9QV`V=JqXgfCi@dE]Xtdw]fYj~ '7-Kg^\nW;j'qOqYa`vFIVcc7;8=1%B%RB; A-P1?J^`-cZxg^ynjoXX(;{@xk~fygvn^kYrHnBq:qqhZ3,)A38%' RF 3' , I hfV-' %Af0jHr@7b7B XKZb$Oy,,$!$(IIv{b{v%B55@S=3I<B2${a[ZG zhw~p;<!e^iQ01! FS@XOea('v {vvfK^ZSSYPR\\Rx nu{ $27XXC^xPHJZg rbu}}rO$7<C#{;Jy+hj K 4  \y e J   z yu Mc d +W o ] 7n 5s`o{y{8V;4 ]|'=fsp Pfy7_+^q{Z:*uzIxg M/i?u'^asg Ml z8Nr6.cl`AHl} C?;AA{v@zBc@aT^m};(MzxB++)'__x X `q  s < . 'Mp  ( [ k v   ePj  t t o i9rl9/a$+y!^ #_wK Md_36Qf_)Als7y]=3Irtm)coLJyZN  \  ~$ MW u /b,r n `}  lB 0'!m=A3mkMoR@_/fE^ZF^6.HsszE2f < D sW H^L:4K\/ 0Q[\riox_DEDZNmtXQ F:yN.G*8%bJzt:,bO_#1t>}wx9e{sHL~kCJ cPZ[  E4  e > Y d       i { TT D , r hD9$^ i wUP}~D  4m @   Jp ZH;!'TZ4$n}SQDTQa|N8%$$+J'!ML_J'6@ sF2:r3k;9v#\iE{xECl-(_UM=7EuCx"s^a22CGk@t PVJ|l  2B    ( G& w 4 oE W Y > H ^k _` u T T V 'MFLwqEZ7<OY-;d%|MTgw[\maw}$?If5 UVhD_MpWugr +H2(95+?G\YXGIQ^A\|re@k6d8r85}=}QnY*P$s tG 0-NwjV\;X5zqKeJ>-KYMKC[\sep:]`/}3j,Tl_@*n22gH47urK`7"nEm!pGQ}?&?? x)W>}/_R]=ojaux?tO=-I[U.D9,26APFo^o2+X> ;F;^vFtuUrK9x2gvaHo?w?cxy[1%u^qy i#h_Qa2A XTcpYfNI>]_S&`Hi){lS\23 h(@'8~gDbd##iA'W K^,A4p ssLfBoHBS${9. K\=um7,a=Vfjk ?? #0? OZ^[S#aDXp%  `Mbzs  ,'zwtbQ=2 p}hoC"}o#qqcQKAgkH",'#;P9dORRV_Qt1h%rV 1l@BPtywryq{k_Vd/OUU]_sG`Eb3C&=:% w&%MRE{zbsmjxqeXK6U$c:M2Uc)l*$a-{'W#WJ2 rDuy%[1 yYG'X/AeKE5i.}}hL:EDYtWnd1KQeN3jxx!#I"?6V^-[!PVx0=Yr ?+W9s, 9EcjesYXXUK:==T6iB2C 2}kO(~\p_,RLBKHPZ%y3`,L-# xvvS 0*3:70 )L8;k^Zrj\Stxqch~7PZCWyrS^<SkSB`@Sk.,v,CKaiG%};zWiT8n+ue reJ9V14?9(4'WbyB~2uPg=V;)'1Rv'IOhvF:`c3%k'K*A=83D0F#??B=1:f^oa\%{:~Aj-Y,%1Djyu`j\I?IPRqh;-aD-1;4#SHR-LB)  1 ?%# ;=4aS{Zoha{1$P;Ook@V+Fanz[aqrVQP}ryoiJ9C$ rhojvhH7%"B ,1'SD\`Ahhqca# (1'$1+!2'*ok^*2**4(Lo$(^h0-a4hSfjqxRgxv~ofhkAruqPL,\`OZ\hgZZ^Y4Y*B=FqLgFgP\HPSVy0`DoS^K-k)j:x^ `;uI {v{qxyk x {P~j)xVjIP{Bocjvru{y10  #P I 0LX!(?B0*20I`i18$+!;BI.,+1 z.zz^`qr zhkvXeae L^OgP(0z-ZVW  uckvr\PV^{=vjRh~k*@2?'0';1h<<O2<9I9nVq1;aPQho\M.[Civ a wPG;JKynqz^?4gX(bb2  haorPYK)-,48 ju#:KD?ZKIRvy#LC[Q8?<*'^@7  @4H071-'8+L0P2F`LQZav^yxxh`i`[bFW[V[O`Wk<i*B8#'B'8 H($7@+P4HB;'ZQL2S*0! !($4!  hqI^AYYZIS#^B HKkL`qL^Z r\v~ :Zq71*vP3L3;#-PrqOZW{~!7[?J-80WW<Whx0*JnoX?ayWLDZSLo4K)YV8gR~hoh^:KhyryP?gHv\V4(22 ' L8eivkbu?O OIP4+1$ vayvkjvYu{uu,n`jyu*?0HH03#8gcoLzLQSQWXB@,2)U*Y0Iv a4CX8NT0C1p4t%M ~  4 H_xCP7]iR<{D0J4i>,k5FU7F\t2l zvkL(1d7 &j E3 #/n 2e1x.N<?M_}2qcQ^bRE*1 6] fQ=@/F:oFKhC n p y    $  3u :v  ! 5 3 _  F   { J w,X^wO^f"lKQ` 33-[ 4 m e`}i F"  . j    1r  0 o  l   K R w ?x2G47EZ<KSd r~EpGeqzL4^/c$,+15QL>A|qoWMO23OK#|ybNXQNkj swpSrBQ:I! ^Ey g  jj#Gdk9rkH6  / si [ - * & t   ?@ b< u 1 B z r H W S  O v  e ~ <zi Wr  " p   1  n . # e `S e2T\ i$SQghg8O+7 wyoaNDQo6uy< %FW9uP~`o,;ue]AMm,kAb:# /v)eYUN5,u5sSO "(1]3 ?< = IfiE  *  .qL  { # } K _:    MX   p 5<P1Bj=IQ@$~X+0q\*-G E_)-Fw=#gPPw,#cSZ%Sr\qwZm{R-<{44Pm7`z;=ghR4*Z8XIMlA"KN|xOr GiA]SgYH-- 4<6 q?P5'sN,`b$iC; gaDtaSmyz])n| 3f:Wx7yZ7xPqFg;V1LDtGuC\^aM1@Dp}oym2m_\?0J|b'D`\cy+#A  p2zFsVfZ2k Ogu}nbkubrg0(0+Ws v$f<$PxhH2aW/;GW_b!y )y"tD=asftsysX~=)t:_)c p>wHXmI{Oh 9872N2e,kLR`\Tjzw7/rZ|cu KhAA8?`}>-|*[0dB{O`;nLghdIMNYFV;n)=&\~McKUbZN6-q,%{fK8Z.L0n?Bu R'XrGaCa>^#:BK0:cA"DGV:-Qfptt=IA1\OYvj-v!^POzXIn.(W+WkhQ_MSXs.WzZT,s2p~WwKb+ y8JDsWh*Z " 3PxqeYqPVO9F;-;81SF0F1 |dVJ@)6(:&&6q2SW#I:8_AKAn[f7BIVV=c"j;B3`Ryru(7Oi8+^u.n%}cb=8;hsz9M*QBGzw{bQ(  p~zKWS@5.}hF?+'* a;YP OH*P=)--? -;4 S^D4?AIF;vkknrynVvyuyv~?(9Iareb} "B+32aH\BQQ(M*ks?81LXC0  bW*XZ", jeqSP9:<2* * qrLBiw>n~+qqu|~wjjJn`p|!()|~"*P D, V^*{7`cou!?HVgruofnIDaZ'S IgPRfA; 4=}uaka}0oL;e }V[Fb*Ae;W3J,H1?IHBI-?2:7?(7 FAZ^ SP8"7, 7FKn"ZWroau\fnZW8*,F,)Ih x1Vo~O8PbbgZL[^vvqun$x!7*4HvbJh?`k9 1@=T,DB TI=X;S,IQWJJ;<DQ\CX;h%DJ(kZ_fM1X2% }nWxhknbroI#uBZZanVF!SJQ#P 2y^`YWyvkxPH~1 -;\\L)7S {u?no?DB4%4ZV Z431RR\Whn( 0B<?J*#?C- 8!?'bC(^LvH@q7q#S#I#kHg;V<Z!h1@`n`koaJkLqV[hZB<B*!?79 #12   rRIK,-{-nW x#h) 0 #*?*fI0*7H\ha *' 4[*^Bg$b!H;Cq Z^$F9J1OWHO*X*oF7 @P9u7! *0FWOkoribuhqZivryXX`aV?gqPa1ig@ru kSVbH@[IDkK3 '%'r\^WB=*0I-4)# :#S:47*\%1*LOcr(2Qgz21P(2B;$0$0*CbyP+<yk%x[qq x$nB*8S8##!kg^ b0 ~^~Z~AWgLrIvcV;r70jR D Kj:AH0ZaDA*8c#L0jgr #7*8+WFb9oSPxzugoax}o` 35<<5uuFHz [ gQBFO8 ;(1 }n``oQxB:g;DVPkqonS nc^Z;)'~g7"+(f~IOkRx(o8,lLKT BZ'kY @  ] h/ W e w[ r3  oN?21}\j:[XSORk9 _vdPJ.rA k  = '   e {^ C W `  1 n    t ~ _ >9  H   mN   cf|' xXJEn/`gR' cP%-a-jveW/#t_KLn(mazr^x+:zH:XN 0O'nO?GJ,Bzb?LCgh_D zlnM/nt>I?QKjr+o}:HM d68- 4 A S=A! W[ <X kX sJ Q (       n] T T]L8 B  % 6T [O+F'} 9aW3J$hwOwUQK^<$nL\)qeJu3yA6SRy2uk2zL0_}+u}E#B&F0Pu+tE:2B +C'BT`A)uR r4/F~!b-^-Nvd.1+=;akSk'S8v[S;ss43){LzJ_aLi:y  gM  ]   yX(uyS  JT]1j  (  u^  - 7  3;* {   >W C w( =? D     ~ N  ;XrZ HzV`X`pi VPto8yDpr]) ~hqRFArKR JFsAqhpRW3u2+WY457a\LR AJ%MJ-^L-F7*%i:l5A"Mex62%,, &'?rn Qyy@{+)]q@mYj %-3%AW7vF +Qw-Xb\sN-)/oCkJlK%wzSi2`O,-SW {Va/gH*t?=wG_OG=E2d4(_N k4RO 5#}Z(oW/WL*TI #^Yuk LW|bnbSN5<X mDbTook[5qb -.@C!V$Vg`D\) |=zj0=!]F78 vi>{h_cfX_XoUTDFwXMT) {E znl+ZhNS|[$1n[6W~wU~wucy7~M\Q% 51+G-K\mk\z:SK9%m/yWShWoIp`~QlhPo1oP*+hV HxwKy,eQW{,p3|gv Me r\0E:HUS0z\lJ)t s(`?Kq@YOcM2KAkKrHkN5C$)-@&aR}Ra81Rda\Rkd/ wqGh"]1#t';I`'?tGt FX'M4!*? f )< Z WD\ i   : 3~  } s ! O  B  O  )w s   Y   ) !   t _ \  @ I.zuER[gbcBZ-773W1ZgR7Rf.#L>K7U=LvXkM w+&w\HZLks]-iZ&&5iW9  '1eWD  m<  #L   7  t  ``   k     7- b  Q > 5  w /  f  W# K . 7O . A;CP4vj+x)@n39+r>OC{@XaT&Vd4/ EKZY@_MK 66`$]Be#{b/Lt^69`x!o;m{V/T`Ezw';N!^iUv'60FG9t9J A9E& B 7[n"n__^*;wa&9lK] Z' . rXXJ,c} 'x pH ` Q W F   B   |0B}Y{J-&q@Pr.)qWa$#nk8nCA*gBF8f(\KyzK tq35fM;s]5G<:TGN5C`6M>4+'Gy<#b[pB|h8M!!?st #GX8RO}E!h]S; ;v    | Q=^ ^ d r  +U  H IX y dk 2 z;ba}]_l'1Bi,I o }x(f1E<_v 4eUxrCr? T$,)3{I$TW84&mX<%%K2Dc&hYX0C\${Z oPry__r~p]NH*X H^iEjN1(R9[j L o'   f|A Q  _?   f*  f 0( W @T | 'b{f ~   X  jw 5  a.`O#*btQmW4kM=? f+}WD;V9Jj-TW%r HYBL@CEGgu)= x&if\-nn-VIvK, X8 6%OoYj],~"X[d}azr|t~p:N~@m'q0& PXJOTXa3EUITbf+S)0Rd0@: PA sle^NN.q|q|{'8T'ZVs!N mp(jDdtxcp~mHE@VtifdQi~|f_XY`~1vu 1X[Vq44RLBAWS{x ;;;CWHXnb[zs=Tws"-H9:b}j`z\y]cez5fB@+%v=KC$LgB<;`:?N[Yi:_sM_9yv-nu^V5TJ?86?CJ?15<{?Gm;z.iMIbXN:WDY>=Nxc'QG~&*O4K\ 3~`z1Nbo0R%xf+[q';nunuWkfCpa 6E$Eaik}*E +&Els   # 'GIQ]G\^R^Q;C6D559hL1-vzf<<G5U"@ * ti<= cZbaWB<"vzWyS[P# *?* :IySfxa4YZ1y- #~Hg?XC((H"8 4 ;(+$!-6#2 !!J()#N'_1X?m bmtBj 17 298?;`ZXX +c[Mu_XfC$3u xny}g`v7V` f o-{gWZ^h\{x# BF9*yjkqg~yYf{uq{qSIIAZ4^3h7I S?Bj\7VY{x~z^uKN3K=@F6O>1=:;:g]jfWxPXLnuqxyjAmhwVoxa`qguSV\USxgKpczPiOB 'A?a'#P'#8 O\nb~74<1'$1@*#;,98Z1W?8709B #1 31% V4vFxSJ4?7*QSo +I7O2 82J?4-F-kgWQ^-kXXL+rr`o:c'c*k;R KfZ*A#AD:0  ~ -FaS` L*Sjkg"v# SW\Vry{*<;aib$@,;5@5yGz+. =1Q GK:%2W,D:@bCR*M>5RMM:+,$ K12SPQ*9H # $vWYxfyPuqZhZvh^ggBu\YYq?4-jLLogO?x3j^ 3`gn,="-j%Zc3~\g~BkfgcSHK`q\Zkg\KoRkBVDRR:R\xVYPVqIcn{Yu^VLuLWLVgvWnq{\?RFLfYVvc~\qhhqZ~-H$8VSx[}     ,Sz%y,"b1qG[PXzh_^,^2kWJk@<18.+BQ*I }qhieuZ\PhIQ4C8X%I0"J  yuxggjr7:  *-*)  |ftiE0+(+H==;NoR{U]fw~ 7 [*r)hHi\vuzyW?jJvSq7n Y LHVDBHSYg^ckr# @9 ZJr}QguV[vVXaaSZ[ouxnkrXC * < !<*I91L ZOJ24 - Z\fyrS~gLDZAH'H,0",PI)hk7F SQ4u2ZH`uho9z-kBiJ7[@$C2P!B*H$Q+IFIJ4##<4'ISWWLQxxrhui  K"<_9$J9 IZa[r Qa$Q;,2;,%G3%+"""%9T.;$2 zqyCygWg}V`<I + 8 7 -9Z*C'49H89#4oV;'0L XeB[aHZx`V`+gLgWJO zX-#C'+2@'0F7- Jba^ZHBBVIB^o@P;rx<h8h7?gCI?hv07hovorx(Heo73<W[xA]llNTh1#+*uCray?S"\7))-nx uGg/wwNepFKW^NN=<6mdQ2`_|E]_]`li~qf`w/p[NiGeElt_ue|xg="k0'erf*z<F[H0~aV*o_v_o >SU|{_S]K~_C%1<$xg5%*J5W 02' H\V)4ZH30i:"ou9"mdb gfN=H= ue yd}&}>ijtzfXpz /U[cv"f]4IYgRfYR)pfUKA%sMi4 H^ HGyRQXNAR[%/`p~a!QaS7?SuYAHEmY*kh>Y0)  keOT~&28/ z%I9?z?n"kt'4zR|>|S*T"z,?n TGqIBOPZL8qVLc;~:/ji.i}RI'*n.y\+<V  sB iQ3 ? l  ~ G L   & 7   ; `  bB d o  r z \ Fe 1  5  E*l)  Hz   -m $  SE$nF6yZqz-fC@3q=Kt!iy'$ hr&s-KwFP`.O'y JkkZjus1Fl]7`g%/|f`\?Q=on'r+Cc##5X a;vJ:K`6N<6rY4-Q;x  t  l 6h  :  4h #Hl*c>RI bO X 9K 2  =      < : A9 T -CQuI )AX+ ?h]X'dlM]@p]2b{a#`vyMZ3ltTZQ?&OFblBZ ZAvB$2}ApMwklva_)TMe-@Y/XGvR(u 4  1  - N! < t  f8 M"A@Ab,DYy!J6.9  Z\< ^w e u  F   P TF\TG   k  m, @ . c  G vK ^  X Ax]XrFG lZ=Jq(or}[cr c'%g iJPb)|1Rgx2veK$wmSu{CMZI%DoQ"xbuQ#J.%"gEW( $u   !/ JW ~o eq tb X <"    T 'oFBkI8w_"I~={$g+ -smG"2_}v L8Iqu]H%Jr+Z _WN{M8PMf5tz!@p7 ?k"=aSZac ^a v?@nu`kj xGWp"+e@Cq[//S6S+==>MNv_c7sB6 9/Qbs+}E\g3r[Z2\RI2 r{YbJ9u@W9Q'9 9,?M=6g%mfHeeh/)"K1P5%"WXCUOFpla%3R^^{"m '48 Xc4~F~[i(1$X`$z$ <3b9\fI<*1+QCMAApmg}ijNcm=xJ=:zJx-vJ/PQ [WHeg[7[C(o`qLg,2zzxgIK:#|`-(A}tM=< PT;; uuyVNF_Jn@&-nya;ZF}L& /(56v|!QPop0tUt#S{3I'`x(\i=a":Xl2me6VZkZnmKYOn|jnq|~+h;OShSD&#?;[-Mh<VTcnOlrwEl168  w~_!dG@6} ?VO$CH<-gZ3oIS!mf[/vHZ& kcA'% dj[0R#E/=A>mX~[KjN_QHHdx*"*kzc4-:nWyRvYvL\80`VWuq( $DPB<D CB @I9P'2;;91PIzWz%*;3.  ke J[<@hVLBZHunR`_`_S_Ox`VBDRjA?4a)1'8))IAFWugqWFPO1#IKu3;^b Ii3N1c,E9]WI\U]HwEC "*(@<P1=QD%<1%Ip%<+g[SaWXFFJ+W$C<; k?qV^*oR S *%0)PO3D%1''8aO"0 O?SZa4\IKVfOa`Saoo1;i[nzi Q(h9x2C`q 1g; l_ kPP'gX g ?fRF 0  I|]gQ@2! p#%A8K:V;j1nShovurqncD1* - V% "4I--IYF^` +$!@\`rn=[2Y%lMMxP2{l9TKK<1aKL3$+~\w;d)|nKY:|NzqN-Yt w-z"A=- #2E6RY` m#_d zp:PHt'p t#)'"1-SPWWPBLL30=*8faVB0"%*3gvFblYzl tY=+=Mq9~vGyhr~1 f$Z.[,lZ\KX%* xZV;}JPiB4fPW7="yqk`OnK:0=DY8Ox(!9Svr1of59\qi 9, z 9oDp"B<\fs\=$CfShC.w{ X5!"ubiueC^g[abH ;Q2@0`HcP1AH** fmfE:AX:_ gw=_Fq0KIjx 4^7ez$5`W6pGTiR*'6&,z\h8 l%%{ 3sb$! }['}y}Qyk\HRK nO{4"X~%_ @Rg,m/ > @!NFYT@2HQ" bW<2nnlqy'6t"+~K-fbsFz2yX*/8a*=J J'9MfX\UJ[1 ;:ajc{w=-3B7>DG;/ NvG*$M*$ g`2g;Y$\Fno_V(%4ayy~spuGJ=3'(26 K:%=@OF#1-%/""J%@cKvbhVmN[Ylm||Od|n7KiKp9mYww|qjwtqdx]VAAgu=G^Y wr`gxRj7_'fcG>}6J-pcS9 9$m\H~_hBh*v<ZcD(e^OqbcSW? C!xfRnKZSPO1"sh'N@X%9UpX8[MiIn}UTO[H}H=tN^i[[0gQ@dfR2GJsuA OG&"Q-xi.?ZF-8}.cMV%6p)pWfWhlQ88!  (5Sh=pfbp)$f ipM1Q; <`F+g3b^0?i_GQ~Mb5i9]AK1OJO0AN62Gr\n?FQk~s <9wOO(06u G`C+72OOxA@jO%4@ ;Kn/+'WFN-i|o_JjEc,- 0-PX= s: kqaIr([ qg9Q7<7.PFFPICW?$Q Z C #+ nQ#Y\n:S-='H"wXy]sU8+[='.)fis~hrw}]or wv6fQ~dL'fC7}{6DTbzRhKbwU$wraq2hJ hkeQ` 8Bz CdWD1 '~ y     h f?iOsS{E\.\ayv2w"@7NQOs8 DP(Y0B,]_<YKW5@.(t)c"N!.>iC[S f Z= e q=jl Cq  o  @# sQ G @     u8 A4 =. 5 o    -' N U      d @   c U K  sM Z  k  h5  x J khU^",\m?^'{@wQej'4Ev+_Q'!stR<_SPVT_~-)tAO_7X qt=LB;@]9c+aZ%-H_@+L>CIRgfM`HQ&l  O WG6) W r g U  B8Mcb|wfBU%qhd7   `k  y  T 1 ed  QN=E ; Af X Dz LW;zf||YYH@vj hK-Xf[6!'>* :Y%iP*P(xRsZ5dA"tywkBRP, GPuI}I1xba3swac,.xE8FZ|^ v9n p1)#'3JQ1~~g [ 3NB ^   n8P(_26g-/&=W1V?"Nv vf     2_m e  ;  (  $  ^]TnSXtGMy B\{5oVUE{[r_Ih"f u5Q/dtu-[%ZLD"U9Nz:ZMex!ZLr(RW5.nL& C!igPtR `KMOQ_t)(t`qX6|Q9@Jo!;WJX@SSl[S8t@}ErPMMG;S$ D0 iX1r ovziIO-lkv%W!!P`9ioJ10%g0;F!# 2b u0 1M(I '' >Q# f0\S:0f8UI{gWk=\SGF%O=vLKN/>mNT13zH P%"  #<8V`IuF=k&`beW[o^nNr/WM.}gPaue|gZ< {RZ1/'fNIF%X's p,:^mA\3PA#Fh'3K,aZ#, ;#ZHc@^}kxvjy.$u{nxV* ?QZHF+?+- 0Iuzig6nUb>)X2Wl?f(K!|kB- DScN3IU(m<`"gq6wGaDW_wle -u  AkgwX0AaE7Phz9b$@i2s9,:KE<NGd}|w'ww["/)")."C.1 T'r5Q<>IW37A. &h[h<auXLSVP884ujh\*  FX+[=*gii1{Bj&Dp 47LVdcdtm~S\RKyBS00&/mD-XE &hcX*[;3bFvxn`SV?  w)jK sD'{DiQ55) "v}} 1Q=!#1pIOTkT#08Oh{zw^XaOhS4*0wRHsl-0RS1t2r<dH?kgat>67;6/  .QZrtiXeNvacfk<,[xLcZ?I* _G^I#~pp^2w.wg[9 u}v^meA??6( %9/< ^ot (')&1JF[Fcaha\m{)-"FIBj+`r! Zu)-y3*"Wv Be|TvQv;zK{Dh)i p E&  : =Z1=k8%k8ku+\-p\#H71 m~KfMQ=R -_yT2X6|9/}g!)2D?GFWQv68Kv{+2"=OUf@u+p)G aj<~Vi=:Zf{1CV>h$,os=yE_XSM;5 w13+uqSLF9271gSR:~vP3#`3 za`R_JG6.. /&H!V9A,>G%GV/i!e_NKV JG*ri.T "T<w5BWlu1LJu lz=yk=XBDB/z j m-9c6nHS/L%KwAhM1 y!i[H4KqH(yyY\{Pw:m'@46,|pfV#ln5P&.{s}@kgsiG&5LCo%EpA x`8b8*Jr{ l0awnYjwG/>|TzS\jN[%- $"-w/-yk{ziiXKM2 = QL7yW[AI(VkcAWB~XwiNe\z= ?iFPG@`6t@zNF[2G2g?G?EK]Y'j.DKep'"3[:n%v #v Fkgu   "C;[W%I*=(D(S23I% (=+C.@JIbhuiqVX9x7nFy$`'LiJQi8'y Zoc,8jF:A77'#,x)kSfo\g`ID"*  | 7%KfKf*{'34Ic 4+8vu!9Wiebzz!+( 9P5B!al9P3@,=2; Q"8"3*3+Gb"X_b*rp\QW55hVVzr^;X^2@`PzL`-I4<9*2VC~A?#XnOH2~pcsE`4< cfl1l;smT{GUBE}gw9klC&F0So7fFX`2qVNi=c/6iWeaKMD3ywz7^%<.'  UtI]m~y,(( m3/JK  ; = h ; B    9# q{  5 : &z 9z 4  cNW  $i - I  m 7A  o } 9 H/QtbuKO#sG ElFE.pP46s2]#myh1Vg7s/AUD\&K*O#gG!|AIC Z!y- @?\?qS@"*m  *|  9 : k D Q7   N$ P    J I 2   s  K  d c % `   QSTJ  f    74+AK&?0=>$BFBjZvvCU}6]t+@R;,\Y7Wc3 i5~ tc/5eX/U*I+%$\QibfUm -~Y~ "AT`Rsq/^e->;u j8c5""dBHBY  aC eh*Sbej2P  QW&#    ^(a,e      1 h } U   YZJX.~;kf{t9<XWZ}O*TP&t`mhd prY>M k>jn);_h/2Q]]x ; (IOH`8*JzWCK3&#%+C("Qjtt|um[xf]~V:RK7]K@wlmo 0(0UV9|Gq:8YLn~9?Lg7S^n !<2cwZ%2DUgws'ha%]Dn5wdsn{csmr]Ug@eur]`>x"3|<K@O=>U uY=d[O,<cYMsRRn<7g&<$,ubeICB9D~rkI: ~~cWk`7P'=-0#8 :I =,nxr  -1*8 *(+9?<4+O[ISSSCQyio ^vfvubIWQL< OHZOa8DYAK=u fk"IDG_J "'-'9(0'X@[QRo&p#AOW3uPonvRPh#:-4"' ' #*Fj -q4P-cO$ j1ozv$! (CF"Pi.q%^%J?;P9^DCJHWu%1!1*,9,P,71xF$+ WA KBF"-qmG>2"}{h{ey[}@y1~9<_/3|:DvnSS# a or`0%WAfx P WHhr+V<<7@bo7 P*vf8fBcIhScirWazvapX__fi5lZ_a@$*PO?42$kvInBAI-07 cxI8|z4#X@tgG(\ai8Dy-iFgG/;Tnr5,TlU2"t'B7 1E2eL+8`7[3- -zIru<2!bqzPk}Wo[kgY0b#ePXQXaWixnobChbhhgWOP7]/^F}K 1q#HK\%aqMYe}v`wE\Z1d7 [COXQ9#{tpvzHc`\`/f-UCr/({QprtSL.%Js,@ \QTG<xv+1c8  qI2-<$(2~L[S7`LU@YB`O`'U7-:'!9OOixfmrjjbZVPR\%L:AP3A;V"KP S,A`-C6 )uDHw tn]![Og$"=l iai}n@@Lop Z M9xTp++brh'#@J?8i70$H!8#!2M+5%v n%,}uB[EK {ghOs3#3w"t)_5?P _,~,e1}P ^eyQeTP}iaiaX1>%:CsDe#]nG>|V3YCo J +=T_T\W _2vh}a~pfD9,"lihl~_X5z<^7 HI'Q&ypI2h(v`H b|lzYJG@-($$  1+'ZTPoA(/2F90HJmVgn"|+Ez[w>qUuiqpm:"?v*SJ;-aPU/Pi/fIB>W&>"t0E*Cq6/fk8kD(< !=;PxBcM_~v~{{agTVMS5-kI=yh`[?#'uR9f"`'0A%,| +]J:@2bUub= _~OAy! i H xhg {: iJe-`]E{ 4u cZ"Y@g9D<AWj5J<DM,1,J,<-;8E[/_UTc~>kz 4G5f5|f pf<T  nbxnnB'zYY6oAhK1Xiw,[[0/ KNao #(90 q/VYfdV {W1W 7FZ ^2NX{ B(+4%'0*;' 0\*  /w]HE9xkrXD8 }zb44y?Xg Z7C!4^vhcc?y~yyWYhfafD|=Rb ~]b tiX`bbq| ,k *(Yq^e9TiZ~`2Hjc03 DJl=|v~#`  ]r4rj ,=1s`'hq7vO11E0Qr%L v$Y#)X%te8R_vnLT*<>-qj!-: 0{A j~]K-C'aeg_D2,4=7f1:$ 4 m  "     T 9  v UX     c/ U w x  y ` ni x _ ` w gk YA   . }  e ~ Lf ;cRq7"a\*b}(rAc,n AB"y/s-|@9c*MEK9vKHkM]gk{ZggKmj`_Da*T55hBTWi\K-G@1z1&Or!6~*: ?| ? ' %XrA  I J 2 `"vt]1 % ! *! TcQQ   Px K L  ; ;sB+]2M-P  e[5cFV-e/+MwU!5n6E>'%3jI<jRJ |r{kx mX= xP     . ; f f V O  f H   s O   wm I ; JaSuk;BO\=K[* }na0d+KO@-gR3 i;N_)0~G?}4*++N@$lCb, AJ9V~A4 4K \-Ia;qAgZPwk 5bYggh`hk3Za].!8%Z4!&0 A,Q;=o ehO?1g^qx[@0@KX290 9+:!AER76m7!h!@*-CFaIorxuu xG$X%pu;| 5W4"TW8d\:)^LQFT vuJ~WqIc4`"K Y" oP5kL6z9B1m2z(!Tw|(]\Bpgj.B~z\Qy[>s2{ pIG 29i2@;cP<ia*hMiMVB ^zqVZ'DASBH#:n4~G/d7g7Q(= &sK1_29_%P/h7&l}palD,9Kz}rA[+P!cE:`-.| 4A3cK @qv=f-@7" w@(~^QAdlI}Tb1aUh Wp;*q`-:&W>. \}}0|#"k(^h!C%XK}R{@7&> tepZ2G !8;$Xa  "(r]/]|5=/rBIlhQN6Q 6yo%a4Hc)'`Y yKP !|VL]g  6@1l>{lsd1K V *Zw@4>p ]EiBhki}yT P4qDlx\NXD]ml{[zD;>jm0wAh 78?Eg0`$qZSX Xza{7Fa<7Nx:X@pE0{7*~A8d)I|zC. +5Hl="aDNVhB_WLK*~jx8a$KoQ%bh?x 4@Z `+4BSX`=Mj;eq}cj-x D~ zvg(*HofH/1_M@ gkas1M.VyN) p1j-F^zOanI4#?LR pwmnA!&0` 7):Q!_k\(}QJ yA1&"hi-TG(ejul3P-I\EE#Q'uv= I."Z ?@h}`RV=lMmDlJc:%- Mbz@HCRjY]kNJZ<Qgx) H_#%kl.DQkR5Vt rIpLg(3:9BKgS\ :ZP -PFq 9 \l,c\2w7~rA/\$jx U6RD4Hlms  }_EQ` @DCL vLDK=Y"n":dOfCO9(#pAf"GN'D5|ZnvbdCziuo_u!=g\ATP@SC*K%zXzVa-9O@XQVXz(^F7HW((1'1'OZhjYgLf0pR|H:)~NKUGbTf.NFg6z3LR 79'`LP7$ ;KX\l#: & = MX0Vc;eSRJl:c_pZ+vuaxPK&q;< nfJr7=n9i7_/lrlild_io'NfK}@#6a F#.sVV(&N7lAq92Rf8-Kl`MXgt}xrxCw.{<j/- ~tc"q=Bp[Np-[@X*f DQnQ;I O4f,hhF Q@#7!~\tM~?Ig9U6f=]@9H#</=Xi"s_XQoXhcl)#!!/+Q`+qJuXQ-Dx 4 ?07HHAonuBD.=ZW9Cl;h03GO\1D?h;X<,}ii48h,=TU?k?Ek :qd%:p[,n?~9c;VcurVrJUJIALX<-QrobBf"`FA' ,q[b+VoYEszF[?D5~vP1!+.+PM.'m Uq vI ni'CN9(Cj[hI_~P #% ? 6_  B=       t     - _#  0 R Oq n   e gr uk `@  j v Y"  _ I8hR,t8tS\$=.?uqF0{`9sn_4G>Fa>&1R9JI%=);]jjr&0'jZzd 0Me^uR/WSsr!Cf7EEU]D s6nP.z(GE=@3+*o .) 9 i?: ] X [ :x   " ~b    A) ) P4 U   )  0 *    ) r M  N !  Tt 5W?5l52vo'P;67J]K Z^;WTJ *tm\1.~\Y^S8P-=zHwz5R1\`F dd2%X`/[Y=x3 q4`-X+Yt<qTZZf WF&QP?KkJ<q|4PS1}0g01 a  ;<xrn ! ' j & . 2 [  U p b !  % c ! L J[ Q  og f d bz Ts" ~$(w~9WU a,e?"'Oq".0 6[88{/:Lt-QW~g5 3|oOb-U(<&/6w |`HigPZs4bG 73IJ<MiB > 18  @  eD xR I  S g $`   29j@  UX g ~  ;|f nL9x U$"&j"l%jqT8  ^ * v  '  aQ!BHA-|l49^7m(HcHG6CPq}x^{rO>OYTwwRd:IUK#zP.[K;/o%uMm% ,4BTup\9K 8 4 ~ m # u @    t @s    z`   Be  F  G W 8   < v o bc 2YjRHYp*Jb}AWbPu?& ;LL Nq$MR077Mo- RRzZg'sqxswws9>wmRU,h\iP+(+,CfM[AEejg<K[bc,$kC#78Uq=_ dn>daXUo]>ENTEL@TE>pfQ."@@AbKPWNMix-@ UEqSp7]&Xi_|Aq~ Or3v{W{4<:;KA JWlIsyGi :&[bi}:Uf/QS)VVLLEi(mccOdkRt|;a-IKeJmg=KKw >y$sRP3%dJdzHDI^ML1t|wn2n+][lGezuo=i! 1Pvy@  -4QKux{0#?Z#qP@Cyyq$FIy!xvo#0C+[Pgevb(1?9  !!fqPa3ZZ7gAJ uE0o? W!IK!(} oC[;s(6y's@+&4Ty}|/11&-2i/TpBc\Cq[~#'BWQov}uP } ;b WG~w:b>n+9,)&E?/lQ]2-2E==T>A-/ 6Ng5J: kxrrznQ8I%$IuBrugICi{$> v\pVBOD`3OSO<C9RA0k2q7F6Y6PbAZV'H+yz r  +*<1(!,% JMWio.BB@z%biK=5 z"zXuJ9J7S^QFSquoqq-BPg[#i "!_ai{r+2Ep$PT65aJ%i7e87'(cZAqfZ=aORLm[9(&wyWmDj'OC`H)A+ sdSvo"SM/vjWc0mE!SDT*fd l|FY[{cCWr?y~Km%0e{Dlj<\;I2!C%l5Pc(*{Zk f lkB9<?LZy3LrH0fN+0A(i=&f\ kiPX(o1^[weTTI_MNNe2^6 AIQ&++ EHlmdsx-U99zW6VjMis3't   n/m'9155|TZ0aRx-i2sa.KK( ^a[C?2 oO[!v`?)FA10)'mgdH&3-wy~q[K&E>3:rl/^L^.c.#u`/4 ?/@d}KQ6z74Q}zB*3YDhUU.-HIp<  laD2%ao*{ A9}c}}p\Q/:D9 +JEkJ+ 0d0UjM-O Erx yla8q|g6Z@-3^)L.o I! +< BRl*p+^F[ZT1G d?39jPDP [bqB,:QHjWV0Dm]Z?%[:<2n>mGGK5*% j><)c3zLSkLzPx+b {\mRD1f)FkzQC"r&l&fZ ,g!C4Zl9%dAwa4o\CqJ!CJalyz;U%RC_vB ,YKJ9,PNW1k)(-b Tveqv-ztCgYQV)m wgUiReK9bi_[KF( n}Q ETJfVCZ4cDd<\i,N~&3n``1l3*VR- H3hDCjNAKMR/--J  -eZ?/(qk{+RX=$6}\!@}4?*LKg)26hdBV\SSXb'H|)N.lbGm|DG =HOYxV7;V*C#j&`WyH\/ lf =Hh4y@Gp23KF\oijhwcmy_Jj!3l/q/S{M-x1f?^:6 xdH#~?8z-" 9=>w]2D|_X+"`viSK OoiVJZ@aSW`Brcyhbzu`{1hL ~2y\?*Fz|G->oIpA%rlnrE6+E3L8Vis2Kz#x*=o';i,=p}-\A7#vG"3kaLYGDq0{7W"aZ4x V0 tK&" K&S\4`P)'=fz?D{:V`(f+/EE0KCHYEdN/"N"ZkHPfshf -7)V"=hY*v#!(0OXeqhxux}xvI? C@I.V(F.Q*`Sb~azPf^r1!8* 2+*iJ4akI=:%"=*  )uRYS:SP0HSfuHrq$7 !8Sy  vqqg^kyugKn;Of@BID1K-B90 % KK30'-,{ uZ\DD HBK F;D), z[>7&:C&=6AX]E# nI |MW.P6 he{ls9pG[%gQF{/ D]g }  G _t ~q Wv !t W nW (Tc;xy'tX Kk1(r^JAv^|?=08di6}Ef4G vvkoG$< eT&{~D"4 -;k;-z $!_==_Xv4]35E7F6>8  9 & J v   H j   Z r$    gw %   c XQ 49 " J D x X Y         \   t  o l sd J9 /9 1<uY_,Xao>W 8_KW4TM%KD6bKW[\~jgbfSqHblcISy]j`'c7I6?#-Z{d4neFpv@:`+#i z)R#nem ?K ^  gA E    >\qGD[@E ;  f  ]- 3 =/ % $ ,Y 6 N^ z e NLX0$M2;aR'n=-`OhKB5 m%xy6772 <s6%UKE%lP=470]~l>XejLbTX*vqPq 8h}NWvx 12 *: 2M){O d= C  u q N \ R B| YI  0 R  T   @ 92  ZB   o`    /Q   3   y #xP PSq6IE2y}Q%zSk qYNmKO?#2'A%rk5&!S+&//~3'Zs1{IK q{U; W G W ; Bp + h x # .  :qHoA._ mQ@67J`$%uw*Ksv Zi  }  7   ` z< dsED{$7+ n=_a`M'pdZ/]]7$+ 5 # KHkNdzH>&C7riW<8+y(O^I4X=87:G'+.SayhyJ+ f,4 xu@=#F<(9`TX;pt,&=%9q+"CD+ WQN z8BC `\V3p3OHc_I eF1}W j@)Q|T_/dm|O PQdXegtjad\[h8x'O~bHUSL +!O0V 9AWnS\rnirnR?AjIZ!I0Q<9-(o <w._9J"@9 v9@=WaX 3vDr(vQ <2iZLIL;a_ ~wvk5y9WhWSTxWPo2bn8z;-'97+'8HB 4\c\Y^;hL=3tAX)C/Ns21)NM2^DfKGQ?Iae_y %T.U~~{s_I e Gcp@iRtNCj(G'w"~#=O7-a9{;("D5 h1z$l;J Z#ogs#^bvM?P0KC24!#{S%eKv8r:{PS0FugwD#u:q`W1"P[^w{K )KX K.%M?%!)re {[h6@YnXRU[G3KGNm>V0Lu!@e`^bv!PZa+ -&%iM<cdr&r9wmC|h m~.G&*-8Wd0M*18euuQK@#(j<Yr"J y[;Y&xnVA[JQM3u.kWo\Vg"q`i0*uzkn7^+Hy,1"C@PQ (58X\<23J"5* )cHYhHa\b[C<X=%i_FsK< I g @2 Z2rH[QhQS8Qo)Fi(t3~07+7)}caMF _U<6(5A s_dnkdzMMVe[dWblnP}J]<5v/W2P=a?aAq /6ggKiM~Gq1KP8r3]DM+x'Mm)MTChFGS R"5=)zbK5*+"y`a 4;7QS4-LV$ fx,xw:"e-W69{}k&RRsV L}vv] ln:.sIKnj\cZFO(^ l%k=mpsew''Fu6~tIX)X h $DPs{pxhlmS[ss*]h1 <'gw,  e}%d8) VrV|7~tNpUiYhD5vh7KyIu8r (xGVTt^6m'O  zl.wPTia)D<@@/q \ny.6#j [YB<qeu2VG;~j DQm;6^v O-)n]k\E4  ; wI%ss /cG7`^f}'RX]So r+Z?ZDe\ y[KQfbqt7@8^\Qw`gRF7c6RSJQ<[!xY!`-aOt^^Nhe+0{HA22"C\?V.Aq+];{l2P_rb 2J869 ~YeGM^+ZLt[wbpY] mt$B-YQgj]jEq9#B{k*Lai#d=>tkcQ4\\zg}Zn.*g<'8 k (  V N 3w f W  Hv      f 9} 3    Ql"Yo~u,E)~|.68E>=.'uk:MZwTk>;Cga5^GB5+`Z4T5$z[FB{\ZVP3ZkjF|Vy5w}KsZ.EF d5a@~}E4Zz'9|~iS: m ' r  F X o z  n 2CR:5JZ)~rNd+KJXZ <cI[f*5s+H&lxxxcM89<*yantqO?=K~6^BKJL .@V}GMiZPt!9`z@e /(\s\GKh[\twI$;GUoL]_e`Meu N7lm_a?F|n^Sg0&>5]]kG'->=3k_1OuOg;W73!#PnBzq`9OKa| g tm:3 ^N\qM%7%-WcbVeD[hZ#Gn 98 <q  =-4T]\n30X9z%3WP *XgOZz+Z48#8BH!bKcoA"mt`+T{>-XcX$ !uLPi ocI_d!aN16W]mI/Ii|W!]r/eM =H|% {$Y@OAN f  Y"%Xs$zJ6 +EeD*4-7t4MiXW[Iu~orSn"IE;_r}Li-S-,u4D_GIxW$ *FQ&Qc a{rj:i6Ci`g,$'8P -2Iy -8B\QH;]F1QqQHt)rcuJ?1% v70S[_w"_ v(o~ #lchlA?.8[I%Z 5) d?ibhv$g:1J S)F?;7{r'r1S[D9HM [ : 9 cb zw       A _(   mIc.@xg3WgC"cO8kX#E , nogh<}*L+dUx<`1Eg%g5d! O\/e9 rR=H[AAM (I%GYYzbQPcvFvYl d ^ LgzJ(s^?Ke 8]"WmX QV 7 )n c`     nr F 5n ~5R y q A q   ^  i A '  0T   ZA  h'H 1ldA?$N#_i/"2q5 /K0OLG3m4P ` B rQg /6  (|mJ~j1wrK_/;V'#I 1[3;D o7V_fH7oNSXp`0}-c@ = :&0   ' $[+[NDHJ  b (  T Ofo [ F o  ,m `MKE_ mKM6%"P{Z.<u*RS @xkd;Kps!C+q>7s<w-g&qwpccQ.<$B?){cTyuHqQ.w6w0 NkM*xn  d0!S 7   {_ f @  (   h - 7 UA@@r]cYcl.)RV_ i  o Y n  1   R 7  4_$3mrA=4xi:syj.\gaE\L+)& Tzf\i_'0{tM=NmDl]T1 ^Q$/[`!-n y  SwcgM G~v;c1 3 z[2M * V pt n S m L 0 ; # s . w-H #T *uI'{j?)w qu~~g[_)U\F<{rO &+<6 H]6[uqnl0$xys. 'RF-rCSvz lJzGiPrnr0Ca:o\bqg^r}zW`b^`XCBiJ<4*B?4ls&>JJr["oqok+^h=KVqOB%4:,W71g#Df{ jd:2)O,Q-q^jLnv{'%- *3OyZy F^L<O<vLSuuhrn IX;[{[+}=z<%;lDsQzTk*(ezkeax`!<*'!7'\*{L8R_;/V`_G9wcv /&U~>b=gP9z7X1r=`gZguaFg(aJ^WJIJ?Z SDI=lkcwKQWKaG;(9hK!S:!R"O\@ZB)Z=Wp[Z^wXU)3j@%r>-&C7XY[)BrV([~vvqQkyPaa2yJh$r8IV97?!!+<-7<ZSqST"$C I= S$kTGCrD+Mbc{U6 Cx{1B!,1#8 UOb=h quS+tQ! fq_WyFr> 2u!#.+-K3\IDL7}0KpeM]X#'5L .SL>eRd4CD' E?T End)VDt&#Rq[ (9'y43FW4 IL=_W'% I:PPq$2* Sk ( J_Q;Q<GCW_9Z3p1vc+w59(;8l 9,>6M%: 3cK$kK}PPVX,!wDw/}Mj2e!CioqXx@g&<)%BW$MF   >H ;Y^v}8$}+8 |CDr ~4KO3 W1vkk{VYP?`OB pUN }K@"%9HIOMciLGy9zzzfuX(jg MO\Mh@FFb$coYJ%l${+}Pi*"d,x`a/rzyQY}rXaIbq}ozhvq`) o`3  7YH H*@7Xvy<P#OY0v`rdZiDqgnch|xvzcnu[A[HJKq+^Zkq^h"(fV'oK>!Leey^@C-2f."?_ 1;YP^S{Shrd<VZ Ib{7 JgJne;I+tH99A7V/4G[-[ttmm~~UCJ&`-dK-: ^FF>m(i~,E6!@OKQCvN0y#u^Vqqtn[F7V!S!b<2G@8Sr2J9^gorv,jj--%zEI=S &Am) E-&NWoM$83K"`$Jxo?H E_JJtRo0hX%~niZhTs4AA5U+6Dnn&ddh/{aP}[E1 + KwshyhPJZ% "[C$n%hx^RrI0p%Q2bgU>)aP+!/'&F2 apMD2?8!/!)2yhF/iy-!-[VBHbh("JDi\xpwylr=pKXxXp9zrwrxsc{:y<vkav_SaDI1KBl$2}zO*7BgFq[7WyO{4g7 _[/UuwEi:0# +3VX "0^o270izzhH?FQvLnrL;aCX?J* 21[@9ZPkiuhLuvbFVIePa-#Zh=VOc?ungc0uqK4?PIDV#- tqbO"# _!f@=PUpmoUA [X~5(@MM7O H?R`8J*@QuboB^kv oQ<B[ *IyyzyoqXObL[i00I=nROPj)`) 0Fo{7[2pd H3|R]]UzpU+/\:go>[ {- "V*[5oB* y~7cORn01_-"l=YJ(Cb Un \1]&Z;=;~-Z; Gl%2V=c7cA|Mm$_m={O;waYRYQ)5%"xzM{=b58$B o{\y%2$,BaSK5vkPqQH1!!nR'ra-tAqReA,z)PMN<?';$ K%q'b.Cka%'Z[bK%\<cJh a^ EYwgi`iE=n&lQRayE/lP1piciJjJ5Do`oe9'CY^H8n"mOA>pIUBwItGb+J>fX2M% b`uHO"#"I)7 c~]G+& v1veRa<=/\o-\gRz`F?6Z,zxg: zX=<Uguvjd_u*1u3D-$za2lbCX_ 3P-{j/3npmg3T6J N,@y5" }k8i!#R?)or? jH&Yw-Ny8?a#p$pk1"/Le KsaC'K2ZCX6{8|x]"l6A2h;B'(2<39Q<yg`+lcRk8F,g=updNgcEnzutPLwFje$xzqp[ns:rT!B [k$iP!D \OdEtND }lPT.@ U*\J&t$9\,-@)\`: c%Cp:%x'S"@VA3-&R=[ 6zvHvL~e<Zai,` 8a]LTl@6E Tb$h]W z B 883~6GT~nNE|j \ Kw]mr@bJF nO@P<@wkh\o$SnkS7Hc4iW vR#tu)#"6Rg35vbM;i!C{ h=[/~Pz=v!|Cm KC[9Hxyq<v">lC:Lgj2igqW ohVun7uUWQ sJ  ' o( B - ~ ,  Zha|ENd^~*3 51bq4 {="mbS_+jy(4 gS>zlEMI-kNcBI ,H<,bVz4T F  !K   ;K  &  ]`     ) 9|   5 uv u {0 x   Iv d *qR>"Lw=.2o,e<x R#4_IByiP(N{]uq*? k&Lwmpxsun nY]y:Y%i!2veP[/aM4u6kZ  Q I^ B/|*imc  m    `(  V `  E A  lE_  h y N ~  H s I Mj_?hI#] ;%K!ew?bL;L` l  1 G b*n>rqF|!z,Td\^xx7# XCwolb5 wGDo9P5 7&b4  0~&AEDq+4sZ\vbY)}Ng =['i( J K9 Xx l g V  o <    1  \  yg@ L     m   J) ~vXz$1EP K>{xI$1 gq o  m  -E@gcQkvP'25y2rrA^+PZZJD\)JPbeS`M'tBW?4*$a\/p CLN &x# & % %L  3  E ' U D 6 wS  7fDvp7H3ARu *cV  a t  AR  ; F @  _  ~ ? /  &eB> ~:x;%aJKxx8 4ADfzGh[c)%SoyE#=Hiq!Tzeg>nkX+M%hz#%%eE<:[4BZE&9>l8aR  B  _  y  Y>  J M Q -SA Pm | s5 < &".?DPx7Hj DI!$&_}DT_h<9>o2Yo!/'j1E'/u)Sfqcgi~(~%9 [wBPL,1;7@egL F v  0,"cE8 R  ~ ! ?Q $ )cJG .2LOd!2vR=$O\:HZ:i/(!WG'apu7GT5;[RW&{C%bWGGyF 3AyI5A`F}MX{1CdY*c~-uBDK3vrP=*QWF|zI_}FE nc:v]FD GU   P&2SO0;?@A 4;8"d9ey`'-waYM KhsJg z/d1T66 j6!ZEtBjcje$;/-gL_jejb]nYrt^AL;L1n9}>^EMDyze#r _>7]%"{(Y:j2\eS *-a]   ?vhut?ROk nfAu =stM>o)J((] ,}`+NiXL;"0hij"C7/(v^G9oVF+ww.8seNvE}kt"n~I_(_e$\4mL3msc\X5<- jt|DNK@*] k;I\7DC/EXe@oa~vae[#iW|Rss6@JJ4'&4ZP9k4P5Czs&(OQv W?%"`p|)/ -3%3iyMY;*+[8S@hBaB!y~hg \ YS =mY(C|tq`2yfl{& X:q7 qWHF'1a!3ZTh\1bra;k /2" El\C QR =/\rUyZ=c,U9V*)45@5 pTg9"\Wl<+y;b@i9T59<=STkkok?T1i0T WICxvvBVZ ~x|Z40QGb2ERJYtfYH]>A6#@-2{M89~Np-RFPk(0a-`PyuqX@qCnBe9h2*91ieHn7V-V7B(+0 "%<"yg;-'F$b([1]0fJ:3/xn{Oiug8M,q(VaaNX? ,2D)9'P'pa^tct!}9h3mRq\ 7b8k<g%Z!D8K+933s9=/=5H  f{s=[K_BSM+"" Jz<D5 P' '#L (V7uKWD??Z))7?g*R N?X#dA`BGR-Rdbbgm|wfnK:"!q+ +309=[u0kZx[B}hJ<9uFBb@?JZevnzaX!3<c=2XpZyhh hDvK;r*W8zJ`!hBf=Co4 {n8Ixn_qRQ`A2-|()tp~9( \h2=q{ZP9;q+2'#S< A73Z) >-+9 "|Up2~wHo5+!9Y;['N)jI*Mqi;oN}j)H1#@^!+pC\:<7A; R6}$J(8 wrw "8Crk:bn~ - 7;)VOt{@LR+ yXb+=20g0D"1t 3!& `>D)^dVCcU<^>zgNLK:gH232(`s8LiC#a2k8=)g+NI8}u5!iN*?=m_{:&+ARZ:=TBgWwTZl~96SJp`GR5Z$p%MSW ue*- fuA)1,#nC!<9PdyaB5>Lj-{/Vhh9fuPQ(=hXjDz>, AU\Ty%CO'zCQ!ZPh &RR *Rwf0J>Y;<TP;M550m% AAQv %xo0gF~:LO?Pg[m9>2@l5lT |Dq~}*`5(9F0IUO4WM+g4L*o[6Jm9-T"=B}S$ ^q8Tc&3Uikzq~% lta,,Jb(*khh"?i_!>AX_^v N\7K A SIhkh9l\f8zl{_Wb(+ik9BRy 4}r f"Ze NNq&&/#7>JZphPxVh1Z;S ~mVR@==+v_"s.Zh`Lg5vV%OpR\L-vuB(fy{>:sppcH229:ATD5(;Cp]6%_{~ %'@h4oSX l~f,([9?hAK0&filf[h{vKA@a9_8o @IN8N"cCGKK>2(]).W3W m65+MUW{z,x+`IB< GnZy v c 9  0 h 8 8  U , z  t ' mV6NT nG+-[!P3 ozPL*I)07fU+'ID ;Y+<Z*>pj\o*;V% *Q%iW<#"1Z+ Wn-{5R~p Y  s #  }  S 8 [  ]   ?  QRv #{bg4Lh#gimcA,W 0qrgG|O,c,%i<+}ej5rk3 iq,2:(o)>?AC S1* vMf|,\Lb(ZI< flBBz IxbI~Bi vj_C"hBZq]MrAm&4c;%[X&g  07DnW 2 d  D,  mS p "` > H ;( @  e p  : !w  9,SL  -  e 6   u eU X 6 ']r8 Zht)2zB\<#u)]`Cd ] T     vb *q**  H  |4 t  ^qr&"\!F*Zp*{uLw ^ &r r[,l>7K e"=J>F8[4Vuvh buh7)}< $ xI.n;>";;o{Q `6.b9$,sq  | U  Q G '   c Cq y r    `*  x x0  'kWv4m{;O=2OeS[\n*moM9Ie)`d,`2{]iyTu @"g%x jv47?T@*p)5*2Pt]eBveu?I`KIT T   @& n ~ "6  Lut- M*   /  a {9~ i d   0O# o ,7PFl5S"G=1gR& Le3rrs/w7>0q(\=~;6Q'Mi~a oh:%:'sDTYrz=l<>Vs*pA;h   a%1{My,E>;(in|`!@>l:ynp=RCo ozP&@ =un }AEN'BeoK w  2 O 7 I 9\~`g<X?,,YX#!]!$efSG cTTC`b!"{A],#@JXe W?kYJBxTF~>mp6-r2?Xnp#{9{e*\6D]KE-U)q)Z{o \; S2(fJTG,b.!P+vgS097I1gFWQ$#HgA662uYdtDzVU E!bFXwu_-pd!&:37AdEft- %#F`aZ^DL"4 %)D7:;K=BRb $\h>*ZSSz&&,=Q_{*0w" l ! K6E[eosK] <a3:o=,PGwDiK33KQIk2B*Qru}<n\ f n<ke@;%) %"V~h'dz&' %{v m)( tK(g"`|t A|: :qyP'* @#^[^ ^+LF`L1+W9!((e'-XhhP@QS4a CL4;L0Jz #k9S@Io;k3epszwN[gh-* X* g@qkhhP[k2Lx0Q^;z#'I-FXnBF~f:7"uz z-ER:0/`w= -RO:x/9&=J#@gg~|EKwpgj ) aIvgo~WqR $LL"{l ~l~*3IFI.<=IsLZMh1I+#P `8eyi``?aIqLyHI;I2L`ee+ny*e}I[I\\r 9@-JJV    "33 (;3C IDTihaB883.2 uhix9#!#B(  4PZ}GacieiHra;8`S?{hPY=f h)KRPK#-?A4:?$P8\OyLPk[a2xF2a:n(F*7`2^, +r% 1E*~vozL~-~47O7{Z6H2Y"x3V 3H#L:)U)"93G1#?~Z\4~-B4aC7[hQnZHooov5LI;Ov B4V-zggCh=8Slz[svCKZyZ FZD"8=H*B[u"0 8'DS,u7Uam#+H/ 'FIYh7q:`/2&Ewqc4oF c8!xI*58W>AQI ,CD$5%G)fqbbK)=rkk\;S?iIJ*Q`yy[XLI*0uCXZ 7yhZ:y1@V'YAV`,nK0]& f<VHAHts+f 2G7V::nwR%#`o: #R i$Lz}^a4Lwn7"^ O(S;5Z1 @iKP'<PrzxIx t6~:p^-`Q@y%&|3uuOj"^8@5q8\1pwXQ^ V Bro +h,qiC7 77LiLvh!W7c')&u;7C9 czP $ ?),#^!;A?_/K6@O3B?jrn#oebS@.l!_5Ws.9c@$}l=1i ~ QwwV6 kS+Xs j3J7M ?Y^%AZ 98A~)O:Xm QHJIoC_< v^5E+ !y\LT?r G'YArx3Kg+?MPvQL~ oldUEaYwp+K9&NhqD#]E TD+~ {hH[Y#E"M|';dyu Q?;F'0 (!z[(}r7XbLbm_J c8#8>Th$ 8BFw.>G.t>nggo\H*c:[6 Q#i2aZKk}dfkWpl#{$%A0;Oa0,-m\ to}/XDc%b m7p&/dp]"l~}$_06UEJl+<bqxP`W%?,xP15CB?Ib8`wv@?%1u} !E>t-o nPiQuKNA{jJ|RAf`KJ(IabP*!-+"OGNENpL-,EKcK3^1' 2`q>xt@ 1}JV ckhCN=n#"5oZoG_.(:KPRz bC%,=5$x'H\Vm/+n$!n 1qa< wVV eDd}+@uMlV?Xj 95J,OD5w& 14F2QXL!I=hi ZWzB;#SfY_Q2T=_9#v,h)f>zGN&:Vt ~ vh^Bh{D/z=<:2xgj/DC)s{D\I**(#2;EjKQ[$~/t:ZC5{gR'`R0>7Ecf,)LleSi:z3&;QO-^I N c 'k5D)7K|jy7>,whwPkb.c3px}T4Bl5Cx(< ;B#=:fQG%vx7CS1nsw}zh\%2KFIV;-K\>A) 5R3hf(U1`kvr@gh5P{77~7wNin{{~w01c2+y2rJ y]9dUV Q5,p?zh{9 %1%y/c6+3Z\wzZ}wr[z(A$<rgBq$-2|UwMpF~sCYv,zD1\hMRhCZE6[r(5%Y1V@gaf|;8qN ~m7@/27N ?'"" "T"T"ooya@bn ~NJ2@a-rFcJg~.}}=oSyxW8 IW@A+Kg4;(B F  "        "B  # m;}Yse/[pJ|*uO#S 8XZ}+wC7tn<XK({*gY<>.HE%[RuE(~=Gq?R@<*\38m/mS.YgDZ-~QM DaW C~ ~  :po{J$#4XAAW>Z<eM{_fn=fwYXSz    Mt<[ 0nI~ &u'HW0 }I| C"9d^?o=cpkor(] L1|r4-rKY;[zhXWQ# DWR::c@J?iETZof-Z/kR3BS] %\F9jA4}9p.D:@"dD4  ]a  v <| ?  >`   A} G O|\  :  O l \ 9   .s5u       4 Gq  nw .@  Y   -XCZKNsz{%Bo8VWTa5WOh I+G@Q8Z{]/Ib$=WBUJ0N$m!}H+Y^3AF =Cwt7Sj-q|"h@"f  c! <~   JVs~jq}&l  2   \H   ~u   & I9 qU |0  ]( v J@Wu  m^ 8 h@+a8      O    f   LX b% dzg]c%BBF1KV&dxWInv85_<*H=h(Z#8x]- ~e53KqzsI5rtFU  | aA EM {  o  H] @5, d af 2 d ] o}  a% | d  b  &  W fi ^h +    '  a*R [EHE-lg+Gc mFk Q 3 }-  kEz<WX~ab1 `T< ',      H o  w  +  B g 6L ! d 09q?G3~&4SnL#SP*Z[e'4?AZ?Q DB[2[P%QDZAMDWNkM ~c<W$:jHxdu[Mzr>c[nlk@ % #   [ PUz k X=q*Q  ,e,Zsc aV p m 9 ZrpT G  > i y ;  \- A0*6Q[)MNWT!nGj% YCq6[(`d H_+`X~rVqXK/ ,  Nf .^ V G     #   h [  7j Xq"LFCu,/ V b{1i$"&qf3L~iSsTVWrL!M L{qr)[sixYc 5Xb~4;kH)#czB:*FF'|4Y(F|\Z HC'mPsmC;# >`]'V.g<MYMK6rL1s il(Ir>DJE`NS?K*VD'Aax5r  44v< 4 [C?yvy1QL#x7nQRSOH;f'O0?7KV;;:%08VWP'DDcKu=BSt Buk,\u8} bg1oQ[-  =jYq--\0*;=0 N/S=6+: y+k8+hq7(xP1V W:8HV) &x3n xQ O@X@E@Cnzuf]dQ[Kd]w96RwHy'^ %7  +69K   ),zbZ(iJJ7xqqCV'uZ4nrnox8EUBj C->(i#b9H)X_gbiu2g0>>@+0#C-K+>(NH:#A"062)d9n(z~n,f#F?IkR4 )=S^n,-(1#=aVuyZvi\v{X=x1^ruuP`3iHyBSW a Q2@ i'mL8]2~dCaG?0 B+!zjU[!-`UKtU  06Y@VO]zU9^r'7arv    1V,T;3]`5U7 <EJc}' n[]SLTJ>T`^c]guW^0-A O+nukgj7N>B VtAcEX<l 5urvJL2ncL'rO_Ltama]SN?JW>*G)@# ##"C:2YbgJ9hAg[cd)\JbyQx4;`,ylooo^zqriziQqWbcFc$a7\!fH2LJh@XZ*<!+#^2'fL;PqK '~y"n%WD-m VVuq[V /=R62+JR /7X-Y"+FN%pBt\LODoyx  kR0^WBDBF8a-*='FL huq;7S ' { %~%yyfcV0* g m> uf_/2+"0eN?e/N% | i19[0;=Xw p$-[gw%-]I=\,,iH<"~_y~_PS2aKK.B(T\M(5*KWXXp_1b*@oAb:J+8  *`tnfY=\[}^?]Cn>R4vOO<K:W/P%qC+U&5L`tpj<OD=LT_sqit{j\RJ5 R:"7 D3ipPl Jb ougcIx)BH*F\ `=\q^-Xx+0UAF,%b]v W[c T6(,E?r6}};z&5h>j!J fG#7Wm'->s(05gEQ)SO1xZ:s-|d2T"xq33^M8k>iD v1GBX E\L}h2 A s#!dNrJ~k4  X  % R . D z j G r . >c|l0hB|EGwttZ~* S|m:e+=k<B  <.T1M`dI" zV~C@ JP>)]?9@afyR8-J,>!DHT Qa\Udj-/A1K#HDj<DXN  =) c x Y{    m Y z"   lE#4\`S;=noe3+18HjV'V \YUPPaM@%\hx8a!1,!iyY GD4E+Ln=+(;L">r/%a4cg@k8s+Zee4=bq+UhIIB7X v"MZ\-Ig#IFrP.aM fXC;ivqS'3p/,8NtRsgZy[p>yf34*%f{.\~skN~m{g^7,Uf5'%8aH| L?I}f"KsDb)cpT`i}Z<I$rP(T9~9J(\L-WSS[K u'S0B\7{[7f L~kj V{u~Hh\)V1 R:L-ZfA7vK)H: fQ=Ng#m#S1xa~v:r=u'ycv\Lj;'SI '0B)B-1KHH4ovj#^qkq X12T( CL1TT3 5+Tu%HiWS[IQuHr`DW` WXj(c01+q-WaVOqhR8 1*  f\-=1`I*%S:nxDW4ug~RjKyx~W(}xiFL2'4;b[iukv"(Q,~J53%{bsK2JCS$c5W1"8"=BrPX+ g2 '1  ~nLq\aBckogq1L8KvjPV*YkK)*1OgWO#c4WV1V8?#%DI="%-0=,=Ofq  \fy#10^D:B0?') R SBg[I*XuBLY3`*V^+CL8Jb[Zi^J+`0Z9@5i~co 2P1Q^$# hZ^knB0GU-20&X@W~1=5le}j3-N 3[?N3  /_ m SC =%   R_ i    C  8   `  ?D R >k  w d   F/-Wf4tJU v.^cy*jIGGyFeE){:gyB*{y.qKkkkg2)'lVa1."{:F;"A[ o\aS;IK QN  } p l  |) ] ` A Y- & k TV 6 e ]H F  ( O  n w O 7hw 5l a [f m o#d5eOn4eWGg(]q e  3 J =  2m;?k1rY{BwY!-p).4d!Y`MT>9![^*ow2H/X!QKUuCv@!6T%cJ}**) TKVqh_ F3ar~a Z@  O nb  ^ s xk 5xMW[   A] ` x .  R  ZA   (K   l _ K < /   r ?DHo@p[)vC``g*&+_LTr8oP9\PF'q ]|N0Jwkll'`^D+9sxjJ78=[wF BCND/j?]EMmQI:Ez(reW. 6pw; I  "  dZ J n    3 xk   hI R x I    ;)XQehp#Jsz".%%iO<9:`-9| N@9B$F*V~AWije]3Z87\$M 79#>Dc *M`qF("?Qx; 5 m ! d  (g ; %     ! f # 4  %v & O  ZN #  ^  WC  U%  q   Al\ )  c W  *  @ <4e&I(}nrA Dx2}4 (OxWu?K%+BL}`߹@ec !FE_F_%%u%fTS.\ 5  F i  -\ g` Y T    m2{}e,B`h ! w  Nm K-   K{ K   (c Uk   k : = 3 *  c  w ,  7  <; b [;`M,MniK/"Por+clk W]<`o22ncS0bdlZAxaE[G>~fS*A<^1M0  }  V   ` " Gi f /=G C&eP,\k&   B  9c G 4 / m  Q a C  .  X= e P a  I  WGLCnRg-L5AFOK-62}1 Zni>6PS1:Q`THbna8E Dj:r\)n2Lk]qrQ&wh2  R  Z J  k  |  P $ T \ q SRExt-}x\#2 GLB?x+vQ KLe?>$0+-A}<.& _Cx p C j c  l r SqH$/ "/z=Lu z 4  , C   { l xfWhgM0$5k; Af/d| ^.3RIO9rXvIG_z!>6fWZY0?GLAI)4C7@RABX)zuuuv0-'O*W{(8DPkeskXZJ`"vzPvZCP2*VV{YFA*j"ugo_Yiefdtxw :x E(#/ gH/`fuVVH&(2CJjnjft`0=nI\7xLX.+ I2@_Qkbn^grH^ o uIXnybr2C1Q+a0Z}$qO# cPf'X[J@)(&/v9@G WhCF7w#-M6_p (,J4>4=O_Sfy`bPfOnuuS|h7!^?SaerCQu(..JSIk\[=@aIspih_v -A/,&:>/eXEUEKNc}s"/=s\w=j}t/RR[29{CK$w,{ v:z=iq #L8c("m<FEi }"v;=   Fj;V;OZp H-}c6f3>Y>vrS"i ~;1= CI1X{`}jnr`Z477"- 0+jX(;W%ni8@ 1PvBw::eriBA,y<vyblloh[C;Q@.1($;If+f!3(CM8h2jv`JWHA,V~j_7>:l.M^@1 ku F0>C$/057'n8ILMn y&4V|( E5$?PUCALoe] 96jp`Uxf5[e+&Rb8IV8;IP 0=),**D3 VQJ>8&4_PnujO8K} {k7(z!@V{=V5O=oIPX6,1?{I@9`8H ;p}qoJQ  {kx`+1jR({Aq(#OR>fiVUF?)nYV>`)Vr+\fV:wXiGmvywgUHX/+ U@0Ssae^Y/ r  + 59 8    9 F f D  A ` (z D : h e I}, `2UIu>)46c,$M2Xu?wOK\g#o Cbv&S@7E`mZ/B[Nv} 3~='P?JeO+81*#O#vucY;{k3%3w;ZpWA1/|xpiX1g"{*#K %p9>u;_=")G}KH{ 4B4He5d-n[aM  (,<28"M(~Wv8vvXeB  z ($\I{sSaSDP( K>uCPwfu: #=" p)^%C}@LIt9sM\,~ cWYkb<]vJxL~$Xx;3b%R>,]2Jolb-Dk%Cy2B{?YRLFP 70\7F`4WZ 8K wGPGfXM[owbMDl<owMw2izzTT1KS0k*B<cYOIBy:V'zp]tQ_!/eKe,Fe^ME]n 5_ Hgxbo/gIj>-FJ|v^N. 7|XeT \8y*ZQ%&SJaKw lOdw ~TU;6i{2iu`ZrKLg(wwVX&tw0e3.6 h> [B i&wZgbH(Wk DuqH bof3z-] w/:w7UH=M^ ; u= Y i [\=8  eO  [ H w 7 * ~ D  ' < H83}fF":wUiDP:BWjEgqUAM ROA"BL?p5n"#kveoFhZJCu&Zztq_EI!   _   $ G # < F c ) l < ! 8 M  ' $ : $ N 2  ?   z  >  . )  r Y -  ` 4 L   j 5(  +d6- ?} Z< $ brx-l`0-uE]tAH y= k1 "kXtz)/r+V/O:nM-_[)^="Mr.j,u B )e $- [*e}sI&%9 &is%e0o fAzVY Ll f >! 6@  1` I O } s^^t7)Eg%  2  ! \  D ; = !  '[  s 9  J9 Bi s E e!3199Cc:TX4PpO%{k[kVf O20!+QLa%/D8?+f& ]A    6 Z ! Q\ Y " ` ,   1->m#':r?o0w{U  }N  f 2  q n J @   7 W 9{*). j D f* 2     EtY3aN"@`m qZ5f&'<sg,c%yLe1"{6F3l j+.+0o-P_ 6*2S<  X   }v)")% z   } a Zm a  ui  j KN Z6 l +  } o8`L>IagRT'k`WuxJ-9|Z" {1WSu836T14I wG{y5vSm[b_cq&&mWK1r;Iml  y   _ u   y 3 RV~d%93Z8$7?kK,BK&$O.  o] "   ) } '= #&  y f h w C $&pCUF](yHVK)u;SE\c~C ]]U/fI`8v<7?Mq &7G%W[q,@/HD S A  1 u ; ` U | -xX:lq_Z X3  ) Gx  7 S  B z F eA t m % r 8  ! a  ,  `G  ,X rvn7"N1/h Iqw8;c".tqC XhiNL4O&63L'{S'LlUx4S!#)5 .F aQQjSn1Jxs-u.$g ` ] C   / -p /  l N H  L  pKa&Bq + '7+0kkviFkuUl'y `QdzTbSA+=hk///xa p  Q 6 9   d I#x!NfY0  Do      oP   V-!f?sm9Pu"n"riAr f.F1vO>Y!:1YM6Q2s46KDPV\z VRXYGC$*bW nQxOc;D4]>m-xtl#,Q`<i5P$i**nfIk:j;i#exElgibw?R=ug3uRn6]mE 95Q*_z k<ryxhP?(oH  @9Syrz,iss~w D zk,_=EH2&)=wb<+_1e4xn'uW0yr'kKoHj w*7*nU2xAx xxjQQ7Gx`m_Gu0;K:V j~o10I?g#a8tr#INZVRnB qb$jTs*q~u: wovDW{JXH2M3+:5i`e"{SPfrzva* C8! .Ag9|V}[??,"uLO'7,0PN!wiu9(]oYOUfs(o2mF5""6%TF2_GT?=A1 ) f"wPvQpU F6| 9qHg = "OP)fmmybo P8a)1t:[J*7 #q1Gc,/cj>Uts\"Uq]MC5>\> Pi ZS_y8@  + .MWqc;4Xg nv <Wg`I?m qhu^ Hz$):#^R#fHLAfqYnKy4 ;i@ +XoTSaKafMiH6{Kcwyh1[-A~YSdrV)=I"8VC[BBE&xCAFHG @%kWvDLQh S_\:1;3%Y\#a6Y+~~%xC[C$il`Ku[Lxo0S#< y:gh!qW* a~ C!pyRA]V #O_!?S5a*0!Rn>SyE?p|KMy$>$[D-^Nt_~2Fj "^HSqJ]o?H-O~X$#Si@W^<4?)xqhc;4 k2w9~)u`KW% B4h2FwV1tZk&51LG'}ii[__Ff*C9~fzl{T9\r.inGx#onzA QpRgxH#]d|nj21c*ct9w o8% fn=`G2"m. lTS zp3t>svn(v[p =}-|~Np{=Ny\oa5Q+>aD[)3,X<&TXs,M`6;W;K<SSL Pg ( y IFO>G`)/!j@^{}I4p/`=P~j\)NR0`I=X-AJdH#A3@3R")2wW%~ W{9EnLOswG-P'|=WCW/l] Hua6F![7OFDhNA]_{A"9"IurI4!Wo<(r-{%'kYYYN@p"[DsIWqq74i1"3+{_4>O.=]n9)Q )e]"fhM SI 158k'(syFe3-?z$C& |K3~xAJ|@[)7kMy|r .hG\.V;6-:2OSAx1fah#X| 'Q;`,,QHG>at1}^J>G&'nPy-N]"MkI?{2L0g:8y^^v 2kXY"\Hj}2hhT8(OqQF?0g17\;P3Te@+2u?(79ZD.-1 {>zq7~s2c(i`J*z*JenVoeNLfD&&.^C.F]Co&"G \[<(ya+F7g; OR[6qmuY2bh@'}yTUl,.}uvZ@B>qx 0o biL r{N@?hwA:+=?&lP0i u=YDX +GJK;IjJihC[ciX-drwcah=L~&[pC^FDI z+X: Xv,7wc] i;~/`] Q'(GWzOH%u+jJ`}@V##\Y{`VF w_f?+yQ67!"u#W (G$zLaeaxWGX; w  ^ 3 Q c  \ < y ? _ | Z 8 1 l h 4 = r M)RR 63w=(p!"]yYcC*Pho&'-$yMd]or|G'm\or&`(iQ{uYch[(c%Y-b PjXNFT1> w p c  m b A | 3 aH .    _y ,2 # w f g l  , j     h 8  QR  w CF 6 K M C @ R8 ~+ P J J _ e B s U i  . a # O LVmZL[I%yi I-OoE9 "1)e'X|VBt4u<[MM0&dLjn V 2_3PRN\+W+) b  3    j X=8]YZsw4[_dT5U( u ? : "P  -u G ~ N0    g " ; w      o- @  [O,wi-$a1'4YgeOl-9;r0US J9TDY,Hw37s)\rT{p}q1p_m)8I^5dMo|x1i"I7Jy /   ' ; He;z5_p@kYddj 7 g   n  5 X I .  !_  =  - ; B2D *  g Y W d r  y_7/4 , i7D84b.L$sxd7GQ082 hBxUWRuOm;}}EEtG219O6_a=6   s #  X el   z 4 g \    nV!2\}hF~E0ys MWqP,UrE <  P 4 @ H 9 ; ?1 1 Z+r<a  B !  f8Z[:p<B)e Z:69HWmC[wP]+ _x3 Fx6f,-nC&A?H 7`mNGD D [ s 5 N  Z 3 q ;  yH  .W c a } n  - ff,[SZ`{L^ 9   i Tf   CoJb#aD'9a  )  M n  -L<0VA%"~ CZ>_D:k2r?M7%xj zN6r/e0 Z w : E  t  YCJSXS;&w+4i2tX+`VoAf { / Y  d :MB"9W(7Lxm   ! t.\p@rAZe^!=E:gX"@_g"-m<T{GT]rYm6`xRO}NU YO~^|L_>a,4Sn#;|)= ] r0Sj0#%{%~__7@ItebRq}`q#D/Y'd|CFwux= oLW'<{Lu+{#6wt  !X-ZrjD-Et GW;sU<@6`QSk{S6-hy[;`W$e'{\yB1k'*KY3@,hpv#`W% ,YV#*o$H v8D9Q78}2?}hFW 2zj\~//tmR 0{Bq@'s +y _cQX"G Cn!!Op_j;Rq3w_{?p^k oy'#d[W[7{~g=DEX h^ 00K#-nK3UN^vFBKF!P"GZ:F5n{7mi#Y> JTTke@> nQ+dl~)fQr #  Z h# C      \)  Zg= AELG-am;ccs to-aYSP9?+kyG2i^u?z4'[pT11@@+?4iadj%c_UM"{9v9^#IgE59w@2<D T`vQk'  u mkSNNEMEC56xB{|]KlO.%]C7GnNG.r^hO~n]E9d7C<"Z+JF7' IZB;0~=XsnojfG|U Q' Fh`VW!/-Z%/}^_JLl)s g3*!Sh(c3E  \-~<c\W9 !D^%N;GBA  MoTwlhwMpTp{?N_}$7 iKE&,$?Q6ar2Tomy`|q|Eo_M%. bLT@M02jKa;=`i ~+{`&GS168--( 6J/zQ)D B'~3Pz~>U6 Xop?thWeG8.6v?(% 9. ,-*NTt /qq7Qy21X:Jw4%bt c{lPs2ZCB$!Q7!L kAy1{`"{7~a:~~qj *7*WSRRIo ;I[ivk!`@krqvzkZQ#rBF h^-*= ) :agILPkcRLP{rW4*1<[7O$ 0?WSX0+P$(bWnz2$$I* ,<9  }}rno`LS<B#W<!x!9`7 a$0 hhh@n""8BA1%DA j k0B w |G&O@CN7wXl6!~%b63)a*:_NpEuT[-6~K& E < ( & < ;  ! K P : J Z ^ `  t S a 2 N  w . N /  U &xhdh{>O+,GN m@2ev ;O'Iitq=B dd~!b?0B`!",f`D]>4F>|&/i*X `IJ+CF%;W l <  J  s   ` = b * e | a w - ^ z m c       u /q  s o <@ W , Q " c  z h F <  +5YpC"]NxvL ,l7?lGv+q|\'-q&O T8C D}.f!G-)Gby=)9nA+8%>4'o5( a)'~ud 0<5$N1xj'l;z|1V.^y!R v]*YUxRy {G~O|s/sVJg=Op > 0  Kh w/_Os?Qr   # Y B'q(=/oJ37` B M V  5 $  n    <`s&kj GX |H`i! ? ) pY~~8Dr%m3 wlSc"j V ~I(|n SxQy,q I"<)8RtTߦ[A߆}A-F=1a`Ch"@ n / M WoF oa^# f 19 2  y b e i z L i  Q H   ) b 8 Q C I  P N  4 ( MCF uO3|W 5S(,_K||v^.S'~,w7`S4"u<qHBg"  W % = ; U  B 2a    [ I f A  biH_"1)/P*@sUIFo'XOq  9 Fd <  )y 4^yyUQ8|S4\y>2`y2Mox)L x%e1L/hJ=ݷO~ܞ#ݣY$ Xws^ 5\ ] 6 f P DuN2PpX'evrz i IH _M 8 I  w w (} #a `0AD<H;Zi<R {-Dm/[l=YW[?p4N1U6GN r/cY k >g>Y L] z$r+nC2o3L=Zx ]ci1Z{gqiQXqvJ;p+--?1O-qnex;oLH$_[pf~\}zXhC$e]XI$L*qhraDk7=YLiSQovrL3*Iv !2mQpd R!0]p{afou-Y 4O!nJb^XeQP2QFnPL[a"z2[ yJp l ","M>EJE:6d\\T|Ym{gw3l[`6M_Jq0k'v:{"?b`X|~mP98/Me _P/"^ DK?Km <p#}3@GRX!>|b V,q);+9C#H[^PBDhWZ h  G yp_hZ22xv{Yqc8r`-P=0m[iQ[-=A{{ipX5.T}rvWFnMT>kTY_.V++?ESk5rYoIlRltr}(,%&K1~@i^} 231ADtt*h~<)F)4@kyB- ;s:t i[%De)C ~Iss8K,k;kXyF n nKc4B\:`Bnn((:/zg fYItoFP )t z%) g %'%`6Y9t53W!'3:vzQunm#== qbjOnb%IF 0?j{kfgnr~oAZf R?~qnLR,LkuSDO**7~NO" :!+NdVT%KT T.m%h5"_sDw1X@Wm/V@?s/{[}Ed=7f|dJ][ m"U@UEE!Gm9#+b  R*m#X|)L4:t|1KS7Px`IB 7AV0VDxqfxVcorj`ZBL`O4"+8 +B*Bq9E7Q{AW34( "G'g_ J@NmQiO2KRu 37'"% # pq0fHY=AGg{tvVW~%;18RfxfWj^(82(-+JaxWea`gqvPu?ChbhH+V <W+a2JouQ@z!-,,2!2L$9XozIgJOPH7H;'aucxfR{ !*;+Zo482;-SqxWqgoXX<9Zzk+o.V!;2(C^# !h98(?IPHZO@^xSiS;@$(*?aI[P<8Ze^^?[ez"k<uy`P-0zebI`Fygh<LQ-; 1*S7`^S-q}yVHob^^52[3 y3xv Z,;\X=9iCCy(W1HbKkQP L OMcJQg( qWVIbXFCa`Wr5 9( I1"@@pbplWw@hs+y2QG8sSTbr@ Sc _[ yh+2<=T*x5QyLoQZ(L;SH4XB?^ ;;--!099  (*\Yx7{1Z^ajrfZDnSFuk'm3h{vAKKKV"-jY0F*SK u~0jvrFaR-W n$HW-W?0*orZLfHh0nhF Wxy@hW'Hnjy^FyhWonL;HO~rqr{qf-`*PxHZPDHKhck~xyjSa4 = F-c=~KK~vx:`-gfHK-`=*8{ IL=0-^Yn- %8=V ?nV jvoy=hOcKox ujr$<QHf!r7zvk932YQOWOVvvqf`h-oFfP oCYQBa*B0K Bg)A(\Dfy%:jOknV`8 RZ:o`L="OO;7):?VOYny ^VL'3yWjc)Hk9VcD'Vo`HVZR`yKKL 4 5 \ v +   X4xJvv*w/c2prc970 h R0OmYt; O'x~5 'L#QSzIbc+_.z3U <0v"W5r!G$jm%-<IXkL W J M ] : U G  _ s  :|  4 a  ?{ l   7 2 Q  &    { k k H c D    &   e n n  J    G ] \ O 1 W KGj%~hI`[~;h]. |AbCLZD>Aj{7HE|o4KUx[]xi(W0_2xoH16=\V+H'tGSh^W}O8) 'vPV   H    F `z " e1IQaG,#f 2|>  8 r <  f 90 f   ;I*;+o*]E^GJtC?C-. Fwlqvz+s 81z:v+ne<p|9dJYa\r%z`;-GR%.2Z(g\,ksZZ+ =4vfgz6C zZ|'j*ax-*?[N3IgH?xMD{iuyy=4OLmx ?K h <  h<N &V;W@]VSo & INC-A   y p W  (L  4 / ? a V 3 c*  u K  $ D j l \ n  /h wj3jGZG8wj{(8RqE]!DyiMCMSI   r SlE!mB[SnrgrrV+  H~/If<q 2   1 z  7|    `    > | g ^    e .  u| 7Y>wZ,-Jh)]>PcjsW+<^ 5-\ i=1O`~l0gaO`5w{bcD\$609rBijz7WEp$ i-   f ' C# )     a# u  Ru   / V  Y x j   4E_@|TL  _f ! + _R .x |KOI/CT;k*V4}\B1PD{KqL895tHp? YfFGL?S0l'E! <@H8;J`H" BV V , rVv>=%{kag@YroO}rh4  & F{ S 21 Kc  !~S:x^$>I,  d $g  W 2 $ ` 6*%OQO\{}XatvH?wD/}?"pCj R}BnugG_dtz uNRFt\yjt=i=X~Wb#NV#ufVgH}Q;"aAjd}q%7Wx:'iXS-,:FIH'i8L3X*0fjV3KA Y#P7;4K{?LaqaPkBP c+qqYMD3s{$%=z_=9u VE-,'DXU0?{`H-B tU-W3?GP{G0NFm$8<kR:;hr'y3n' 3={&{QWci]b-vDMvf@sBqWOg@V03+-!ab^Y\gkc]?00YkjxIEQAwl06:d&Hfx_iK:jwd@ ^`1*cuBkHP~#a+B4r gi7;F#biaf113",ODr xtxwJ/ ~\ \~cXA8]] ssbK\w;>FKpvmi6Jp/'P!aQ3{6t(6 6!J>HP60m*KjVyjIV\BWV{+Jf?L`$12i{Su:^YY^OD8g0A kC?!%k0up~ UgJv|-f;u: mQi+t&/N"-Cxq2~Ut`=O:&bnfnJqVf1hI?r*#v,x;v0eyug^O^FHBQ[zbQ[GiGMuIZZHfFXC@bXgl8Q=fp2p#IJ~?s*8#B(@Z8G$ ygy*S@SLh \a4^^( '+4k AH:K,b, i,A4N )G`CRtjO4DRDjZc^hg'(S! 407F^ig?9Qyy}b~SBQ-Z'SF:LK~IhS,fjqg?c-: "`/OdH&tJtVOdjw~R`"K7/Q_7Y9mKA+CYC"uO]>6( JgdudnKjKp7!gXu0uj qX29"x[[R-&2VVmEfpp]ViH*%"KHI1) #  7P%B^uF#Z0hj44Wnon-0bInAWV8YY(g`:='E#E O)0R10LcVg{ ")RFPyf)-a Lhn09-[e2rv<  +9X=bi+*MMw8$,,9~Bol2<G,%;SLxaoIh+x+LH P$'0i7kog-xO+#S oH;vCSJ (F7LyWbba }P(V$9 $o$qW<$e0X y(3$(<9J<DCc(9cw_wbBszQzo  35JasavXlM1PZobu^`@i'hibe0Ix4[Fiq'+?QH"x*? *3uB^Z:g-*S0^R~Iy;yC9uC(; ( q#J2PakzZLV;<F9S[xyi^!55;  Q?@nZo jkok{o[PZuf\W^B'$Y\fjnIZ-KK'R-\P KB~?PDyjkKvS00Wv8F#a ?Kkg8kxBxfkr#nRy*HZfuS:B^rVyYxSvvW\I jFS\On1?V u{3~Pa,S):;gBc4\O1u{'afrfO"#*acv$Ar;01XK;-;x0 V#C$ ;V@Cx-{ ge ;v 28<1aI`*W 7RgV;kk~Q(Q-([Po[k0H`n!}ur[hqxg}7Qyv[VF   uxny[yZa(I=W P}Q x[ZQ;iu0+{g`98WiJZ0$Oo-fhjau0I  7z@ [O82?  unB KbJSP5GXoG (5JG Cc JVDv3VrJ4Py RA= ?g , Y?^8;# ?7{K)3 fZ^1#%7Snoj-rLy0O*)nj #I1ASe\XPJ^VCqqZ9gySoo^k[oa[<uPP9uV01(;QH2Y` 'Vrqr+$I?`?[CyPL#'4DfDrnoDc%,R;u'?1Z;xJ~!qRpV0Y- PH[?Vx ) 'nogW3LrcC 77Hh^`HI[?uJk!($xhJb-Q1=LFB}BB{1 x{nrvyZ%;n *,v-y:0)3#4Vk,`=K=:SLo{qfuq{:7=o Ck$  1zHa1?n( Q 0Pq^gaHHGv?o81V^?q BB 7^}}((Sur*Z4JyX [W}nv8o(n!CQi`<^ukB[IQV}%% `r(h%eQhZz,! }i<BvH*ez %k<'<'#qxWk'O b^uS2rOSkjqK#aY,RV)aK?$k(X g9V#uDy3^ D4'}[?aI8xbW} L{7*L% ;HSkPcF1HPXwh10x8g` x~]zJQ} [ G'fw3 =e GA* Q ~  jR!p3a V Q | P Q  T % z5[6 +-DKr@%(*"K@Q>Y $X]z}Y__1m%<F09+ >-W@ :xn:#mPd` 0S t1~ Z  6    f  V  L \  ! E  4q:ZY y  f  ,  q d ^ 0 1 i ( }  h e $kU/*G-4vTcuxFe q B l  z = 6  O w B<~U=R~%YAm+}-FQPQFW]y}Vx=p-oNY9\%/v4d5yoK MK[/NkWhw.uJ@lT>$E : ^L}8m/'[   T ,5*sK}'=u.'jpzz @ * -   U G  s 4 x f  X(/<h 2wuHk).  [ ]quNu9EJeRT r[<{!D?n[ @3_'r3-*OlM NNY6WWW- ni  Y "  r u m *O;bXxX&IU$Bqk=x8J+5N '+Yt0DEEQs=#\ hS7(C)khu4[iw61WbJ:bp$jF=  % T %  A  2  3R}y+#S}IbR B t } %  ( g u f 6 .  c  @ U Z r T r  l g   )  . r F y B k    a F 4   Q Q}Or;) G6}T33 OkGs}*/Il=[3;~d2'UF0(rs]OdVHB`lTz%Bp`CFHb&Y Fwt4iE3zqb3 sKR$:' lwah?Be#v#i(vmIzA,9.3>kSK+ G8@4q,`*)%Y?Z}$|<mZ +wRi~bzFU}3)'OU p 8Ja^ n'x#u[ S4YCz% ff299`o8v'@:z]tX]_ w9 kknJr" +1hzlrw~cNU;+@,"?5lms!9q9kB;%P~(CQgz?*XBy@.TX)+{kf{lTXYNRR,bs h1%~2XX8^8qjOK8*+z<eKgBDmYOFJrwg:qqD'hOnJ40fuh88=Lu8u4WJS"Xf a"pu h-au`jv~3bnXYBPB\VFZKqqP1"\jWn[0,:8 F'%P;RP:c ;WP17;fRzwwv\;xa?{:{,uKoSB-` qtq )[zq t`a;4YKZU)UZbuX2Y'@a"B08KxhjQry7xvJAkZe Pv kWBJWC9Dc~~*2Vnn%8f?:^~mfYFCu&>x4^xxB ^vF`S^m_9DDw3 ^19Zj5Nl7 [9%%dI/#oiY>d:zb9Q] U:(g AZ W-\ c;+ O7e9T[os.`{3 Od>h&.xhv1e'#JBw@ 'a,s- =C=9F3UvBvU]suxsPG h~GrGr6T}skw_6@ EJRyeT0y4r:PA=WYA0%"#wJ'fw OgzNShZFg)J;tf6 :n4qKf2Vop`go|q:q;yF7a\qq[4Je L!$4I$`Br0`egunPFIx!z9?vu H+ q=*u` pwgjg7#E6&PX~{G E/:Xec_lws~P8)A<_RutAGQRjo{~lNuj"BYqhjo"; *I0 ~o3c 'e77Wi 1V qx{ *vOgH(un9(9gnaV -"O7766+ +33!-+E7xpgi)}X!F3Xm/:X"i0:]{yuAB)o6'?"=<V`1Zhq`*2[nWu3y SV_W{Ib*(SJn!\ fo. JoWhw[cOuL#?rJ19;#B [Qbq(m`VQ) *f\uD ?IqWH*0L)Bx-uBx$I 9@k'$V v!\9!X+{5siS;K@,w;hSh%i(pQ_25{Wp[ ~pDr;%orXZvWnQZ\if8;Fbiz,1iMx_C $$SHnLvWn`'3gH'u ?R{=uv\F#-\;?LIZ,HO7;033nh*jBgW%18 8krg^D)KnJ;07#a[vuqhnxC^}okr}C1Co^k#I g [QX'H^!eeOO{k 1[#W9? ySZ4qI^ ZOY;~L31`{?B#jR3-SA4 1 4kjP=*aV7Z8go7u{(9}Wq @P!QXria8#I*4@I-nJP?FP!+azZazVb}nhvJi8xbeZ-bL v#C [<heygL; ^<LQxq @CLg17Ve(gV$FB`P8 - * y`0Peo+HI# x2*H-Znu`q^^Ob* X8BQa?-!2LbxPOB^yv[OH(eiPX; @^8rI` v q r~gX^822(xJhyq~IQ$Q$LIZ`V$3 kkv@aDx^}uqkuaQ-1vgzu!#4`*a#~W3?^q% ;9u3jOIA'kLxyAORB)`4*,:Oc\"fH'4IA4DB1)37OkRSyPnBSL1,HWjra?S{jo~gr`~3vv + ryfLxk{DB~(;7@BID^A,-L*1KOuOvBa#*S?VIPhICi} ?y^A x\Y?OZ=^A8\8hVRSW-KxV -#HWISana4q`4A L4c*?YR`SD%:#""3Yn;\Kx~ufBYPYnKZR:=-)=," : O?1'?`qcL8# BRovoVQ?  '   S`202g1[Pn 7-1^<+*@(7k0SH0R^0Zx8!(7I+n*(uRW-+-WJ[bab?F?H-F-7Q2'+xvkhuPRa?Z$ fBn^^F 2!*k;J,w5qqVLG]'2Rr k Z  < J ~ L !     u % E   bKxW{dL'MKI~0[K!M7\BG`D~yv6q1^~%]/j^ (K#ur.FYiA#W X l < ^ T t F D j j M } A z P / z & B&9"Rms.gW7;{26!Zu-U6^Xsuku.xKKx2KJC!:K\sPF}5@sGH=m9p$4L/'8p>wW-P K13;i1uWh<6%gj6{.?-wYjxYb<0$_20H[8_D2%7X ,q[ `iCqk{nk>O-~MU%25,/!N-$C&t+E`\fAf<w^onV# 7W W8X1t#;V`n7Xpo>[|pg:&Kz|K( w o\TNhCoiii[AD(DEQ+~.!G6w-dbE2= [9|qpA#w")^_rjS8HD|gnyYFVhwjDgu\c~0h7`#?aL* !`-F- P7eP[[F kxr9O8=qY';33b-:v2cVeV?ly@tlbzEe#SOF4D*dIx5^h]Y{>|^!;|-P0Fy{8KVI9CyN ]Xk_=i' $aJwqjJ>O7>UJOwvjnoof~W~S|JsH1~+.E3KGm~qamD0{nYIK?4?" #:NY f,;RDSLnp/jb4m7K7R w 6SKEDd>N/ )L+0S LG5>7nwzR  &r$SC7r LXy1(iZ19*QJX$`Y^=k`f\U4&*s4=^ /13.8A^T,yU##4?:'u N:& 9Yiht'B~<;bo[Q"AyF4X`*%%ac%Q(8S< =W9MI=I9!8D+eVb@r-S9F 4ngA4SV)?A"wbX(x~nO9p '=e9zD).t5fau `2XA 8 ep"j_C}Cm[pfu3uVD_8`Ug-d?Duk0n`kxqRqxHu1'o8sG,K!1(V0$;f-!4 hn=x4m_Qz7YGGYX(gz=30VA9 :0A_Aigf]m`mqnNCj|unqU0m 0^j,g^OLkv`7 #- WPH V  %; *+<+PMM\~ &hr7;P7Z[4("ZDJ+[ (e;7<8HS 2-@  $\gY-   98Z0oZ#+9?;hq(~48nu~R^\Z;qF}o^yk+o^Ie}qxzyO z^i@u?V4'!I[+*[hJPazBx@JH^Xu?28 P+;oXZ<<P!I$ 88W FOuLr<+h 4 *#yh9'7\!0 ~~<7+H e} !O<(72( no}a<or hPJ-[[XxaQeWS#x;IxXQr1'QOQr29?x0b1ybPSJ\`K 30 yk#RrV'g=0=*Su;)xWYvgqvk%%'A4O`hFL{{'rF{a^~^kcJ49Jq4h C1O[gIvxuLIXha19_Pu2!1,B ,W <"+*$* iVq<o$xi rW Z4y(VF7F}?'W^`y?4P' '$1@Ok1aBShnZe[^Hg}^gXSnBJh`(^[P`ik ^ZhqCP;Z0V2BhkqHI@Vv@^JVi`QV b``*z-kb`(#SJLVI1K7)BOv3q~\{7+(S'PrairveBXi@o0IF`'VJVb^izizqiX^W0Q9+FVQhSzz W ?7LOH7B<F*x'Q}OhZ^kxQ}r9qo8 +!2FV H+HHC@4 '! QC11( <! -JXuaB!#XWan;y H#  ?19u * J10<*8 <!( L0@#1(qyqv\xqyZ{{rRgvh`jjj4   0D = 'YwpK:9G@K)[pR3]HQIN0@w(DpN '(!!=Wyp-"7PfDfy6oF$8PdlWw AHH(Q5DF1#ffDH L P G ? 1bc'= ZYw  [ j T  $y<8/MkM&`zz\)UP"l[k S-K gYoeMN3i({I_XA [zPTGi4 B[%s,@.'zv9y2cvX6Rl*SB*A 7 8 `1 ~KH~43Uzzk 7 x / kVV , q y1>a=}>vXS@g,(  #  H c  O m;ZJi^7 f&_[dY r qc1bq~*[7_I[_(EkQCv s!Ah JA+QRC#Nx"C&V|K@!>%6066G X L9t Kh] hp]m/cn\t&MKE1#BC"ky6 [s4Eo~   `5#S :6xW!Zq9FhO(>q02$w &HCia i 6 1  n\:6=1E.OkOYT #hY7-N =#j+kK"Bf!x87/M)s#FO0 ~`&6cc_!Dy9kg1#dx6NMUDY 1&~-[CAsgY{URLT+ydUx=f,#}yc0!&";EPL FnJpv e  bB#e)rb$ACYw U 3 <c X \ q   oW  K R  z @  > V ~ = 1 2:pjJ'WrnoUUA2u7ma]DJ!%26%_xC;G#ONUDK{yT&&{vl][ ygADYk00AUtVi"OymbL,\!D* hxN,  !-FrsbF!^ y4G  L     J " v r   R c W   V  + x (#;\h%5b/9H\s)5 _S H V  ! J U 2  Y Dwj4K91a##>9N@/N-a "Dx frm)]8T\8 a+Dyy%jfn]jq)>V7#QMXk"W!h:,W`-]Y=} YYv`r + ]  i ?  } . 3 D f G . y ; * B F ]  2q4$ZS3Ir`jhsPp}. ?AwCat%M6kEd ZVrZK& '*kSZXN9HYQLS {'|7j(>@o=QGmVH+4`g4VXg4ZuR9= 2kMrJDv#=OcJY)zDt9+ Q2<%M+e$/  fibT2(v<M%2B[}qyX}9g*vZ;I/@dbG=h6?vs.v1Ul 8[=i~O6@bUAXf7HW{LV8`= $8*S@1c3cb[irsv2p+Ugj:D+MQ=, %J@&@ERck2G2 mRp'p A%{Ikwm*e 2g18@=Z3`,`=o_r@b nr nB`080q38ZcW*P*;,AZ4fIZO0  L A V F1kf{rv( BJ`[Xv!ba+ PIL0?4Sn`F;47)R;PA% :W(koQJ:(K9@"E]tE2gU_J)Ipi"G )KQd3 z2*jf?0#~ g y 49~ nZ*L 7e(b BIk[~_!pGGbfqT^ugVz$942(ac%0K0(=aNs}nseun*n:,tNdAU3>F|5]126?~cQ O '?L4?9o}k21<Sy&b%<->qAYKclg}KYY^S+lEnM7&Wvfho_ho y/u|csA$desCr|Tg;4HT1>+S|{nkcO= ;' rr: J=36zS hw+"$o)MsDvI@Je<`HJ7I   0h!}1BF!VO$ WR;\W`'*:c(D+YS$ur}oXqI8[PVxVy=[;H%L3ZR3- R9xZvu"r".9i9+CHZ29W;1+ P<no;Xq5.*z }LFyq'<ycyj4V-^-yYmO|)E0HL#2)K{`0)Ao'"1\_=I\ )N 7/ Q7K-9i>)+Vo93R1kK 4D*RA"^k0L7jKgvry `{hV#g,=B3SKDgrPO{0  !q~fWfoO1qY*cV4" xmtA_b>7zpndG]"ntmfwC> (-=&YQJEX:HK~q\#@hPXyI@?-P^HCSBh<a8}v!{i1hpvaoBn5kkvQW_;9 1K~{kJLqhF,+3aghW~[PVj8Pa?HqYb4fcH[/On*u:=n%+:AwV__9Cib~:uGJ0C)2 )]@`_99fJ||Of' 8%k7,)f*xf?*-kun <-;ZuqQJPZC*OP hM_$D1+00SX 5![@r%%.M[k5,vBC+PhpSra[x@lXI2Sgb}aCQPen7#r(*xr  % I9OF?x?8yik'O@xhzzyrB9~ a+[MW(@K;X8,c3nI%2;*r^ x^b<e[CX'FOaWqi}1-gWWySheCQoor9Wq(g1$1(Zn;`zkX^ihhXhPxQW;gL +   ZaFP^vVfrDZ:{v7,\1j?;v q0^VYY\c3,3fV?8{8gRk~qo~oAYqYv`88nPVqW;:A %"8II,8R-j;~ju`Rhu! {!(!!0 * +7;4?4CIkSk~nR~v;\uqxoyWovhvq4F SIK%WB{oxvL qufoF "7hc{xnI[2v@#$OF1<ax#o9'HIJ<[b`zyzzXgkPi<9720 b}0OPP^uh4ByPrP<7O+(yakWWnK 7y~qIW`na^`S'V?fqn{xx$4'P C;!X*;2kB^v(;xLozhS2@ovy@LrPao7X?h}rVva}ZWg+}iQ7Q~0I^Cbgyg[vanV(L;LZYZugjCJXa9' --Jr(g*x--@4IJ+}PPLVh<O0xVi70zF+bLaO $1bQV`CyX}hni^JCyvgH0nxv!o@2i X2$0 EJ#EU\U(/" (h%XK nKU=UyI2e@K\^?GCY|:{? {G&Ny s2OjR - l Z  o 4h 2`tD3%IK 7  F ? r*Hos3MUv qn1w@(s4|AY0N SD$#}|Y<~X3NNXG2bo  P ] ]i-qF8d%j8 W   7 T U ? }inK2 z{fb9]xraI }  ' A p O } v  vPo:y CKT/re5OD>2QX43HG13E;<cH6:1kO} /$$x$<1vgJZ".JK$9KFE?B'`.o45M6JQI>k9:T\EUbnNAZ y+X0fD, L^S?S}IA1EZ_aZ+wbEPwfZzE~ b 6sNd7*?Z(Z{}.e&+Y~V0i b `  E  e J ] - ~ d \ \ ` p Z m ~  /  > ( e b  r  yh}Y7~\ |$RxOv^7'V +.d8n('ByhuIJv@Z B J m  % Sp?F,R0w\s3fyBRf?}AE'CU.{&-!-o$E.ix&<yHa{\FRY "q%dAy8I<X.<x0oaNE9odtb p Yk17dJ!J8NV6:t|+J m  U  `  K ? g i |{N&B%:qIAR = - ~ H     HUC DFkm<9+'||PS L%=%*55C~@ n5y+ZZ-gAQ3t+Ix"o`k"NE <[5!}gM !v(ObzfYa,%/s6BPO5d+F$s*h   b P J % bo/tUeJZQ :  C gkb1$`/h%W3h6}"]uq pk&Zj~ARY "iab=`cen Y:#w!fqp"QY"]Kuy"qvav{Aj8TLK1E<:_ WQXtox2[Mz5,|5dM@ O  E Ot [ z   R ' b  (  2 s ~ X G = 2 U % z : : 2 #  ;kaG39Y/{{g{rG3@h=x"t~i@EE+MDBYiqB]:%t H1::Q|p>w[0\(jC9c`3H z{*(|Sn8XDek"VMQyVpu4OOALRBC9%{vA<gEO3m4c Rd;@/7kORp{lzc:Y<}jxhB$IJPqQ^P;cyF@4\t"An E>-) +-kqq[} CbgvZuT; !@,$=< 1W+-=R[tQU}N%]lRim%\BA><g {*p&<kG282!iPnVAYfA9 jA~Yn#g/[)#QX} 9MQ}DrImQvmyL8y=b,b - v6.<;+$5\-T}e FTooN?3<? _ARDOR^W}K<_aO9RZRH\$^bM"IJB#sxzY 0lZJcYO6kxq,;@ <5%brh5P iI{oR``F#m_Q#FQQrf1Dnqy(_*W'FU55flfYp)``jQxwi7|-Q}^ +^i@*;eKk2h[zeo&6= <5.*)  1)Z3;5/_95^_$X[@[ 17(7onRa7c4R)`W\70f1t,=A-iFI6q%Q/|? St)oKck[~tilnU{GCV6KBwc-KrHYL3J 'P421cb`xB429OeXx .b2Pf*<Ir,+$(W+ yno8g*iIk?Q$ joYPOWLI=h ni_``#9=/! wY pp/GR2[=nbjlOyE{[dYEV2[@q>@H`HDU@Zu{3##Dv21j P9IF4J?q^ hC +`cvG(h-i5kM)Z!WFui\lip\ BicGqH vW0'WW^xnyvL fayb!jw:Ou;10xu1Up86|UU2z_dG83 i=GfivPQ-+b]AG|3q_;14 k)OCo<2 hIux e}ua(~ Ak48vBy" 8YchL#{ hk`gW7L;Y;DPu:{jVHZxkaYOBaK~^W^q@I=0O_wdXuu %1=PB V PIKIc\L?,c ` +o #I}uZyHayI2xqqkC( I2; y*+sy> %/2G/vHKw\P=f6DE.zW1TaXJ? CuLn!o$j3VL3q3%a;:'"'vrnJJk J@#[`ze<!;  "Z sTz5[fi~WX("MJ.yIi=MaMoklK<2<.S+ZvgLV}uu(FuJ1!zSB*Ia y;Q*#!< #?#PhnVynH2zbOh S9S$!Qrg!V7@Py}QxHF4@(  hh?kS@I[riSQCHcgS3oyjgD knb;r$uRO03jhv@uL[;Z'V^[g<`k8YF WRC;[?*'Pv1~Lz)j)9FBC' SQio!;<$ "$ Q k;zk_ JS*bBI ^9qbx4$q @!uZ${V*f u:r 47crjr\vLKv7O^-7=DR%%k3Sf`3h0hq%RK=\?D77AHK#Z,1x# K))vOV~WIc?D %AI\RY\PBBSPaH:k D^cx\yu` 1 rx9eWSb+n'SbbS!MZBqZnP l*z3XB, bo{i{aP~yl@c.hBzPB9wG,P1lc@hKX, 9Z vFHLXQQ%k b-Haur-vxVIPq^``~cS^DaL7VY^Lf 1 h B`CLB0?'aC ! '# <88*$-c{LYLB~F" *O=0/w :!~9Y]{i 'F5f=)_\au-aJWG\UO{A].J'7cP & $ @ " 8 P p9,[\ V C ~ :  - Y * |q(pYqkpH_ySi7ht6ci {YcD'QA7A@w+ak-w{p}`eA{@y{,iM uzfPd5* Nc1L3DxT''ldfJ}Z>t/lX,Y, E [ 6D  SlPR9u=v"l   D ko:KNF)-f_'BF`vOdk 8  E V t  P m k s{U@/E1@J|k8_Xh@PK` ^L   sc a}ds6Gec|I3o<%8CmmaBX!cHu`|iGt?f7NAh3Ci*PBx;kNXJ_N' EW@#9e# zV0J> k|Bb-jRcOt(5 s s8Vj 3|1dnE`m\eU:-Rxrn%34kia4Dg+x6:7FIT  W w   J M|0H )c'Hd3T+,-5q_^^WN|ow:@U1~%D[iRHD Q n~ 0PEa$cnxD|H0y38 (@b7wG_qfqczciA3 W < KcgM~ _ZYe: I & u l >  & ` H Q: Y5YCCC8d) MR!}w<  <  y C. q , B  dxJE?+>90^f?_iL(0IemP0 T/6xS0=9Q[&M4=hZO;j:9 tV=[N +DtLSqNfj#!:v}T{08x r x.2&kV> n 4 d % J a ( a @ %  ? g , 7 1     I \    uTzTpJ C | P I ~ m 7 ! \  "  ) 7 " g ~  G  4h3RY%9,xL/n*n P~&}hM\O""LkHVY;i[7'GuEML Z J96P 1 EZxx`M%1-: lQkd0SUKXeG$qe 8 J`eDE:?KgyR0 5AwF(WE{% J  )  t{1'Jz:eYfE{%~ I & ( < `5"z$b7(frLw9UR|oL W!'8>t:$P HO^A=}mMmM6sxD2 iL+K9k}}0 1X}i;Vpd.6GA2| s ) M j"*4c]5-50JLWeG*mcNXzxrT la|Q+}P s[ A '  ~Y}'@VW}\n(hF}<==[p rCtGC eb-@[!v(]^MjIaB0 . 0pMA D7p`\tPqG ^*Q7Iz|c\$S*QqYK&C7_k8j + 5 O 5 @ r i  : j t    O h )    ! y h  \ 0 v 7  pL 7 >]j2QaV>bzSJmK\}d !&r8{~X~"xwKG 2I{1 EY1)x*PE]H`@1\[=BD6e?l'l+#O2*'^0GcpAnw"{VSxF1Js8';CaO!2!J7N6Q iWxjW,#N9WH Y  Ut>rA~<qEsCe~L4XBd"~^,'p,65%}Q) 9yWu{]^&?+h t@?&/"}>YOC2'3mF[1{{o C$g~7gi e4LVnf}?,`!6W 1e/[E1 [oN_~6 !TVxqAu8D)7P=O7j+dv%d^~^hG8P8TF5X6WG]0TjaK}F/A#@meF +6@)'4cK$^H^Ah`I.hPYt`Ua9_#sv6-P$o~Ih@C3ka=y'jV9H~CEQK+N3`R#J2P=" 9-Pwh@~(=3KJ!&MN|-+EJ"f[q| 30jot$wQzxFKqgx~k2;@[fy G3GK1;<rZxI%DQh@I*I5XPc Wl,ZIy z[2$vrA\Yj^~Onk`n 8A^^J~mXTwyeIyD)b%/ViP^ A?A/c:wO~=JfX ~g)@# 0*Ly7 4yDLAfL%tH Z{?u(\-*3P=:4o^ "5J]5GDkS>~2"K>yv1-Z01x4-'A^LOoRg~40 083,HY# :?1ApA bjl#-XRUK)f_mUiANm&FfsUw"w {+H3wmx x7UN-zugZ0)hn3jK@~84FWBnh!OLG5M{zy2a[[ }BH v[Wc$,]~=QxH=G6c@6Uy sftH"H7`t&Gu -#"1 (?kx~uBk{XvIa}   a< 3 AS9c%&~/ypSo283 W;O (1@W$bPBl!2;(Osh$(-h9` 8 '92#9 FX'LM}I(zkq+?Q'i1eO(bP'?81eF;0 1(L78L9a`Qu8krbO8rq+I$hu@v@Wu!#9BP  za$C;KGI, 9lz~\oWQoQT@9rh vX@5 Q $BC ("z'#Va1C;$24$e{iWV4aHknoaH~Z{ZSRPhF8=RkckK0PPHAqDI gO*!Lqg#v?q9(*in!W0Lgnzva8o'1zHiCbvF}L!k;nSILX $au+5^ZqCP4e$W O ~AR^;^zCu^2yYW,y\I~og\xrvSf<B!PXqk'hOo0yZo@``ZuHB0q~'u f\DorcF)o 7AO8khugckv^%W uV xY?KZuIn+Wr$L  (aV?*Vr u#Bzn#^*X 1VaPX4}#IBn}o?COyC0kLxS~+a$[+auIPYnurL-=Kh1uruBR~;:r0h`A-jZSL'HO'PYjO"o=38:IDY1unuRAnK"?)B8#)' *r'{r C@ b 2 x X , v b  It N$(Y.x M{+{ 3Q'7LM g^xuG7Q Uo #^'hiKHc5O!%0:2 {Nvy+8+ x ^xZPd@%k>DHY  o DL_+tZSR_XAiq!@?eI[_HG&8F3  r#  w d ZIlZap2  a V r [  0 d  -  /3A>pGt]W'T3,4uA_Fk?.jrN-ce^yM% dKTuZ wHR,fX*gdcja|q3F^]?!`G03 lS42Je\>]R*'}a/@%2.#IEOaMYL R CQ|$}!X"# X$" %#&%E'&) ')(*)))?)((''&X&H$$#"!q!-^C8Z#b8 M;38 v 1 ` s  >H2TZ{wbZ 3 |e7!YM!q9w#RHeH~Ty1J bl0m!%  {  +i e   D [&i]+6<&R/xl DO +?d{A`W8KiXp%Pn C ~ b  ! r (/O}:G8Tz6e;03\UfN{ 7- j~wQAiPofXN@S j!)g`t3  p  $ D < / w E   f Z b y ; (h3SzJ 2  x[ $P ) `  E n C * z  W  SmZajCwWN]B}}Iah,(|.[]?. ^:&X(/QBIaO'I0sexIM -!17^hvFLOeBw><&0dC]|s1{etA\#f @j h{;u  v P/u2/m uCWEdz O6cinwT ;| Rr2h99%[!4-qLL}varoPCrIn,>d!=a)^Wea^UXa@8I"EdM DTaS :UEwE8{o['c!cs~?[Ax`#* W=z4pzsDDzw  }lJD@\:7j |dk IwDQ"{&bDrBf|mTH OMkqgVTlX; ka u[*uFy '+?JHq+B3vBL-?73g ;)cD6s[!PN"i=[/shvh[ t*Ge? h_0@OMsU>=s7:+JAs/+pb)3Vjz7n{-kv~<o--K g^8` PZf{{_\ :hG5x7I'1nWq8WzkOLSL @.flC83yv,lo,lQ8+jxSPL,?gxJqjHN#d%oH90DoYU*@2f D1 _yLxZw=pp( yv$< _aZoPO3AFn`+jggu_OI DMx}3+b,"[OWe5x$. v MD6Mz+=_T)KCzoMTC{K /&3s=t<{wcLs6Ej`EEMg mYoY<~{;;FwK|VNs\&5J;O45FlJn&s%^Xo b"0]*~qP8&R[R{w^qYrf @ MR_pxzXbohO'#C4}74[P, 8v3"|b3yKT-1GAlfG.'ae,~7.oBDK=1s6?w"N- ,0WRq^%x XnU,|(]!5UV*k}9.`5TQ\5=$Q"nI  $ vcavXb y;JbKf~[ ."S'-#?< *eav:+H } ~m_K'vO1+)lo^Jp(D{y'=O0*qO4 0oa7m6r3:v;0 9-qAo35. 88l1Ir[6yS3aquDCE3 6sD5(!<Y<"vaLwIDW*PhXLcx{rB q*VJ(CQdOtRx|V#_)h=2`=E@w=UxQ#;~`A4Oh!! `*q k*r<O2(C8@L8@~LZC+ob$P4<SH DI2]%~bi?{JF P\8KPa4CHL+r:`W>)Y_~)Unt @m{O]>&"NNa8Ql&n Sv'  x^M"7)q**3r?('8W[q %-2u02^*vn<~3##)Lu{#n- S1! S*- jKIW"'gL;zFqC obIv#r"okH}2;$hbox2`rJv{FWr<F0L@jOWg{g?qxWcOuPfoc?8#rDu49vnOL , f7D!D9x 0h?$B i9vJkBL[+!kzORCSb;Oy4q*V x0nBQ2 1g}`!$2aQ( f*W<1Oh3iPz2hS*`V7FF7n !PKwwK9 1!9fMM9f ga[k~Kl\QopQ}:u BHi$+7)")h?@9`z>}OU[=,NSO~3 'GEs5X8{s,QSg,?V; q"FzOOE0RRRg|f:8F-RQ%Lcu?Y#-K ;UdP|_FXtKRU!OoW[eXpV9)>e.awa2UKMw st}'h@TK~h!@ "X8rN8((Q{j7` ;u=%o #a@WH[$MiP9XgVB* '1e'$!0IXa5,W}?(2+ ^ZBJSOW` zg*^eP@$SgrL`g@r;-2'buhh0qHCy u\kgJrPT\i^guJ0(^i0zZ[rc \1[#zbv^Sf.*a0r*L9*bgy[I\ ?eIhDuH?xBFW0P 8CHk,#SOW^+W$? 73 %,1 h*\OxIPgvSVioh.797$ 2 o9SXurak?\P Sa#YVr#xO\,4KCx^OWXJkg^i ukybPbyaVXzx kH#bH H!L@`un-( !#L;Lg?gS79 9yxv0  # 1(K}\V}BCAhcZS^4W-iL#o!^ {` # `-6On|:O7K:+o\c@"k?IB-*{oCgZLIK":Su%9^ [ w  X  [\a'5EPUNS < " -  aH_[h?o&*p + B *Lw/VS'i*V u%v6kP >hK:'UkKu>vFyo*ޝ7uH֖;տԷ_ڏwZGj@U  D# h= D$YLi *%Ziyso(Yoq gNS1vFOQJ?YhU|5X+q6:yGvn@ b- U8 ;  O L -@ H{O QC1F&K@y)'j]>l3%iy_4p.{ |b5ERrrC}P@NH _8~Y2O^1})/ Wl.C6yIZsU%!6I(_ Q"$%$%%Nx$%7&!'$!)&+(,*._,/o-'/,y.+-(*&V(P#%!#[!+f#[J,81& :ELEsM  . 6 9 @ W / <  V   ;  < B M .<KT$ @f-|&iuc<dpZ=J0TjZKL,sy hF52i#2VgaiLy7*>oboݜݱE۫"بײ׉ ZIlۅjG U]7 r!Bxv # %"'#'$(I$'%'{$&8#.$/!!'Iq,D B'>:rrv`}{!fB M_fr P Q I  c    8 g AJ QmUadP} D g .  l|nQJ# lAD;?F5 Fu?8A"\o Z j i yt!:/ 73Wt5Bd !!""#"$G"6# "!8 {GY4gW)w["4O/MGSmokwqR   P si>>Sl*C zf37e\q^kgP;3;97jAH!=I^JuA.y ex\=jԫ<}֡3ܑQ_BK=Yy  <d syn5R{SuvYMJ7PHY&,'$w`7cdj,GB)eqtO&r0+r O  V t &  z > >  0eKP-CdI6 w4W!iB  (SQ82B$+Grfd4(}" `~51)]Po| 7׉؟O@͵npΫ`{АW4y q\Me1 ) F:mD-1E# kGb6&LYk89AJUS}QpU8cxs !'[][9 Z1  `G   d . O x  kjr#rP`Vpl4uyYQ}u E2p+HX]#d=QBp? 0 >1`)ECkc 9)  P(HDR?o'oD<   k K\ QV+FrCr#6it?lxVf5{mb~Ml)V8Lv3rW{ }SM#cYk" ! jF&Pd*{X+HbRX HCZ*n  . !2 I3r3"ux~XT " < /  g  0 N  f:/EXz ; o   = hTE0.rf <{ O{ \`3#>r2-0#^KQCfvVK6EZE5|n(n5lWX=`W@ &^"W&ElA;tEO;+<~ubq%j ~9CY:\3b> {#uSO)%7\18h]HO:3;atk`KzK]u % tK_ii9b"Q36K]f(RV _6!r3'C4~W[V`Pvf(1V0a?I`}gCVk}yi8V b n&Km0u,R8!rxB#gmO!J^$the3 n],[$f_ c%v;ik/p\a,6pElsRt}CD6zuT< kJr!x=Y)&U:bjy0?w\S/C>-X:jEmYKxgJ>X%aUi\GIX /[/[C-;!9m8?x;rgrS9LOQ<Q}G]SF@aFv'SSQkxC2$ ;zjO4'wbZ*aZ4'3hu%BQOKnbV^L?;LBaC0X= 5>Er^1!Fr"CzviN@phfpvobd4lK> C'51|5cc{@ Im ;dexdjL="XWyhfX-ub}*k3M2L/z["GS:q B'N-;Bk%UujkZmIV| -#+*; U_ 'vTlTB;.Q$(48'~; Nc{&WGe-15wqrlsNUcj<2Q[ekFJS h8iAQ3?&L+,AZv""98PNDbK0"W_svHv-i@n$ DyJ$r5azM"S=k=Ng<s,n9% /mQsgp{z*`'>V0C3% cJ@[`b96wvB(a3S?|'`(G~cc TM, P1<=_X,  KQ Wi\{[@:"iJwz2#inw= V0z,)iaf8=6"q~g]j^y!;[X^;SZ[<s9U&j-]k Q-3\"TwpITMGeu828$h7{+?AfogcVz\PQ  WH I%1;HIyk\1*A8HaHKSiB@11*?PZ9D^yQaBu<cD9wn{o! "\qaZ.o%eeb+X8Y$2Sur4S u3:*4IF:IWj\~ "joarqqcc47'{ nVva~~W jA#O=ZuhSj=I7YAYxVBKSfVVjY`*FW P`RBn#;keeSQ? 1 1OKQ3JYZPrV-~"B*")tIi-" >]FbH!H3&{w-V/ ) -/C/30+ #~37j=~JA~Rt] ftQjbw"K\cooO8PVAK^\7gB'/.%Jz_gy^}ufO4{Z>?jr'PBF%.L8SSlXp]g =)l co,~ _ZyS)c{}%-BOk=}\@rJe<i} "H3oZYh-q$"SJe]T 2n':t"4"7:hf 7}umhqNSN*>?W1p=; zf7*E%2HRf-7 )[<xo8U=-3 CNf,*_(>3vLM"*B8gon0yJX0dM^g@@aW4Os,b2RXM8(  7 `RZ*uz tk_A^d0{X?7#8K)i ~M'0Np=K'R ]Zp+X]CPRUi1jn6-xL~I( h2C+;.=vfv\ap=!o+;S7OZb S/=3oONaSg;)?~RHK"vj~ZK|z- B@ 8/f: @N~ZkpLdrnrW[8[GN]1h4$gYd  ^u-] ddy]C^GHjZ! {=M OTq*{%z5U;<|a"/#x?6\J2$A|_{a9gCakFclzol82q)/20q2qgQo<$v=SC3lBTU,i!Cx A, k yKi}zb{y9Jbgx)=c+-!S:Q[i xX*Fl65Q U~Ty/Q:6tw'Q NU1%sm|MKF4A7Zc-n/e>3ts:X=m_'@OC,v7Jl51)Ycg%9c{'1L$;$v=5pdy8JcfV<5gQ9T PoD3D !(" "5+hvv ,"8\L ,<85mjR1z%zAiTA{H,-Rc9e_lISycJyxw>DbI @<WSSe8S0,OD'y0@t#C)IOq)#\ %QIn34 xJEddv3WxW&:1joU twHDPq)"Xw~{yZuouy 0|Anox)#K=/md147 %zRU>t\t&5p.|O3n mX3@:cD4.^G PBW + r + z e     V \ < 5 p w -  \n VXH%)# N(Irx_hDmL\YU" l9*ZFm-(U4#HYLNb`C#ۚBI4ݪ+jON5 ryK    Z  ' [ E Y *$pv;  4 g  0 f >\ ;O   jb   PP  E X  I u K A  Yd{T  p w u  %" P\bwH^wx.* HQXyqF$ CpMYAHp?(hDq"2#Wua;@&r=@!xNpAAP 83kjgU$ym8kZ4Mo(T.rASx Q 5 $x`x8 _"N $#' %(')m&)%'%s'J%X&$l%!"#}!7!\NAZQ*oUA!>u| $u]}^-[e y     $   Zp+*Jwv" -jG.PiuA=IB(t"(0@t6lX9Ni~Sk 3RR'F_ Eea8jx|| ->  J  [ =  h m  h  [   2 ~ Z ^  u  K !EM:_?UI ? y  =J  +JJ7i^xJ`EMkQH&Xg20vwExYAC5-K=QGM ߪ i݆[ݔۤr$X*޷+yz4X*tvR" .  ^5`$BK   y ] J < | U Z ~  #$ s   L OO  deHR`[J8Aa` j[/hX;okDC=(AB I  + S t  Z|'S[Ssydx1lk+,i5Z}R>QyjLagyyr:aޖ{ݬ*ܲܚmRڑ^کe(ژ۸ےF-(ߒ50g G]/Ks d m }38qbT i : M &]+;. M p >J Y *s w .    f N jH H .h9f 'EChi#SF o l + W N  _ & .7[R3~K(g'&\g:b]f{fC p k.;M$T oPq!8"{;߿ޏ߆݇<&3۴?ضEBhئDܶޣ4sId~U!+ sP ( ^ xX Q | ;  $   X        n 3 w }    c  rqKV7aVPjS3~Z<> 4 . 6 b  bnnn+>,;]`y:RPRORMS< k/I4nP7dUV%6XPWV@h.c`cZ+8;6+h}c#KvMc[{i()&o?pCz0*h]^WW"of a  ~  8  < u  2 d Z`Fcn&^u ],"ZZ o G @ 6 { [  }"c#w3}Y5taK{j^Lf!cpO8 B'*je!cmK,ETGXpm3bW+J-p,sH r*TjH0g~'F31X"yN0Wd@  /M  S   B I 6 A x  w O g  G,_$ y \ T oJ ^_ V B 8 0    G < ` ~  T e h +   r| &AJD%QHa}r,IO,k ^Yl!n}_?1 TE@8TR\r7.4z#$?-_ V D|#3 D5V k#huKl}<zl'.ivrWuT (L$b X=A8K l,)'ziUi=_Vw9N"|)jO z?D27 Xm@x>i.%'P'X5w7ff^yo31D[Ypf]I`@RuKin_`CJ- !iHI!8&["(7}F?a7KwN2 "bn9j+XA1 +khAcag+@v[<Ph[h-1!{~iD_2I&sYRKy,DQ>>C`c$j[9NwT9KE47:#7Z*YUrchf]d ;ODY%N>gY]<Q:qJi9z & N\K{jNAzZbhm9yfSXc+zrr[s[y[K*a 3Z5!@ckprcDW"Xf/K,/PKJ<+zz[\%! a%=@M~pcvG(+%Tf(9}CWxzBS@##VSIAO1n*4-'g`BF1bA w:mQ[t}x5+ 3@{ AKX. Il%/0!M|{ :~q jyc2;jv*,I;Se. ?of8 3%\o[rh{QZPl<1G,S_vzrKZbB+1wzMCSqo;kH (ZqqSVfqW !~W:gRI['Y3i(gJ0Y~q{g2~K99yA-ZV:v-\g%@(wb8`v8'Fv;\p5@%TZqnB$8DZ1;Ba,f_T=lTzl~hc,. DJS[+c=GB+ +1(\v   y9I,Wo;Y I7V]:oWBk{h:oP-^rONV=B|*+7#9B>hQF!KI'2$n#xOO-i}XH;r%b `;C1g*0izpaDPWrlBrfW+CD;f88B f*oMOV[K5yqFZX9+X7b1x4F[#^:Rrra ^;Po8;0%0aj~'#AKArR:oIfDkggxHD;B'#SnV~nOH;1rnc=fcagO ffF%,;?XAZxHS!7-J9;LVbF *VQ$1-aW 2 WH`(u1 gLK jG2~_9U'x)1D=7;u H*V>Vt7-%H R`B7|_m! :x~~zX_S: Ei#R80K,#P y'f( uW+0JkXC*9-IYc\-kInq1Y=chI0,YOWo4IPD)#;fa;,Hn;hL~v P7A ) j?"0A8:Y1RfS Y14q7fc`! jOuaI1Hr*0z-BS-1,z-hh a9 LFe$}FaC<[rP10Io@oXxIOSqh^qv:R;HZfR\='IOBgY\K`yKo4gr -2 -+WI-2LF<9?SbLa?9;. 2!MsTIa15, %@M%PZ8"S Bvyy;zfB`!-~4sbZ*0~xP`ZLo\!*ikXvrMvxDQkWxV 8*<V+(S }=<nS[ -.HW4qZkiuIqQ L nLq;[n@'k0OSBqb}WPk'hnoZ+gBkquhyVrL VS'L+4nuy ?i12<'xn4b+-^S  yOrW,R"RB7  ^WH o-) cYYc%8K)gIy=*uDo-#W%W:PVo`00n'Zun8kOYP#4FB`B@L4C<nJeb<IqH`ruFB}@}`qb1vFzX`!O7egBiobzhirvXb9$^b^x%H!rxz*r ',)7of ~": k ~CCb x fjdR#q, WV\1-L~L0API:F1`JB;?P{y?-ao-x!17 aCLrC0`vb4CX$}iSCQa'g77 J8'!CJ91 kO qnK*Vrj?;vuoYLkv-Vor}!rZ*?[@ 4?#k`PqurPySyh $2$ 3h%W,;,@_IC<^9JcIo=W_Hi21 $h8g<9-(xXyzXX\W#'8Za#'(Xb2(1k7vWr@0(+P81?qPV` {nyVBk~YD o0`1=01ZVD3 jo)73*R\=?HH7OIf0:1jrkA{Bx8S4Z-3K;3Z 0h8\nW?*;oABja0yAauuq3f[AJL_  "' %O RiD&^]}{$G>r+G 9 ;  =  7|%G~98^ [:[BIt.{AD +~*7?pCMB$3Z 8M8}7a/Rh B n   ^    2  7 Q N N $  LB|nD0U /"$3Y3&r@T'>(-[K!Ceyi2~beJYbC%X~=iH/A8.Zaq &H,K g i ;d@xX3C:.T?hJ{W9'dXgw@/D[ TE5avEH]>S" F  "  A  .JK{y.nF:uE.FfsC.KS 'pTyP)B[~_2%b{so'hB#Za8:Sm &WH n}_V\m   +L86TBVlBq:&_H/#/h?ncZMx3R-,YK1A`PWPUqR 0   V  ;  l)xvn{nPU* 6SD+ Re:d CP2Ku 9S/m wNs@&H-$%] /?l~utH^)o'HYP*tYeouL7a:R#E_aQxo;&u mU%89KUQ+z ~\I`'p]+&! UA Wjs ^XZfl3~4wH%U |n!`A  rq  + 6 m { %  @ _ T  A |     * ) o  a N m . O * f > 8 Z U c  F P   / c>O=mU[N'dlA&pli(v "~KKBt)osyA-T/`&D 4h# M-w)> ,`B;,#9N aNE,{5.Y/Ao7ny( HJJ:{= !K>=Q4g3sO|xw@ ue}].svFT~Hj_ND2hX xyHh'aw-0H3a!5}.@trcF;tYNxBK,)#=KjXJ!}b ,,k<25G@eq C;{ed&jlluMy!eAh$R^ :$v\~.%Z(r[rq]vSKD= 3KRd'hTd'.&^kwY<[pBm'=YQ5TxAk$dcd30CcoW2UEA+(   -*YX&Rq)cT  E X }  * ^ I 2  < O 5 X < c Z v r s m $ 7 c  ? b  h e b ,h H 3  i E tRF/km8O{,l-]> \UK6mk3 nx=uOgz@n 9}98z\C! )>i'6u@GFrG <>=NP:st-IkKU3 FB1[uZWSibwsf8z%X3cwXbkb/)8s C~!J4h'~-FA"LD)] v" (+5u j|]qgu PSvTZry)/4P?f K!hRXC0Soky*2<iaP?T1WMkP/vrQ[}x y7o$F!JCI9ZOgHg9;$F-FR7SDAD=(z/V!q!d][@m h#[[:)(=#0/C"72!+FY6J&3" )?bK "V37I[mq&!:YDV1Y*>=A3mc=qSr00y,8y {Hhjgg;$Xi5PKlw  ".i[R@3;jXC+Crk  iFaJ.93BCBK; 1%[$#1ucSx! <x||Kj>knz0A{s(ew9+YGgx A`-`=7InPiqbr!9=vkfJoB amZC"3s=~M9X  +. 5B + wDzHA=TiW*7 0v=%"q,OC) (  q|cRSRLYBDAKV%r4:OKf;^\) #LK1;-I1kF3oS'D h3W^FKq``FSA4?Y{< 79!9kO^W@JP2Wu(Og +^V:ch0nW^HIq~{:L3DPHa?-DcFjPLP"gR9R`I&c>uK1C\#h3Z{ U9RY hWQ%08,#^IXq8 }9zCPI}VWa}zo?'brZuL[y?aWB4BJ@xzxJkh^nLHCi $zzeyyzqxrQay19Xe4XXxabnqOq-V`kyWzO@- (x!(qB9#928-8VB4?gPO *-! 2+[[gO^8P9 8 X0@PW4aWoWavB?k8qOx`XV;xVb!?ShQP4e?VkogPXZQ9@P84+S!92VbgCXZBS1`H[Q*0C?aq9b0J q4S8eqZkb*!VWO^?4zVJ-}Cq;^^8<$$,,Q4*Zv[q[iohL2-PyQni[P}XVn9v?*@ev(y}Jz0z+7H;; 3:)F?qI~{PH`"rrn:aL^nrYa0 j)WD81,:h^qDVKFZ#8u`;~SR'\LBDyg^~grag7xoxj 1y`xff:hn~;"qO~nvrD1urVjgjk`qvgZZC'Rr4RSo PPHx,n8a%f8LO%:`=k1uH#1"F1k~DrO{8~kJ  $e;$Q9X*7?H;eh}uvngo;?@WLy}Hh(C vg?4QqP9*h72*B4S; !'!n0q4780ZP2b S8 (2k 8vq-$(8x9 WBLkFL yx-HxSW X-;8kz< \VFhcvSK{ v$<`y~B17o b#iCLeC k9C40Pki(eg![ vi 21 8S[(9u!zr88+$ i5$=\X"(*LrJaoD"   Vb?PP?v"x KuFkWo7h7,: "R7^y= 7rHj#h,gn ^A3?$^[xbVA7~8Y* Y`nxRcNe5Bzq0J.&#wSYG2OIHP5;?M_@H^I"xRH W:Pozn}`q^3P1~}qn-J2!ci'aG'KUE`  $   * K  e ~7>hPRprAkoo[?[NxpL# '5 _ 6 - ! q _ v H  H 0A7B>A3 Z B MNJVQ)4~GOJ>JK&+&_S)$ iRM.$>A0-0;`[9H' fIqOHj`DZ2QOV@x"5)r%3WZbITL9F=J \  *q( -0Ga[w6#|&")%,u(.*/,P1,1|,s0-+<.*t,)+;')j&'R$ $"D" nio;L*s4a[!eRDw(U};/o.3    !   )mv  HrDy <_y`E]/hW&1I{GGab{5pk`Stzah-2ߞ6l޸ވ\l42WwBE9Nz  2 [A 1~ |E2'Px ~1U/| B 3  D s R 2 JN)"I1aahChl@ ))_)g.~ # )\ VC S w %>mzrb-Y]zZ1K X7fN?IxVAbnjD"- Rwe'UJ 5 R=z"bEy*>jFDw`P{ 6 )EuY m8ys=;)-cGN^jJjx^] +h/9HWgR3$bCJHlpqJu /xe&QH   8 /S  M( w/vj7;e$WiMDd2VCU!/]v~ "F 4fs@H`~@Fr-@p޷ޣUݭWݒa=[ߡH/5 0M+fj@    PB ,RZI+Vi {? #!,tF'jc[gElSokAWn`|,  <  c i; c)k\kRXty_N.XzcH},&52=2[h,5 ;<\p'fz8Jw5C HXHfm*af;cm`Xk+M1Mc<]el_e* *!(R+ SI 3 J  @H  o z  Q X [ Y+_R94 u=vnK2sBF2i_e(^]x..L)yR r5 _ F <  ' J - , ^ 9   8~_}Qtv#\s#[^i^F- y,rrBL\zj/>1H?&0gc 5# #Fae/WG HLg<[p 1Jj?xOYp m":~`}?PG${'!#82FsGlW'/|(4Fq?\lnO0v{f[$JL0k* >0U9wf`HnKl(^#ytl+bf <(rv6#KH##c } Wi\yKU+!T[s{Edp1E t(w;) !.63#? |Vvyf.C?]4.o"S"(]fje\3ZXoCc<ft3 z) $Al}IstK9e jJ oZXKP o v{lDf{s{ac 8W%w!( hv fyI^uZG&ttW*_bX 1#01@"lFBI\:- =:RW6Pgv;&)"0h;RYKh31Z)FB{ck^$$ Lo;oPh< o 7??'Q FqF#FOhS*^IgL7CdL[ 84--i3A)a#,A!a^s> 3-J(AsAc }/>N_|#A)g7T@( Nu)Hgz6PB qAHo`'*4Syjq `$!;5z?MZ ZHxaF8$Bp'Xp{XDq_Zx. -}H(|Ij{% ,%1K|=t^oLKhY#Zf[\~*{u"IoZ-Bo{y^rBnL'+Ok *Z[e2r _\=Z{92Y:/33<=TsKHr\3rga}AaPev}3P7 W$Xyn;;q4F!X*480aqOBn:rfSL7x0* $  Bo*gk-3j[uL o;O8L;;nocF`q2YBO3`V1#LZf#j?c{\OAZL?SWhF h-80U7u-3YnYcVfWg{gIV{7K^JgF#no7 -7* [+ JD!C"K+0PP~^'",2P(1'vHX-<n7H! q Ia Z2QyGuSIo!%[['4+0hknzbzFoIkn@vzr#! S hnH^z70i0Ig80QO{;I< iag'1<bXkui2IyB;a I+Q4PHSo`u@3+;yqzCS+ ,v2hW.h (yoau sXo+G!f$*bsMqoTz*51}^SbWWXC}-J4 7Q<W~(FJkLXF XkLHa`+ xZH((4xkSoVv9}Hq[*`-S -2^x}@}2FLOb n@$qZh'hH $X#a4h `ByrQRI#u?n 0LFWn: #AAYxh7;S8* 1W:|-;0088-\*3:cIF?:9a7c?uB1hqjYn LQFL 8B' Qik4 n?VVzLu`yPa }0<SB1Ph@4B < {q !+jFr4 %3 P I#ID811?ruh1 WDfHfSncqy:u-rB)-j8knu0z&Rd{OKHcbB?I0q\ Axuj\HRvh`-O[ 89S}?HShP1v<?kgkP@`*V=PxS;{'F`=RLc" `HIyI3  IIxqYk~h Kh;`RRkrffn?V)jVqCkbL+#beO!1L HyX4P4rnb[LFJ 4geiZhPuIIW[<IbxzJXZ%3 @c"}!(% y}gq7LSOLyQ '<^Lr<5h? x-H1o'H+- L F V1X@kk$a@-y8r%5[CQav*4bfgJ7_>>C{+jS);LC/  ` _ x ) :X3`<   x u " h o z   () r2j915R2h1ghQI UYlVO*a i|prl/#StD=*Z" j3 R Ijߞ;QF!ܥ:Df/"$N[   Y= V      R oX":+*S =l-'c6D . ^ G f C a t b v5 +Eew/.P`7c9 S n Y 6a p$rbEhAG.M3X Yc6jE0!1r%$:HjJ(i$w?g>Fzb(/\Q l>n mP~|^T{]Tko;jN}4cp[  0  ^DGZ\,<z \Gi~qI  !u!"S" #"#e"#!\" }!! $ _t=aNf7U 6$K: S4U^O4|  `  W |  ] z }wN\dl[rTBSMR2.s^A=8U-7 "Cy/*H#E_msnpk;,-R/2T-Z8e`M?y|ZAr\  J / c cDPx-$0eZc5/J zk D F  > N W f    0 c Xm~<iL|IYJf1:k/sj d F  ]Z*jC?y5i;;Njmnvrxn4PR;F*ypP=s&}'0i8exc".S]l  c &  oI x h  @qG`6`j @ c 7 L ? f / Pg`sK+}|d 3 O i ` s  5 ShnPxC\u5gBd DE7,2ZU0$Y#jzBQyQ(Fl?CN |2Qs} nzrW @kackA2fc}.~l~^  %P ?NH0H2   h  ` ] & D |  y  ~J   $ n  S 6!7,rG!IzzYS=  L~ j R  q ( f o  Xq<-p?VcSi&yVJb=%Qs#(AR{ 9GxY+ao*>B R4cLZLi/;e/= fW_sYy?H?"IWV*vSQT\ c/qi%O\&c)g D3;YdcMHncvVS^sO?&dJ-3OqD3zz xfRWvcbs\p!= %Z5vaHkoF*u7`$a-EgH hES3n mypE]>EGx>jpgR:Km"iKp;%A?bYUP~ktfj|yuq~d<-z}}yF 482''jxfJhr0#0 n[qk`y S2$FS<kq+B!X*VaV aCq8gzSq`F!+Ib[oey\1Q@ @e$F<k4+2bq} LvDL3~L [A "Lm_v&gQ<5 p.1iWMiDmoDDDP_ 03]niNlQ0{Ug0w*u0-~I;@b4qihr0(ZC}=, [K%:Am" 3T2[>ppYj9mssQ3_wx*99t q8r ~FM9c" voJ2~U&cP}eoV^&5l@l6W9 6MFSo$enCJu'c\XU!^@6j2>63#UHz`iAm'4gOy{"7X'? v;<GM!'bUhRRr=2-U})4` L$<HHo[1SI|M-$ L BK\aaL;NOK':7T>[/R=9>{be,9Tf@Mhi c !IaS= 9yX@gI  I*X kWZXrQJ$DsCCQC@ cf"Pc\WS_-wDDk5*6<JDBT2yQaZ[4-vS8b#?0 rh ?H^;fqg- _-|f,nOmN` ]OO`m~mmRGWi j9!(!g{ 7u]&3bAiy/[WihHV="[kL*h!J-vxr`o2v 2eoHz[z?zWirg+VCz9?L@[Z`2cIofajjB-7V]QVgj[EU!qyO~VAx&AV/JrUvC k E]_pQnuR1249W3orgi~0yJmuc+Wqo`1a14Ep!s[+){4rxC9./`r/321vQ 1 ' N < * g U  H m  6 s V & r  $=`$@2yW4P>6 $ vQxZJynZOrqFg]b%`D2,$E+dVJ1t8tq6v] * ~ $2*_c%|)%X3 F.Am)]E3f/XKq B e 7 N A 0 D 0 s  ' a . V zD \   w h 7  *9 ? xDHWz^V 7 Kt1@v#`MmQ4,|dpEZVz3Q"DJvR0Ozo'n6AR-7VrLuxu#oJ1v{INDLjp  / $P.-@ w"X# m$ $/ $!$e!f$$ ""-L ETwP ?" d] Om"^fcgaEH.^W;G> o '  6B t _sgv n9 nBvCNo0-U`>{ O! D & $ U &xd UD7S Civ;!N`B B  ^  s  -o(4[?LS-Yi>).[)g~!2VADYK U 7 5Yx(o ; ^ l _*;Q^A^"l[*6'U(J?1AK;_RlBc&kOK>u#\"4=T:^@oR`y݀݇n>.fhFVd@[+K4  &8J_}cPc c{#!%$58a&og~a1;Fm'_YjOVdatCRM'IV)-`3jnpJ'n4<YQ  h 2 : "   r  zD:[{}Ks^8HH.3p~=o\Q/#*qr:cq'qb9%> P3H   % Y<& x ' J n 5 m   t;  o Q   I R d   jh 0 T } 9  0I{Bg@-AKp9![s   F k ;c   l:Lvuz5nW:<`u["7He4.0C? t~a[R[@ CA@Ga~[\K:**x#< NP\>h'm9x)McD{P(-Dq a i  ~   B & . _ n 1 8  V u v t ; X B ? # } )  h , L m C >  s @ | _ g { Q V j w B c CVI,dxF3g'iU4=oS3V'Z;||m*{[>sAmI|NpH KJS`S,2fKx##tLH};T>'VNN_A_?wDCAuP +[(\fY8_WUzZEs}lx,U/H\%,LB@kSE-&[jK+\Pp&Lzi XYf8~w=_ p_/E^M$qh$L>-}f^XeUSn0KIr<!XZ?9kWa WQl?z7I2lLs<6Vwd];%J/>rj\` "XC]zB#S  .4Wklf]/)D -W{)7r0T04!n c[{4 #V[Tn8}0KDS'}}L\VkPgDOE~bS t'U/q[|ty49K@KK\,tQU5D~cZ{(F#ns3A-ZHG6ttQ`I6rY|5U4)s5:1 2N V S+;A 3LK2mouZWiTpC3CO'{b3fmG!<fkB^fY,'fYO01aRk1`7~,6:VC-Bfh?Qc4B`O^Iwsj,?1NSu1Y7]gI-M<=X[LJN:J4-E3+)p;y<BF\1i X*$u|N;Yg@VKB6H1y18h(kWL\M[W ~<KG_n{4]6SB?H A RIgn*;WLRVREi/c,+uyHzo8Tg8DKGAvvNcG=`6UNXi '|k=l-|MF mR Gk"sD.b . /  vLD qx% y :??g]YXAA^A! I. d }  L 6d  jL*lE> L,8N> K=u(M@GoG]7>@Y@yax ~VS*9 2y>>aLvn duuEi4ioY.zqjqI;= !  fw''PHehlNhbp]lw}PVg+y$5%= jRLr_-s*@]=" ~  B|^ oX-Ob61XCSU\/&%)~j H NhH7*k&3,[e2N%x-(`|FV786U,]APu7L;&F6s 2-';Q@*?xxWH , kn    b  g k   p  4   l A t H q  _ & ' * r   / l{  = L*Oyy6PWTU]\BhOyq74?1UOyNVB;\M `,^A`xdpB`Uj&O""D"7 p!+hA%wr37AL Oe DQl(nX@Wmay+"7z-l IS%'A&A0Dfhl%.U(1H0P)E0*soQ1`u8|&L4]a&GNVlq6Z"~o\T+Y A<11zJzjKPK]H v*cgW(crPr4{;uZ95Sz"#916ft*Efs~O&l6s{[g&UB~yIQEMl&^6u/c"i?waj~*eB];CA^ o4| O5[$]L-> Y `-&;c.=9,fy `;Zy9VQ<;a\1g "bG|66n|7~O]=dW,74S^)`,w)8hB yQO|AL):&j@3#$4F!h[x'Q^ a`r>#N*q%/hE3p)"{,!\1~Q l/qnEW_ m"mI#4P \wL: _4=?+V[lOnQ #Xm=\3.JBKTm-z06 MP{KwUz5t]Er)T6u%#rO(O,wQUVVU%]k;I{h:a_Y7pVuVuA-c&~(w3iqss-;Q+hBP; 9-s!W N iiu8;H(j;d 3E10`t`^:vf8t<LF5ut,vw|\D6^X[A9DCvu@nM sp5sKK<_j> e:e{6j'O [n uW{O)JKh^4(! `Ew=U` []%uAP3jRf7 q!u~itf=c\Ca iJVVK83vGScIj1?OCgnVcPe qqB&3W,(HVf>^$\ >"d%^r^</?Z#P!9J  uzl6Ao%ZR]R~mv  W*\_?WTD=U22..;"pi8( tH\vPbRm,D7#ms'cfR&LH ,]!' M2zPir8JCyv)jiwjq@i m>Tm*Ng>puIR5D C]&^#uH x"QRP`W+2Jx %P W'j97Dn 3hfFi"X *HojKB B[Zk}n!Yg2?LVBA{n-`{Bi2\81=jjqwYnXH8xw*1umA &t>U AV(DW)g|Q~ ,XR+W {A '+4Zj mxkaaH3yPD^)L 8:vKg~o8S1 q9 jH4gK=djDw)HtN9 Ri] ``)tGb:9jA:,]&hAy jQW@Cj~P,A^=2)j# zVB 9hXB+XWh!ny= E$r~orzK{gE"cQ:o!8,WC (2riS v"K*z^!+9Z(`+$?(4xF2HR^Sj1@n'` L Y_|pz|#[73NUfkSW83"Pq^ 7uH 74-L)3k<H*R haO\F*LX.4-$F5K[h7$# {P8Yrkuj <[Z$1JKi1 5I :%M\^?;WB@qPF8fS \i+Nj6*%7r 7 e^hJq=<ys\.5Xc" Yj:P:VZzGQQ)Jx3c:KmXg K *VHh{N2& JVdV@[ y3~zgxFr{0U~zC09gQQ:>90x y5p]mvf.Mi@O>KO9(K i=!R&K['Yc#vPf:Jx;4~#{oqnkh-[4~q };3qvW14(<HnJWI7%oVq!FPWk~-j:<9Fqki<W!B H h9=3IKKqq3NjKZ=*u+Hya)-c'I[$ro e`F*F*;VFB3J@g([v^[cl#8$b?}?iC^vWB$;rI o{<$Xz7rI7?ni(Z @ZD"$$rafHWqXgSbCyL+0a)j3f*k<0@yyhkbv<9(2C2=zv[WGK?PWB}$*i@3<JQyID0-o"W_\|0j,jnZ,L;g#'YO\_6V*~j>AA#$orz 0n^YtOhE28ZQJIkBr!'a3u "Fya`@ yyX3uPRWqvR;BVK,33nQo<* #g{W:kD0VHaAh+$B?Y=4HHgBho@u0[v oRX7# B\xFI=0q\r`,WS#ai(B!cPWP7#jpfh;@"~c 4Hgk P^q<# F{n%d $$Z,ZQi)^h 1  I yjB P P Y B ~ > < % N l'ZMHjg_5=S8HZ=@Kg$U,DWXIW*8XGHioL:[ bv#>g)Q'R1%Fݱݛ)f8߁|M4%?ON$O%  h T '   p H H *  9w"DLH$X mTFF=    Q F L   6 t l } t  ymt xdEh*Z TNg!!>(y,&x4Oq3V9VftyYIF`fgL.U_]GwmF3C/^7eP WJnh1~vDVފ>eoO߾%Z@ [-A!c c w E . ~ 1    -  A F 7 u t| vpu|qgSKW2  r  5  _  z   i>z 5 )T/xj < ;  ubHC q _F   .5:%]L6 | i  [c O ^9U+-Fv]L4*zl>kX >kn0 /P.Dd3RzJocf:9ZU0%eX ޻^aQo݇@4j{|=7 b]1!^Vohg f  7f  |  nB % t  T = M  1 T r  @ 3xa%w9/ZkvX6GiA`K8V2U>bq  i 1 u / ~  OOAf LDw;p%$`>]]RXUV,8=IH4_5*߮)j-j*sy.gx1Qi^M|U 2.  s 0 " 7  E g ! { jw(P)-CXh<n '   g g # n  & < u )Z:Mu?]; 0$X S y   J " + P  *2gFb;a?%q?T8U]-%h%]~I &  F H $ l^ ~ B h&V@oJ'G ^   T - b  P :    P=UR3[{-:FYTIP6F)+0C( /XT&)ep`OZ jN,Kc@GW;~ $;];Dr[>Ph2Koq ; QHKe_fKpedF@}*d #L'm6kS=re;Wah#Xtn>2pPe> W=O(: GF-fc`I|e ?wGN8,7e_w2w% Ou hc O`p|v^[l )*=Me#.XwdTckoC4ahl  2@CZej$f"f)# cRw_29uws[awi~FwHi/dmAcP7``/<@5Ee@v,TNm2Tway{)d76U|BmX1 vnZ3g[iz<'hW,h-I5rJw,MK8 ,;;9 u1 {P,Xh jq0F5L_TIio O#=_/(g0\#tdk*4't7cLn'aI5?b(+>-4l? 1PK[sKL^YB;?#x$( zC)cyM\;:H}RmOVxcP=F*=#}M#dF!?'ivQL9`Vd:,O9]L]z)j9[x r f04jjWXftBv|[Ul FsP"yw7frI }\"XZb <q4bvv-*(S8 #qLvy Rn3 jdw=!S[X,[ON@] fn@8qPxe^Ry+L{aLLXD`Z\!8*,,c [1KxhbiaI^!?nxC q?yA8L2 \`PG\t~Y_: 6JR|cUaOH0 vR"O%Talb6/heVL+b?H9ui +m_vuIhvN)OQ0I(LjBz^Ew<Z-xk$~X z5xNW Jf{+v!vr$ k$f*a =@JS,ziyJzIh u(u;#.oJ qb1vQq?rWWK~)gYSbj-cgRf<C'Z1x{~J"[uk<7n;koCia +}3B^1o5H# O`!r7+@[@<^?FO Co 12n?I`ni([k_^<QJ[%=2f02WWKVuB*4V=xhqa[#' 'o #@+}!J J#iJ;er!?Rr H=~W=*'JD$\41o^,:O0k? Y#k~`P hfj9 -HL gDQ|8Y`H;PVASIj' Au`#x mB`Dr*n&UgR-_CV*V|bqi7 #"-'w*:o7p )L^YZpZ?O\) yQfjKVuw)-Y`bHi=PI"~4O/~3D^O@C}qR7`;~jB{rOYRc;'JU:WWhHy:%Rny^1[@bD[ruC!ZT"!D<p-ci{wsYs,y<z$5<X5swo"Sb<fv%X"yi  l ilyw8 o}@8 ?PPFuq I1'IlB_;bB 92^?v+y*b9QzqC  a%;$!IT8*MJ\MG 9h8X+"@xGXohcC2r*sBs8*VjZO u?2eyg 'Xz7Yxnh`Qy\$bCEqybaK {a$*=^%e@F47L8x(j*?# Xn8BJ\2fx=MbzTX93KFVB 2I # XI#~k!aS?W,u>*" n E7hxkB":j~`'Z j3Av (8*@j=&aPXgkynB8 ~@K+|Cx0jhfO;XD4`DyO]Kv2;CTg:A1aV(\Lk"YZxf1D=h{ [jv^0x~X)=O'Cb? ~?o[Dpp8@Job[gAf%1h;v7u W0 <c?{7X BSJ#($u`WFKag q~ jx{cyLf?OH: ([ZVrDiCJu-0 f%YHSn~fLWV L%~v1kz~ibk$oD\`( Pl{T!,/ 29kX3fqyix(S[Joi1,%GDTXWFq k<qD3 8}fC=1qs6$VyqC y,1, cgKWp3:4D9E]u"1 zvOynfnJ4^?ne#un1B}vQzqJ Z;^Q0zCrKxer'"}0{;aW1!hI;3vHVI"4- PLH;K#^y$Pc3ac`qYZDn8Y(P;nBh9D:fHq~$8Rq(*;HuezW-AFA ^@vV'b Qhgoyg?n@% *:79'!0^W nF0 P;L74H# at\1H;tX g9QAa;a]?{FbQw;B%`]lNUrUN!4]qrk.4yL<1%O2 5  " _ & ; w N 7  c h w ' | M*w,eT5Sg\h.5MqIgB"=U %VFjqMtvU?P`2H?/ce{jK>etLpsc}FCJw7u~.97io;Obb:B   u u q=  C  xKUx%Xs%OvecHW3 GS0WEnfx@`q$:23  P z  < l / | s t ? } |-tpNI@;v:*kX;ti*=LY p Mni*KZrbr/HyrcS4Cxy{ s?| ~) )N FoW:*6\,#* ^'hZ44Cf1[T?<g! pn a  Z^(Q5N G! "!#" #!#C!+"| G! 1%W ?    d 1 C f    r  M ]alc]T#MCB=] )T a<9 0Sjn, %- " lG$eY@ ~  Y ro,(FXd 6 Mu! n@G26J_Uj=gMQmQQ  :dFo|-m~;zSN  4 \w CoSR{@&#odua"C]?B6h=aWy ByssvG]^sUE y;0!;?q;Rޮݾܮ۴ۻ.ެDߗBl{]m1 u0R9 Z 9 <  <fo{ r g  } Z d 0 s  H _ y c N `z ?B]KhH lL:X?7 Q+Rt z:f~R_DZ }   , N A  7 M1Q\@q(le ]qlB7"eI>eC|Qv2W^77'}dda&=56m2MOJ{~2NވޙPޮފv߆:etJ W42[ N +  6 O j  r m #  }x KP  { y ! K  F J  > D h> lK G } N  t k  uX   _g #d{&\yes%c.  U  - ^ d ? p  T"kuU8l! 7SoS0Y~1\LW`eGG;0"QZ31N{{56d 3)Q9BzR<S _Lit~uBdN;w~V59-CI }Be`PQh ^   rY    J h    , B   3  @  A  V ,   f j } o     .-03mUzQ8_iu* j#d#il[WdAAoaM7ifEEUK/KD4w~g,Y/Zl!?{D.!XXU|=3JHRI4{${q$#}>KS(}r*R]w(ZzxDM]=>{qD-5KCC[qah<5a!<Lz^ ?`k9"fhrf=ZLnuO:qDKmQQ*]%H2J@N^oELV1G7HU -Q-3bO>tznn]NUHHXtU-KAY"&'/)&% aDpx"[nY7C}voPJn%C-f(S(9Su?=k"h[WT;X= G%JniPQbKQ?$9<@@bPv'u\WcyI,H JHBBfBx~"i*9Mv[qb!yp88 YH Vo<3iqwUp U[10^^DwY_f{d#?ZxCCn5tGA^gj#9 -0"fhI J 9S(>}2$js[  U,D+t Q,;] uD%T_zc%%p$ki/  G 2\{Qri;CPbp26B  Qu1Jo>y\V[vr%g1oBz  qzZ0 -Sx7z^^0$##4 v$V'yhyQ[b}SX=hW9c,%5=DzpP9M{@  `3DlO  6=t Si J@=/&Yf[IGy"2kGb'^lhs5+19 2hZHi++N)+OU ` _~=+Y>0>XN)73 A}EiSx 1'"D:,d ['?LDq3]n1kB-$911ZHkFr+3P}FHC-0WP^[Fo`#<"eboWQ[CBiH1\Y;vxC9o-`B 8Az X CJ< yqoV=7A7nPOhc)A\~z@!P! nr@fR;FKL`}hSi  zV;7hn,kMrpaTa!rSuu1!ObOge X5="+3u'9 ag 7xho+eoI 0F2O2*yB +0 yguC,J"( `3rpw_KMkK**vfl29-9By'@Kyaik n?geD+{ykb1 q=__8$+9_BzSuyQe@W7 WO#RO7,co{qHo~-W1%B{u4@fYP'CF9Z0kIv*I<7PH2< ^vv P'@`-RYu1nPI0F-^4\4 k BY^LZ`HcRj%jh rPO1fg?;x`y`Hy%y3vfZ`1[  -$ W 71O+n1W yr'k0@4[ L-` 'x;1C'{3"S # =n'uJpKt>zzXUfgFP uR L, ca1YVZ2Koa^E8Jae-fuI0r:oh y` u[ ~yZ~bp9c<(V-"PhgvWnzhxh!Ok3ILe+vc1Zo[1XrvP JT,QrVS9 a22+<V+H(FOgJ4$ O<8k0gfZ* # 490 Q[PSSD+, grqyq<-11#S -<%I"kJV14y^Qxu(yIsCC%hkH jR#DHZ'0qkI^noi-84?%4*9gq$a!(LyS~@1QJLBuS'*LPco??8 =P:o7FAO\Z V87cuk4 81*=BZ?xg:)I?Dk u3 Su |EHR3mgWaiFen42 !;#a QIuy "8@Pn$WvhVZV-+v4a`(nxxBQ@cCZ#kVF^;Z-< 2^hnfqguSyWZ,L YR ?}JS ;;ICo?PO ;K83'M5Cb($aI20hH93W{ Zr,\,*C!FC<xJr*SgqRk"7\P8j,-K:Di#Gg"uu{ H6>j0 U)O~AC'^n[8hN\=f{-?uqs{)Ar  Y D : q  klclIN*FQ9  6 ^  +Hn)Q^&si-vKT9er)u !C0>\R/yRr%3qoR>r7bTON:|C sZ7Bkf%W܃&>ݔv7T{u2Mv 7 G m %  ^`  8g& $TpveZ- 8eGssm y f m *  $ u S , D q Y  7 e C  9 q 7 E s ! o   (  m> r H Y 7 o x u  B ] ;K'O]!ZwhX;c77Kn/#su^nfEvM8sXV< &qImxgG92G=bK~Io@Wx;jw$w1Xo '{ %zV-jy  Xr1sq$|)8 M 1`B]#a7lb1@c>&M9q  f ? ) : o  ~ O  I\B%K#/K?Vv 8 T u 1 U ) (   ; J6DS*;QJkot#lO],7%\:emDE.`tm2x>VG[5d MS-`ޮ݆&,ݦ)ݗ^+ti mY W;Fi)]4U>uC {H6<<.Jo'8 &R`Bt3tsjWrY]EsGjX/isl- d 0 ^   Pf*&(>\-6QWeCpvT xF%ZxsR5޷|ޕ۸<9֋؞օ3؇%ަLZM!*z]W@=_~E#p)t: 8UXDihzrDQ\ % Q   O  Z   x =# +oG a28<z `, W H > b A b AwcNC`tq`.8'+1lSK6`@|6H2'xޠp&lܖ!Zxrku ?FkR y v t 7 t U  Y f X U *W f:;4t Isvb9^  i n = h @cC7F?WR    \ zVKf;d7=Dk9y)lH;up<#C eRre\ "E~WP^V+Nbtr;$%Z'0--tB<lQh.VA<w>">"XJ9~E+j1=qoH1i`qSokkF40Jl${[W'$D^O8 n(~#H!%y?jbj1P4m= :Xxq7pq9m q`C+6YJ!K@>UAUjd ;jd[@!!2-@H[[ #$B+8EaQ2R)'UWFjf)B ?xkhD,c"- ?`O!WJ #*%rg; I -V?7Oy4$i7LkJiC WnX2 ZjnJ;WVKhA{'jI-$888 ?oXR A ;xa`[S*J<I;,[gOW5I1,+!B" "%P3  gLQ ah 0aS%;kF;;VU3c3/ EbG [A. F8I.}dAUiI.|yaN?Sh| *)"1Aox{Zh(ZKDHZrj$Wi{W;0qvkn%`<\ zQ[ya,=ziZ <W ,_hzr  cXIF;~ urhIjL7Rc[| 8W*=%r#yZ`ooWoPZ+FPH~%o"^:j #P4t&+/gp-tS{5B<9o=_2& E3%zKM<mwb9b3D1sGcI@Ikrv=(B@pc5yT$Ml9JhD`4qgv`P;WRD0W]K" O=qx][`#8L=FDv#uRo-*;;0S;y^F#KnZ`Y)g%jZWkoDgI7;Q$x4TIZqo9*J@Peyu`u{g:AD"4 H7]9& ERajw-v)SwY\qtHD[f7x60q~!3 Lv#?@'?-Z;Oe\'f*W?*`Q` J[#C %9@\Px<zhBIC[ 1nG<19*S<k*p=,9z[zkrxxnrXH*!*#8-  IH;@Fna?^0Z[8=kZo $-+ 88;a?Cv'x?(4<$ ^`L?2Sv;}Pv, enIk!#; 1_1eJ|B*HH0mknw>_] 2I Kg341NwH7Lb6Kk|9(2Gme$,Uj48] -  -  a 9 2 & YaZ: J!)0ww-o$-tY6g WB^k47 (Ld5 Z\ [UH)i-Q ^zP{gzmK`#"=d@TAEVrn`1d{Gk0 R]~prMb+VH7K7h)VHVg9RwMm,>d;{-' ?BhhC e|F2~(U[my=H7b*cbs*j6w*\S c\O=OIGU'&}i]<k<I".}nZIBuuy^RR#) mEC`uJYJ0=(/-6Qp"EXY+`/u~un ARQ:z= 1Rj ;Z~OP^*ig1P J[zVx@!++rhapy9zKvw[k,KP~Sirk@c8pZfBrK%D"g"%*[<}GvI};X[CKoPuPBJJbiIbnoZaWg4u4a q@HW*JQ2H}Cb1(J'rn{hn{DjSV;VFcRYaP, D Y%,F8o%8 )#% "4LW#Ya-^ x yhI1FY4WWg-BFc?Z`hyZ'[<9q?zZ9O< `g8iLW a`eZHP<v'q2S[[iry}ZC9 Z[8(Qk!B2VcY;0"^kh{j,OYuKY#h")xpXz@t)6u]~~bt"1-8D* 1K,*fY0F % PS\8%))a'o';=cIvPLkHggyvIqY B#4XbxJCLbxk$e9QP^92J[bgLXhS98@Zu ub!*$PPxO?Z}eLJZP<+C@Bn-qOg}xx<Q<S+$18'$!(+# ;#I 9 1HH,W0*~#S\^q'F'x Q+<;h1bnziogzJkqL;ge+BSJ}eyzuVnvnI^HkXe`k[b[Job C!9812VX+J94kq' ,Kh^#-VV7;*4XkQ4B( P JWq$Z#8L`vy`oB@?F0LP`a@@LnkOJXe0r9yai;-b`VrkhbFF20h2ihakq^o`99 bXLbO$C^#~kWIgv^`xkcrnuVOVacfOK#D,)17HAqP0f0xoxIH;?y^Bu7^Z\jHcyv`rn;=S4\ qoO$uJCeb `OVB(Ozb*$XP@yJQyCCSFVF8P(ZkQ+ auoWhL$F92Fiq-cS3f71A7rrv:{-oOBZ\~fAxWkS*BRZ:),Y4Y #8v3Kh1R`*FnB4Bx{Bl$P/tEfJ_&e06cak@OkSNrq:Z>jTDRj\b69zIw2gkVH7^/JzG L+Hit*w4 Mg  ' H BZYcE*JVntgL9 0I4vhz$Wa9_cg$${p u1!ko~y{V3+Q>ER9=f-+\etW(:+w"I{ehcN|(Fs\QlG9U/NmPs2\@i !"Q&"EA3U ;x{ 02OeqXz =;ki_a >&ADR==$$" > yWv_Ch kKf@y k%x+IF+#*''*<$q{SI`BOA0OZH;8) 73~H1ug% ? cK^c4ALu,Zr1HfWLca{@7JkZh$ (- PP89( xKH=HR3KF&h-kq#-g -E=D6Km9p]jark0h99(H0Z` U<g&-[wKsqGMA1"ZU*qt6t WZnn'N: g\ s%i_,nC P;;-Z:5;$kc$ NsE{ra@4\>[j`=m)5\:tvS;C+5 fB.5unL+!v;@#H11o-'h',* n0_d/E2qh{1\WnH17\S^0?^OB0v'L;hiSa4S2LX#Ba{A_tCTW eFdR)B#oFOeJET?Cdi 7 8 9 c F  C ' P ~ " p : > q M`KWPEHr_}X N_e(kg pD[!X+  v@Y;  C y   .`+Xw=I?,\\yV b,q:AZOH:'}p#8lkxZC*X zRF-/?W<1 M:[]3=%-8`39?gqS)I^kgjvZ0PvZ8)))1aP7,j-R % *h ?DB"OI4oX8Tq5Q\;1_-R` 5Ib4qR{ERm&{G t,khYu  it>m2<yaX"^acf ztwN(qd=u0gpP:8*27hin[%P%M?IX;Z\Kx3#I5EemrkS>cX>) Dgw:29=AO 4&sCM]^r RCKLb :[=.e EMRH9*ppJA1G 44V<@h.<>@W[ M]d!VL g5|ve :w)mt7H?XBZBizhx@(<^14!X {6+!  }NS8Q)oL# /Z ] T G  o d x , ( 6j!JS4c~I76R{# cC8[1IY4ptQDSw@giEl-/mC !^ |l?l$]+?lby.Frn([.,@ '  TUb='TQEs4@mu &"X,In\kgvHyJ+kX[WP7+ +Jb$~  yXB&<Y6/6RQ]}xq/30dI lex[/e5ows5BTXJ*D*!%+4;`u9*y^LKanA{8L id6# +\l Zem8 ]HUa-4%/$6U =%T:x6PV~'~ovNLJn<lfX<wMJ<}wqgtY6&4{`5Ko(PFqb- E`&yDJ19@ +?]nC6cI>]7F.Z$4RhT^h?c{Eb((o (65"+ Y%J/~7gR"j`LVu#2 @*kXrQ@oa1"i_[y ! 3&K`{6+W_BW +-  cc[+oZ${8rfcaI"igk vyo%I~:Y%gD^SBHF%i|Wf ufP~ 7AiIg_04#4D3Rycf=gvq^Zv\of4#L\=n$FO1-Zae*n b=C CRz=_uS|\hyrn]4 0hR'e6/M8 c2nJ!:?:>6[Bl:kPm!vuXr&7g&/5K-^;mK\r&B;=^WQ/9e=v[(a$'179ezc"mb=p">B3WDC"DIhrsw988,S4j7 oB{r`4zBgcHuV BP%A9&d-]=jNq|bfX~ 1HS#O=O7YZ" , HSu#^k~ {q;77n8#^!o*B +PvzrguxPaqu[`  5%sqtZ=X WXei ! @ : f  :##,&o{IC'=PuJ |H*J=j%uyarSvkq#V`uy+25>bp{fX;C"{T(GJf[1S`O=@C_5LO8|q (J]\MSGMOh3J@cs eRgy M z Q L n"KTN+|A-4[Zpp1+r8~1K* Hj{9N6L;/%=VCL?$n LJ[EE?w2 n1n JWe] KJG@sKVO\D]1.}S{"K< g A,Y "hx (!M1b7K|T.\DaBEVG49W ` Ic 0s4#aM\>\5Hc"pQ%+Q^H2"ZF1m2D`w[^cK[=a2nW1O > o %   EfNXs# o 1 W . N = P v  @ !  ?  ' r , r  J . b 4  Z L tPLK{KE'Eb[1zHK.0S5)OpzPm{9$ x#v   /   f - F 6<! B8_fU{&i=B+8r=zTW $4\*-V_dsB/]R K~7)2 g+7cY v 2   6 K}7~ = 2 7 O m ] D 1 c j`'y[X%!k0DS9M^P}3_p%E4Tg+p np &FxSH,  '  ~ }  ' % 3yk8q}p,%`r.xB\$rPq_"M8Nc0HSq W-fD ^!; m v&OVR,  x  X  g=K@{>K==';DCvaG.Za<+aa"Op ^ZkK;bU@EeP!5Q&TKL <>6P}BXL8 Z  ' &    vagq%2?"9`gS5&Vc\{,f9w3I Bu#fziv |OlimiD$ QyhVa>uW%!Q3_- 34JFP} Br " =pjr7&B.|ST$}w44Y,_E>3A2s!z ^ee LO/z)XV@KFP)(!A-[jxmzdiE"#HaBbPv=YP ,#zI30Qoj!Pn $' *W5h;yT[*S nr%D Zr"C.9!<_ Sch=k~@IB49=Z!+oF2#ZV70[u[Ijfn/@E/U~wmNf[]0qtw]2YRGt@t/YX_xz @_G-d/B~P18XXq4`ZQ2q\0~8HW\8`8;{?{8nfR6_A97J9Q/] &R9NOZk Dr?O#qI7LnxBoI=0z:Wa)  9\.fJq*KqYPUA+V&cUj|CDVB8-Xu1^  9-2Q=fH0xW~ey`ZkwaMbac\S$D+(0Q(ha%,lI3P%=,hv~WKoIekG82.Qe57bG< #FQ^'`[@ufn O ILh~+o; Pu 4P-2 S4*n V @ bx!pv3 @aZSzk X~2v[=QSkoakvB?4z@v QPPJvLuOn`8J} +M\,9nCQ!+O $Qn8grjVW3=L#Bc$4SWx D1zmUJUUnwz`gdwd d_E8 BvIfeQ3e[H!yoaoqR~rga7/0=t0wmG97| _Jx[GXmX`LPnx[4;* 4 !4+h2Bg[Iy 8QF` Wh7+S''n2(fggYq O7 aVYr\-[?Vh^\SM(!'8'! 2-2  oez o iqOO `+fhTJhf$3 !j[T/Jv hv{C,}b,  !SP[7bnhf(KJ#`7WFfS9(iy}vX0^q ^.$q8u?ZVWC7C7O@Ie P=p Sh(O1yZk+$B -a2. 3 (vJKkz 8WkkhiOIa*="G"v*L4;-SSr ;H9!?Z o%4i _m i9nu=ynjg;YQAr3Q#qLQOBjZ1`P!-xqrzk*.hro+xX#9QC *H#c;h\qgAA'A ) x)6Aw?UQj]'hv,cb%O_ '7 jWx-Y93 D+-!**7)=%H;;1~ a cOvqS\ao9ZPgW1`RRrurF%W1c"n=wi"7_ EEtG0}X)2E6R"b!(QOOX&:R[g0j%Z81gYK8LraHH'4\n 3 HVR*;,RD?R4B %  FF1418L V1cPf=0D'3Wv7H#?)P ocoS:^x^yYgV k1*!vO2OOa!x-^n[H#'V h@kreHOr?ouk9Pon!Wx`5}W!o%!(z'J;71(1BoCo "zgo+BFOkxC;i1W-Q;#2C!8qq#hHL}b C@%a"$JJ 88Gbo,vWb.J,*QS\+Pa3,+b!CJKQv*(Piy5@o hrZ lzo{5Mf2wMG1hcbX.2W&T-TE~l zs __T=XliK{XkpK_$I%e[Q?gkoOPF+4@qvH$X!$Sg <!74$$RSKu0{H4 qL%Lv)fx:1~Z ~e#k? `0hOBu4S?^2[4$V$}41$[J'$bi; <# @S 7#rcoIWISxgxqoOg7I== fKjWo*0'fkhZ3n=0H-DIhInDvVFSZ,uIZ \ 0u A KOK7?O?j:WhxuOaZ -nDO0H0WjvvZoh^Y{r~{k{\KuHhkfjyBa1B*IW 8;VBugq%vxWD=71 un ojSfHaZvS4*27$1-7(7(V2y4a(! O @-o4`IeyLe}xgIS'S=@{nk[H@F^ e?Q4oe?!(!!$2Sh`z}igoii2iL`g`xee1z}Zkni[rC  }a[yP1\%zqrry^nBHn[ooQ?<n08ouq4Xg@Lae#7(n oaSeuhW?C 1 4eCVJZbz}Wz^S;qqkoyvk@i4<#H'kounW$8?'H!17J0SLbequk'2*^*97 '$@<<LP94g*WV'*#k8uOoH}8P14 2o[?2Q0O --$* 4<794qP 1({ZHR7;y~v{#\fRq`~^'H)O3~~2hn@0J;C#9*g VJ1I'hrB ;!kZ?oy{q8huh8 ShqP{`?r""3 / OG)~]OJ9Jz~E:HE(jwzx 1 4?48x )BDq\h4[aZaheLZP7WZSroW[kX(IFrQ+Ik82ggr -CWSB 7$ .h 2J+HWi$8ie <v ?eh vevSC[L-[iP}qZ'@kgI$ar ^n`'a4HL#a8-$BFL+!!i!zqnv SQ7!@ ?Z,B%=;J. LIh?auqO'}Py (F40<xX#gjqF1 1HPW{)HaY$jXgziiL ^LPr1^;X?g"Cr,J+&X   q8{@; }Fy<xB-` fO'W-) m1"W1-OVtOU?#gyk (KC"Jq#v9yr5 XfrBA][yy1 ran [Z@roC^ [V@I' 77c 4qba(f!n[F 0W?":B"n%\ DI%cA\c FoSO kxqQWR1xI 2gY)by# Hj1a7S )xS9hxq.O^18 [25F^,4xB`hjcB31zFJ`tCP>AZQ%~d2HH]F= w]#H!AKxtRjz@J_q7+xQC`d"7 mi7mwvfh ID-7VyZHI(XVr[Jb7OgV^*e{ OMuk7W@VW (CO IyOS%h:~Vf _tRf:[ 3-=W'VW"xB0O1Bv~hSk Q4<71<oz}qP ` K`?*@J`QPgA:~n?H,qLo9B;Bi^hIh-fZ;LBLPS  ?4nI?(O#rJ+zx#k$[-OvrWXWFyqguCp.!8C>fC{\p2Np `'}??I28n;4Q^Cv(%[B2=Z: 5Me #=K g| 'godn2UHw3vF 83g@GaO~AzK/1)a1GU{D<\m-['29X L.2?Ie+b#M+FpSOqX)Nt<DE#Q*k2. P!V;Y;y:'(@ng^ZjnS%*8X ( Kh 4   b  Q$   B  y x   OO;!>mxg,78'Q{NVzmP2Bb*Ze vW44Sh;_V4  / yBJGvC& Z u_ W!F a   # L h.92 P$oZ9cGFwB,iw BR,y[cR%V^4_19n6 W  O#KIZ{`"z)8=L{9e~  !  R A HT l6x28Nx |uyD]}jR{^ y:%L51IJKjZ_dQ"pjd8%Z_Xin-z]>3LK*4p -8iS*wbz+H-PmIYYB d]L*fLQc_<=[c^G9[W^h,<(QPQK2(rg-$K wr)6COuk'rh _ E)zmk <"Ib_ fR.[KynKwL(z0 a &=LEpWOz? rf ^  oV R _ - j N EW &j2{ W3 6b^s) h (:MRt b c q h}U%Q1[6 c B& 3G8 O *' Z zyqJ^ \A;JvAR!k*m/-=T-a"4/ rVNMsNP.%7@k.kx'f{1 2|:eRQj}GE-S~G#DQri&@b[1Se0RE`z/`^Vv.40&WKd ?-pLJ1uX USo(\gV;u=&3>NNlj'g3=kw:M{_;g O t+ J d 0 t  ]  _  0  ZM Q vWn # h  P3 9    h F W\ ^,W  E \   :L 2d   PKT et  N:zv$S/#P@pgivl/kZw u{=^<PNDQf}VKbEPhqu}cx"'@hq:Vc/a0^eol;%EPzt0as 4iy71=<Wi|v<v|L- o7_[p959_Pk%j~ q2'cxz,c&s4bqz?bsIvSQ4$MrrZNy?%eBKLzq;5p)J8RPvgo"hu.BrJ1k` e-o*" ^^74Z,g_PxRvOt +NM9F]{@z^"4fL :)ld 3=_?,!$<.H_R\?|aSZroK[-D&, v`aZSsNT1:DLO#z a |]pN3&yiE(hhBxkgVz3>3^XblXC/!"K@CGJD-*R?N`3C\u z;V-Ti<+;laI(8X%HP^,(r OR\ D!n4"+/d <ES3@!S[0=1nKygR8 5NK]<@0~d!M._Q:u4Y*pf ~{28"Ko^JVDWF6"dGm(0i=RRgWtKg=r"A-x,@i~:8SLqD82hWB!Q_.FO\FI8+IY}8W#kYTy|0D*Zg^F 9c 2X0*N4L I<6    kr |P  (   V n Z#    3 >  O iu  U U;r,}BbG1^\e)7EAYiqMh\A D v ,T Fnq < C g J 7 J 2 I  L> @ W  ( s  T & -\>*QGP/~`+H^Xb*|}e|ZupF++>\^U1XI#gL#WNPlGQ"i])5&9Y74f Ue4 D;k=ay]D}_Jl/x'?qKj/w&ra)3F7-f0?ez&}\&+@S" W< F#i, u  ^2  [H[   ~ 7I  lx  4Jf!K h  O k T   D , ;   ,$ - L    l6 ly8D f @ x p  m h   >_ /F J n* x 2  4 \ y o [  % J 9 j Em J[  Tpx ; *   }   ! i hv] M I Nv D 5   | v4*KXqf 3MA {X,Si{v1"5N 6';wix*%m-++C/]4^b7k%J/TE58>''RgK@p3_5#oOc )]{n41z8>O 8 786 nbW )T ]  A#I : ,Q n AO/#f ; q >| dpC s$ J7G W*.% +U8H5s:<x2vu[giQ F~WC^m=NNF, .@ldY`37 {z$$SoX7jR'b1:qMWd=1Vi{:%yci\ ]~B?Hxd\0 yP4[?DFS,G'K,I<3 q{&W-NTUp G: D b3tB` H qfK\+y+f]Pu6y8fN3C9=Nhv oF95eFz_oReM7T=t* b >54+8"QJsH K$R.v>S,HSu'I.RpTGBA%li}f)X~c6:M~~~I6nr42^ p%B_Zl){6x 6vBw478< +Fifv% _J + n[ R S  3f " ? R`T BKq yP_.8 x_X+q "@"5R!]1B^KM;+'LJS*J~Zn^qH p1LuoTIai!@'o*  Y/*!u+,z+r3 2i9;Un(G68rFSBnyi n?`gk=(+XTW8:M1aTv~E.E@&=h\( LL"q;HRI,byN1tXfA6>Z-hd4]kYQ#ljyeq3918leeZ A~1l,Pt+Q%*Fykp=C+ ;lg@X%acJJ=VSBSN;$3{L#JD,c2+*+-M.&`'>7 GZ6 .>T--yS}FCV"sC> hE=ZYR-2a D,3Te&Zt>pQ-{FY(v.hhAX(Dztd&">%Ab5 C Mcg0D uXUF'viUzV9pvq_sy}@R|,xr$I5b3|_{>[U> xG3B +'De *o%e-HYc7LC#I,lS'/aAMC`&}*cM|*( & q5 Bo Uo/ [2 N IPBbl^p+88D}C6t9B  jX^  B$ c = p*-bfBc> I  w , ! @D5oD\_+]-Rn1y #  <<t416tJ + zH  9&WFA0?D`bkBfP q7 f p M n 9 c j 3 O @ O \t f t oV t n+ L= ^Mnq G |= s 0  Y._ 2FEb  r$ `[ Jt S ' Y  V9 " } > 18oeCRe|"j$4/S!amoF>{m-L!&WNv# (?Yjq .- &|l(z.lDne~\WJ [   7  ^0  $hq 0 `a + X ` $x e 4 P  , u ` / 5 `  J~,#  E  @$=z{-Cc=5mne>ynGz~<K' ;)a66kDXWcK)bFuMBU3t&\HHC\TO BDuw&rcc J mE=NF|fxY n  Q r,   g  }9G M  `W FH | < w _  Y  G 2  X b  U l 7  J  . +> [ Fp % F<` Vt F n  - ` W } A m 8f Gnh+-$>y=MX#W@o+$zJoT6fGdI~ `_{> $Xp/s,]X"5-Z'=pwc)mCe~3i{uNo Wu%Z-k_p+hDn[ZR$vHdtRDW`%ESjlc|Yx+bbnmxgZ!>KxknW;@, OU$K%mQCOV3.|#pBa/ Y\8DrDh `pf OQ1yfxPb2,g!|.I~#3A^%kG9`""0l\ M i>u'YJsW`) O; hX TyR\:\R a(TwYfPa(ZBx< 3XaY %/bh!_zcM8~k~`&e%6qpp{-u^L]j:% D;' ^FN%t|Bi-K'%J(|EHnj\_V8 CaO1>;0k">/E*Ba0gEQIV>:xO-{DcNsv-8P =zRl\lfJO.;=Dp(PS wttp_Q3WM ;n } C/ -CX#@xJ z X Q s % h3 o ]2 [ 9 r  7 u > , z L 7  X g 0 |NH YQx5fgMi $  RN 9  @ ' S | |l  d   Z 5' EM x  < P  $ 4BQf``l pg |-.85|k(Yw<7}x   bv (g k ~-iZg]uf#Qb2 < s    P 1!- ?F  3F m!A #p  7  &"o "] !2   & 6   A) s ) 2Yu~j+z |L ap c,   1B) x0T - C.W|52V^ >!+-zUz==4GIh.Q]4 7@ybt+7ulCzTs}AN{Y cmLϵ<>yS}|D3SdRߕ;h޴pH\x ߶߶ \7ߝޠLG"{x3i-uywYH]9; jN.B#~ o . &' *M $(*# j Pb-X%J[H$]Z(#y@`|">!""Y x\._lgX"<   9\x! w )  s1 k<  , Zh | *+ X@UfeZ2:If6 v-$8 n 5(5 53 #"J P  K*Kc  u Gj \ FR ?  K  d#' R2  # Hd ;rmO~<SA3CV,:v<"rijAX!lwA$?J܅,abT]IEQi0dܹMތ,3O{X٧mۂ"l` yEcGTLZRW,55cB011=ݨ8)A'`WXX'=yo^ X,@YR _J)gu+6$m<;#]E{tL%j&X#t Hfm Mxs(~Kl{H O{:GukRQV|wW ,  ]o`k > c/<'%' '\ f YJjm5@ U  f nWqs ? gY ]%  r   & y Ue  !b H ; WBwzXaQC*#+QC/6%QQ[;jS:eZUZGUO'p^~_a> z[sT<PWR[h~ L" p;`SQxs\ifb _:IAWAB[9Ijp]  y<]ii6WK;u5rSI1kk<m"3 = q8v qr ' P2 Ip T K i J i  8 1  C  [ F} M < 0Dk"$   /=ymz E =Z y#rafW"gJP;{J @ "}} %mnRWh@i%pM`Bkr5r1/q+%OZ)%bJzS3=Y;q)y;kP wn[| xrc|\9p*,.|a;dw/lV&J_4:zaEJ${fh=to%\Us9|W aIje}2e^p-\ZzD6 TZrj8a^)!8FRxp)-;.1H6((`*l`,sK ".1jmJ6J9x^f%ctOxUQ6[J$d+}j^qGI[-ixR^y7b."z96X9^h*(8W,e5<y`ur"#sGcvIi[vC\4''Ye4u w.!l8>.Z C.K7\jb6AungW^-NYX z4BUci3n" Jw.]"U0nM(b-)_a*eiyF oiA8 z JU7-~Q'9EqR(.xxED%k;O$nt`=n9OJx)5U~nK7N?-Tvem&gtzE 5qe88>8QM4} @IgvFnRm Je{W& K  z _  %  f E . o   3K :vW2 5   o Y uA =CT\1MNg|'3qPb5^<_2lbZ0,^tyDJzM8h<V="U>qnQ0< hC/;%wC! 3a  N zJ E  Z R &1 X | _# A p] v ~ F(  M  i oz Cm  D&}!gHt { ofR } ^1   h e 8$:?Ev(Hix_Q O , 8  P  e Q  ,  0 }b 1f<tZ%;qKEL,z;M`0;{0\i*\+ 3 [&iTfT7:]H Mnc\$" j7GY!\%8 Ot':~' ~]@o~jdk{{<5ZcmSWVA 'CYx  =I=\zfQb8 ({'~ti5y JlM4O/jfl2x4y p"q5(S "x`$I\K6IeRu${!NOaUKd2zo= OR]?Rx'8[/&uGNy8Yh}|p%qmU(N~)`r&c]Km z/-#f?hGF/ry4. dneW8F`~4cekG7%aIjYXh%h>=  p ;b BI  [P  l , Z # BYq@Q ^ 4  H6 Ux J~UyO)"Zp;uRjh7:%W%.;W]' -Ii>v SYAR*H1 Sn3=6AO9H hVr8B=rV ;l : %F.GqdC3T q%1"]n md A 3 R o b5 : u p| q _]  x _+_7a_5ej{`&jfua2FIV e_HFi]+LMo(P#2v6PkON= 91>'|nL49/cmx6pfL5i%g^Ar&#}xlKaj'Tby_E%gf7qzH^FV%*-7XV)J h b 9xr2a   AB {n  H , P V D60Ux|Xj} r wuHfH^__E  "  yQ   6'  El   pP  OV I   *? n E 1z Y R lMQ . ~    W  \8}  & < ~ p '   > X ~ 3 vD t > :x N T } < !   < q ) j X O y /)} q |n2q zl5"i W #(00"1[JIg56+QayF'8^(Bln_I`CBtbjBBr\ժQզl?34AE|֖B kژM^_d*r~\fm|O\ܞN+lI; LH_[%x[agGxZ#-; s d  J 1 @ O#"'?5  q @rb @lY #m9~)!+9 ~7W_u1#eDwu,"8!&K~ +i"3"L&!u h0ph8, M z%j.@  'm Rj@  K8  =ws_S Ky ! j m x7 = E oq 1 f9  "_  ; gt *qvaP J  P?W$ I!  ;k vY$K K hTX0H  <%  WK{`vd)-5LG[}eݐݨItߒ߁EG|, $2eA2"~K _e wya9d<n} 5Qja;m'>i0*iO Z'-H/; -b{^QT4  O?0cmm<#Ql!CiTAO?rDrf 8H1CeK@+_lxx)'FA2 k`w<'Rci(DEiX\50.+X0AD%53&gF&p*/t>,M,>7%i gC.F0e:nOq M g I\@, b z D aXP 9%  x  k Z  V z S  OP E Z i x }  r    H ?J g    $ I Zv   /C + l ;{h3x[ +Y( hf!C XjN`c3lyJtw~2h {@j>=^ -TkZ#3'@P=y 6f+mm.lqJT3h"9p&iuJ(B-@ %% Ovxd?'G& ,+<3Q@|} jXgE}R I ~DVK~ \X;N&\B> R nbR{=/m-3FIhFZ@)gswKNaRJqY,a k-64}_'eCEs| Wu 'O'nfUJk0eQ.c=+JNqR tO_sF t+'*fpez* %%?d+!`E|!e'd]4i8tb^=YG\Si BZ ' % 1 |,)dM` H\#*)D    7stOjV $ { *6 e     #k XOY N DvL 2    % !sAz"5 IS T f X> >nhP e !9w Y  Y 0)QCjDJo7l&5H`1LfHeFZx^yv49w;gzoM;FDy co]GX}O% g:x(uh 9^ Wp1FxCKYV.jKxz8; :k9 Ss9d w$}'$y:$y[`B&[9u%y.6x-wzA on*6p[idNM_ =l nU~2Vn6`j7uG#_gAh/siZ_4(4$-y mw>N?(s607ES9bxJhG0fjXfWHSE-SOQI)Xn`a7()(<b [h6pgEx xc ~4_bNC/GIYtJcaT  ~  v;A d ; C R   T4(J(6"E4"fQt     o A _  { c  F% A < 3* I l +r|]  AQ  1x   :OW ' u rh 8Q o v   rK ; -x/G@ I-?<)2$IX "?_(\Yn |HS]YGU[ eC(7Ka.t1MC f@I>N.sO h s Q Z / nm n V v 4   m ~YT )u ~[ D G [ ! x&  4 ?R  ~C ,_ 7   [ n^ " q G 8 5| Ow5 O@ #7 3h qYzw=T*k] I _ u xQ%A, !  YH M K <   W    Ac!jZK\^NA_Of  w6lCj'g 5d yS4  < ` N \ (  k e B   M  ; _ _  A R , = 36?71c=3wmETK# D 2  ) M) .W0O z_u ^:}v>KL_y&v?8Q" I"M6i;`urf o.!WhM7P:jYOrn#)$\h02i55 Xe#]t{j(<oZak_-DI bw`8Z(}Iq$Wocy%wbPkw%_o. 9BjIW5Zq4uGDhW]A/OPa@1!%$ S ]Wk`97( ^5][qp$)A "cghY-&dv'R2@{6d> I r/~#$]6"^"9 4J"-H+?85tKc?Kzq$EOs ]j/ }rij8G?FPxY^7D>ao<>@Q[+Q84R6' %2}hhLFGH{5kd>{1cg4L-VUlQhe|UbHC=8] b^?1uw2b\{gg)Va;D{nxS%V 0_B*R{{v%GY(uTADGl4*o1['RB>#gkI\\` 7XN'y>%ODw\Gs\E%StHa`JNWtI3IA1zD0%A)w\_@Dvr#7#dFi  p^ lF0- Z/Z"hL;14ewv5qD:c51k"[2R =#lw,1?H~uhAZ7l @UB0  u?v}rtV)0KU[rij'Wkzn=Y| ECV@N9):Ar^Z) ,aoJbBcO=Cw<NUK hn rW[vfg@uzv=~;6, k^_[)!h2.?{b o(1!l(9F}k[1x6N47r-phG ky`-aF |&1?PX,+:_9i::uSKdJ; e=]55CE}!5;VK4Tj(^IX&247N>r)< nEh7j8~JF~S8}N [* Gp_/xyy/0< Y,-RO)K _$"n q ;L|#T( 2g Og 6 ! E q _b # 8  < (` o R ^ C x J ~ ; *  ZQ o  1h _ N ; & ,U  Q O  U / -       ! o #   Y  P W s} ~ I   q Yn n  > ^ A| ^ ` P U k  k b     F :  =  | ;lm[I29 (<BOV#3 hFoJXb5g@J3zY\^\k0c [9W %1wd7:e!/ $ $Nu *hR#@y#\ZNzgi`( Mxg@IY_I u>j;q=8&)N;V b)^"6fGR=u-#yPLm7C )v<y9@3wEkxjzUB+fqP :   e`s 2V  ( -3 k ~  9 :  s { ] d 1 N wS i  (  _  C   b  ' J &  {  w A  2 a ?  U v  y K + L  .X    B P  H F G . 0     < 6~ {  5 /z ,  je    iY ` C   j: < wK   #m 0 hQ EG  4  D c  v  d H; L%     W;+I4w G 0- Jp ( X     7  V   h O<  ; qj Q <0-1EN YrZDA 6e (+h(^DA]<LTi".wszfy!G"#{aN[E5JWo jq{9g1:I3czUk..{4{!u??k;3 ]Z6 xlwEI^;1E]K> Tb  "0 ?ZwKC=/["xU$9MYyXS,<s/-~/|D:3CC0X=)O [( [Hx" B w{ k 2+ * n w Qn !V \ ? O K   ; y @  q p \ d C1 yP{"wK} %I b~  n   < bO,f!MmnTuKTO ; O  u,<2 {_svWf+i6GeWqTG~"%}CZK=AF7^csI)1KIJqTSR.\ 9vbkMn'I^#"x+5uvq|2fI5'oc6S 1-"HiL;NYl&KmR $1P166[*MuaM (GA##/3d-\ (T(Fr*kg0)b?U:*DX)X.2E&l''uZsE {B-+ Hymra~y]30<Hj6 j-~ P - * u 2`4   K  z x  MQ77jtf,45(WTbzvU 7F_(Z o oJKp"tW n qL & M) W[0(U3BgK w r #i8W49y   + ? \  x- %O H\EbtBFP7~Nv(-{QSfo,\Idz.@5/K QZkyuo55(`O0$29SqrR8p=7W9Jx&|yG&By9C8z/'4MIna.hlSoQoaNAl eT,~D!+QP]FKO|5VSxR[Yo1&x|';^t#?CLSTay0iA{:o "VJaf6v+t[K{7-w0 d!!86]T |)aMd -i  # :  ] ?N \ " tcZ l# {jtD=Ozh<r J &jRT.rX bK # !@ w * - O Ub r 1 uf)S 0  `~Uk t Q  p *~#YDk 9ylacOfNH+TU %cB+1lZLWzY`:-0AOx> >FG@i+=bh6&]u]Eb_@{ AdRjQcD|sC/U xrHJ-F<k)]m F*jE<*gM R Hh|sLO<(a+ %p2es2ToNn Y"Wb=cH.V ; d) G \ ) h  e  U  2  YP W ex * n ' ]< A    | U. hr w=m  [ l"  ( Bc @y   ``a v  +f1,S0;fJ& @k 5 Ozx93|kIhGTXKP_}LIdHVhu{o}, 1#K Sny6y=!~, WJYgVu479L*+,RL 7?OYO\Dk;}O 6`I&4WyvME.Hh(Ww.v|;*hsr#S` R]e&wLxT,sZY1t"}bnv:j7"`DIu$RFi Gb7Pcs5zm^B(;7D~jDzv{[\<["a;Igq'Y1jY<;Cp9Ya+`qnte;bZwry ;9Y"'Nurvp0[NlI.2bJ&!Lz' + @XKX;{`IKj[DM)<""ePPLFlBD#3;BnVx[lK2'pL,#fh@vkh^9@: fZIv-RjR#0t xj[kHC3R#j73 ?Fp,*M!^V9TA3bNJzAJl3PG12,d@W}WF@G.Sa$3`l*Gn }{/3Rj9T5r0[<>.q$(!5PX]G5)_Vv7Sgza&7i]H.R1+a6p9s~[\F5 `W RrrBsjh:Z/oPivV(qwc7(Fn~3A( -NK-<qS C z!q=3QMM}aT"%S12;; F+]}[bF+$xz)]+J)`iCW_BO'TFF98yrZ@ q yM^#qxC 7WK$< h##h24I I lWR0q J # 4G Q - "H { ` lz C#  5/; `7kV V*wE:a8?{aKEGx_f&;6\'MPLI Q\{A[.@EVtJ mhe>t.R@=`iZ$$R3 ;^7C% w ={ z; A ?] _  x? 6 u |fL  / +  G EQs   3q ] p  s  b' (Hih Ch6R:# $ f    Q     m c  q  *~3     8 <A {      m 1 > U * b z o 8   ; .    J khr    E>R@]psm'~;+cK8vA]PjAyXuN|LWQ%o@KaqyH 0&T Y^ W| }fdlAH=4Z*c>*:sT}"A.x@ _PHLc9 ++4%y;,F{)p ET`u/@lO yii[ 3F8K8v=EK_2u c> D* -AeH;lC QZT c a 9 i e C S F $  i + < +  1   .     d(= 5 U, ] | Z3 m .i 1L $ I = AB; xe]  0^ k ( Q.Y D 0U !s ES90l ? r A nz M  ) TA"H [4;/0[GW="|=I{(:comY LdFdrBKM?' :?g`TQ5 9y%$Q aX &`J%[-2nEQ[y0%G.ADhH4KWrK'4b13k= O/$PJha *D7kKP_-9[KjY6.16]=ywa"x.[;bs5$r^jU[!xPMK|gT+rK'Y8A ?H -C;D<6qs"]0TOQk3yn`zryD) )R+L'x99J8 J*[WZ(U_-og ;/tK oO9z%2Lyrlun)>h&DA B Q Zv <  F < 4"! y; >4 < g3r= c @xtOf+/y*jeHBj]:K#IJ\ n#|L!B;hJyfq^*cKB ^7-lD3--:OKuL!W+D%r<V-=Jw$I'UtXL; D$  ^_{d'W~k6DGzzL/lv2;e'x%J"_cp3:<M KRHK *4K'yrx.! iS 2 ua W V 5g  D XcT zDRqwP\/5uXP!f6)BN(>oZ;}J5' &F5M$oEgBkf?f8f,9`gBCP\C h1 V+2!o231vHD#yCB[u2QA@}ZjXqxIjos!G48\X^=>T8h[{J0>?#:^U D? g!.H=Nu;)`Qf.:*B-TfD{l cDOM[^\ ~yk+,!ogNYpFNt3X Y8V=5_[iV~{!5n-QL6O I{]HC2ST6SOB*3! O#MR:f82/$&97P)'c-H8 I_6.1HZ9b${0`~T!!I("DE;!P:$,Qi-d|BwZ ?YnCK[uKmEL6L.lTul JKV27Yd0 j'&JQbHTmE~q` s(#yAub?/"2QWhJ-_OL[{2t~ C@oLZ:nZ6<iUa?R*?2\<-.u):c\H9?3j(qw[qec3 y  N `  !;VY'I Q  v @  oZU[,3~.`MO{_I ?y g ;>E709y w T  v@ C coZV^kc\ml$93 y  A & f S: , o C S  4 < P# g   -  B i 4<   V   g  n5X  ,"@_ o J 0- K * I ZB / H @L4{!NWau I %#GT^^--;P&GI}]^ia']7vb (Lc6'PH+4DC"-C/Vy&  B ["h   m& C: k 'FG I7 <a  Ac  c  p4 ` , [  ^ @ jH3 $ [ W+-@{;Ib-3XaG.i]'ka-5 :| 9T@"IqR-oGeRas;0h+#(EACIL.=::A+!{u!U%sKHQL~erQ l  F h# ~  f  y59 >  VM <: j % b D  l< m )   > M n E i 2  =  8 ' Ro  e    C ob@D  l  > p   v k -HVTLe Ud m10/^P}+$rG^M)N9H:oTDpt) p[t/(E%D+vUidds%t4D-jD[ ManVx N|znsqUK]S6r]Z%(t[ zIz^AtC_". ]+DwyilgYqw7KcTcMLhKDM/eHQIkvq.B KDzsT-I<Q DDnnG;v>j A))of8*  Q?#~"Hb2:X5[`yn qdL-P{j>FPGw:KAK /Km HY YShDJa$=Np] <P/  a8Xl9(x d/lEU*PV;lf$l9X!og Q#  Q4&BNi8QX "  !Y X ~ . j8 o h7 j C u  : x D 3 z H-  S f 3 YN #d[v5m`N_| #  JK 7  . $ O w {m  p   @c e } & ]b 7T  y  ? 8 ^  ~   < &^ M ^ =n ~ c lK / o Z Mf, I A UX h& Kf q Q ao 1eCUh>s-`[1;OAhXgdyxrFh'd^3E[gEO~KN>2sN0CkdLZPPI;3e2/Zu!O3bFIJouF dju *xDv>1o,-jM. %sJuE}/<70:?. I| t w 2 fZ v5 _y } , T " @   4T 5) CI  < T  $ ;DQiginlg 0,81yj  Yu64yr   [a "k h y)fdiXaL C X% 7 y   u N 1!% 9; w ,; b!7 #p  |w)  "g "U !(  ! , 7$ g  ~,Pud$w uC ZjS!    *<0 s4wL  H4Y:-VY A" .-~U w=:3@9\*HY-"/_Q^q{|*xf^3 uj|pBl_iu0 y ??F! H<" 08T Y 3`Kj}  Jx l FZ ;  V ) a)G5  8e -r\Hp9J=*6R$-n3ga fBSzes߿><~L܃,_bW_JLQn3iLފ)5OzO٢f|e_PjETGYQO :v! "X<})~1F 38.fXai3 Nyaf.:TmaqT:t2"C,xPP0dX^5<#x4f&!~)Rrt)Rz$w?a ~>J=NlcMMRmlK "  SeV` 2 O-~ K RA4~[i-7 K [ bAgh %~ T~HkJ e n  n Kc S = 4 R8 vt[aP8'(3]KA81f^eAraIn#dc^Xf7]37whkx Y j{\IZ\]]bT,v;[`Xsbpldf9J;M<=W4C``Xi4[Vf,KH@f+dJ=*dc7l$8 A r<w# ov + Z< S~ b R v X r  J =  A  W Dz T D 4Hr,0   /<v} ? 3Q |z!h[eMZHD.q:2xwtdoQ\h@iv`GV-vhl3v56  7)V^0*&ZDzL03Y8l*>uIvn[#xul|\=s.34e?c r-nTC\13t^:EpZ`5fcKGh/uGvP <cTw(]Sa/}YYj-$?@eV"LQ#t7Jr` 0116C;/OfK)u;x'-fiH:J3xXW"IhHtUQ'fL*$i*{}&uW,j(i>^h=Md&@WyT uRq~P_2'% 3eV -m-JkRbg/vs-!"@*w BaMSf~3ueOk[$+p[&N@ ruqAvlASRU5V=.\4_Jy\)'-^[?.U+IuK7fp^niK\<< 3 YaV7g1=3g pm 1iY&!m{h]Sb^EHvMO_s:@r$#p.p3yI_i(&/h#OB1]M>bo&+\LBMdCk<$oBg~v5\b EB_p  ;- HU-b  ab0ZJ,kzX  f g 0U {  6a&$L)c{96J^7fTsKX5OnC(h2Q4to:38%  BY'pSzCM[hn4 \u6Vm%HaJS{.qb H3M"f# PwH=6C[  { w + ( #h {  ~ "  $ Z /K  W   9 <j B86NwJitr3LNm= : $uvEZR;DER;CvMhnEQ(FP9! tI    g m Q0 TW )i  w ) E3 hIM(J  N< ^y  * d Z\ Sh e/@Y Lm:2O\y|P2((u}ar:dJ&3(7@  <K=yOQ m>[wf>8?*ime"3d1?+g  n @um E EJiY A [ ,y    N  )  !   SfcB .x   x 9 ] h   so|J MbSuQ' \t  . W [ : ^ & X {#  8  ?4`8 Rx^}0*;JzX}G%B'iO=^4]{-a+>rW5DFj ^,:tyERZtVFKZ=QO]h,GQ2Xu@l)K,17wr88W%z1AS w;S/mr])xeu(0L$!xqt HDhRT9hK1j#(My{aVP~:2BWJ3w8 *Mx:+Clvu ?^>Je@fTZZ,sJ]$h=~sHa&'9 ,cU;fV<6Okv6]R&>Cy\nyJnxp-f_u%(ohL7#[>N;DpV 6 HoR 8BwW(`SrSzdzi@}Giowy]Xvga{VD$:uyzZ:(e"SL]WF]d&6j|\Yf'^cZz?E$CP`Ai51b]rO6c /<P1e&S8.QfM@9 Fql{/)O*!kpKH$Ck}aGS rX<am\5 LN`CO^ yEho d|)zc\_$8p@oy 9\aor{.[i#s1r";6\7l3jfema_FZsg3X\rzf " C~w,XU$j-NiaO1!\J2dd8y9u}P?TX={U@"RB\ a:7&r}_^"`H8P{_mHKM6RZ]a4i8r!U7f"7`hlHJ]Z]?pXhcP\J)a =t   wXG % {  Kq I,K ~tB)f d3  0$ h Skwjk":;\)%6e+8FPr|(-Vc  RUS=x>Iz VQ izkJx:h]awCFA"SqcIvp+?]c*1^Vr)O H3=n0K\`37zkulALg9YL~PK;?1K`; f X  P0 i 1e {dw 2 /Id]_9s[| H >S2oY 8Rfn8 *  @  _ $C  EV Q V     l  :Y  :t   K u o7 c J  .  .  W } J [ n    E* 1 % U w  I Q  P P  # } } Z$ % J   E   p  h D0 z  lr4m 3!]$"X+h32@0OLKa?-OHXF+!{ .>nN hJ\)tzbt)Nպտ\A}@K֒[ڒtb Ow +udub|܂I$"G .*YM g 99]p8kG r?YKf0y7  P n\ 1 :jCI!  ! 7X' maE>A?/J1fF!4dcEKE/{w^5L%OdP&"{!&X^ B9"`&j!P2 M<H rF'/Q#  t m   h*%PfMog i-"3 " mkJ Z N#y t  +'N _ JVg [Q*5 *   eFf-Q, mD c Csi  5  |Y70~ NJG^ireݗݱImwyTt2lBfoW j# `)u!vހn <vmk9O+nWgCL"IX)W`O.OFS`? c./S(dJKZdHxc:/W68-sDCOZN1GoK3N=.aPm=VH/LnJA*2R?Fhf6'a;V2=TdNP)L'fF:Yg*9"[ Kcvv *0O3q;F=k=dq A@wTnV $bPxz6m&mpL"D)E,.O~u ]8H"u%;@[Dy pYU]=sB 1`l,C2i LLHi>m`R(j"zxEGcL~K_oa~P^L9rwR\WVOjhB^Y*w.vi0 vVW h ! :a=-pkS'{J ^C^~;8x)vj:FwrU?*BurQi*74Ia(s }^E&/4T~)[c$Q{Z7'S|0 5 5 F 50&m ko9.h{K@ *9b    Iv D  AY   -   9 yxV-__-E  .'    3<J:5@ ]} | s kc QAHc %v 4Kz e  _ 70c@ o28}Sa6R ;%9VU-uBo]H^9u\rO;1gilK:@P /%g|jX1gX0 ]x3s$rl:lO[.0}0AS QXEcwl$ *-V,Kj5au$.'~<&tYkL8f,Q"#-HJKpVe<27n;Au]0fs_@[}>& i})d Mx\pgIiN jiNcv&k$slUB0=>> @cN"8 / ^ )Q  K    9o    D [lH 2Ke; 'A wS 5  F5 W   o Y y Ek`I T ^q #c mp / . BwAn Zq bMpj }Z n  ; d gHz<#|q  ;h( ! v q   h / J x R # /X!TX)}8Z2 >W7u\O6Gbx`" S  l T I 'c4{w)n P \ h " u ' e )   { |k  S 9  N W\a^Mk,TZ<H;BR,;()K n\ 73lc@sD[OI2Ur[RrK'Puf2bu^80i"V*IesXb?HH7Yzhn5VY* NwxfVr 2 :P7Z0+9~5`b\B ;[;CUN#7M \jD$c?^F4O G" _{E-Fe AsdqB^\]L@jk*~>_W"cZ}}yW:-&8jg6d/L\:GmrfjykgGeP1G`-#R1IBCEVa&S:iv3f.K a >2d.138d]I=ILhMcM!RAijeI QJ<S?SZ&3Y G!iL"AV<x^L;8H{*7SMQGtz!a,y}%~Ql *gnkPRT#-FA)tq'rcK'H_iPnyIKz9hLW71e;!d]q=WH xUq8JAVS,'r7wg;@L11 o Q 38\,DVa<c`<*#wwAPa23'h~-"#Yx/*+3ix_=D)pX;\M+u5cW~wfcbVMa/=9KtfID'pfLObR&fhDgJn8r#5"2m.oZ_-*W+Gq1fI@3%JwJKCj#Su']K-k7" Qf{$%>D?-nxcW~a\*Y<[*8l uVe^71?1fN" =yJjmfS.u[5 @qhUA+52 D?13ILNy0U;tXW@%s+RO$@ym Pb0Ty,S?@^PRW8.H^VtJXrzy)4~m,8+k+(P9 !^[q'x aM"8i1SESWFb+Rf]FWPuy ;A;~wa*3 (opO|*?<'k7F ;s $+3alV oSD^")(NwRNN}nQJB&]9_mG;v8 [1t99+)7ALImu<OO=*w^-cy stBX0@ .Q a r h [ w y   7 L + h b } 1 T {  P  CJ {  m D  ,  ( )  #m      V  wn    ~ { ;N k  7  ( Z qt *^ ;   Pn 1 U  B )       D Ow xL J e < j   } >"3O=6^k7lY 8iv<tN`SG$=4q@<+Hk%0g VvR_O<;5 n:DY3*-IWfL[QIYmE&Wca~CZO!`W?Zq _ |'{)M2J=ZA8 Pg{: RA v+ 5w[4rv\w3)2_0^PN<saXM3x9$!,W.!H v l - E z $ 2 |V w , x  ^ % K O M   q s 2   e V 5(    [    @ . _ ;    d <    ;q  w iN _ | ` @  0  cM ZZ r ' *r K   7 9 ;  }  1 R & z { G # 7` = (  FH vx   X9 3  TCJ z B g)Z  + %j 8s _- ,% y    A c O a ;   lp  n   <   F   F  f  } a nY  g Kj !{  s  " ,B MPU u H)\KFki6~upI E/.}  ~]z6Cy6>q3/1D "k:_;U #/B%Z<8]w`o):hx7 \z:L%*_eG$NX&oPr} oQj:KT_?F~A8&+W6!kP=A0uUrcL0gsGRtDZGOul}g+I@ #B@ZN$W;a%?V#5z"eHC1?x{]HE 2fp-$}B@c<v\iBQ(BWuq  Wg%`V1(gGM 2$ !0O^OkF%hiE ezr5nSvgc!h""8B9Q!o<?k(bVnr|R Zv.q <&O|gKFN <p/$/ )o8u1Fr^6IJ>&$[ 3MnswqjH#SS]vus^%3Vr.unIg}FuE[YW?3zgjp$A T6pXg{ CEmru`&/b(CHTZJu:E[4wO]eiz4:U0b2K}@w2<)yz.(>f=t>X8u/gTPV2v_#z6 \NDQ}s3}IZaS ,VEw?OKBF@SQV&D!T}{p"yp M3V&KW\u g5]Q.&\) ?u,5_3i>4^x< E QfO((t%Yz%o:\9r0zXph[,g94H<` 0:t \wT{3u];hHt)l( =@t/yH^ =-!nmTDS)< /t huPQn Hr?. OygIK  |xg"Y)5hk,5I DM0T3Mwk3di(Gyi`z\8tohE"YE"ogYgCWOudkMI&&9NL,J~Bg&+k|{{fc%UJw>|6o%>0]CmScAhkGOv'@*4}~wVYS0-r>^>H]4u6h{V44I-y2YU ->6T4GAdG <@mvv:MkE{(G/_{Xx YN6,]5FmMq9Om=E]aTp79/e^vZV@x5FW|e^&o1<Ta5fw5{u48I -WeE n;;' ^e[Jh_T:M#7P'S0kT oR;5  J{pcxs&3/pMgG"jySfKqd"/y(@{1@>}0C [1hN)**H=%:jqQj9O xWij&#w=ACi;l\;[%k%UJb%N!Vb[^g+B1wZNaH6 #TRkcU]Eb X@;$oF)IMU$Zl8AJqb ]Hyn^{K"I@,_KS7V"(6IZ8N Y 4 %l&|fn[o=~ xNk_Q`'t ; b E y # z X  kO v'B6z{- t!(:[exV :Q:D'xLQg:Dg##jpczxr'UQi=`(fJ{i=:{1@H*QBx1)MS[GTQfuVrQau]/?-6:9"{(@^"+ky   :!  + 8 2 U <  LS   \6KG'|)2x3 _xVtNeUOL4rqCqys'/qNo F)V!|p{9vSA\hirptZ,Squ^; GNKlsqW A)G 03rqO+zo<[% iVRP~s||WZ$ x{U< Qs*W@KY]  ] B + X O Z e   cx,WQ:sBi~HsbJ: \ pere=M;] ZCq8<R;33m'~&3=p}!= f!1^ PZF^ @pDc IzA tQI4q#Yc-M.U\'Aol{FvTC<$^W[!"dicGhi _RW4 ;'#V8 Gj&cF) <9(%zlM^6@]o]]E P>K9=G`W?K=Y_!jRebf7#f'p wP\\{ajS*$+  9T@C+BPX ]&eENGG'y}zK$%k$.Ty?"O?`FKHjrjj,fcX\ /Qn 0A\vx=|%n}vyH:m0k{|MP[]T&dg:2h7QKxg 9cBrfF$41fa1~jm["DJuVn&+ je7Fig4/]c5hJo+cishTvTuv1 V79h.|Qi b ow/ '<Z mOiET_'U=\ K=WvPy8%Q_8%']pz*F[Q\Mm8p@0RI @ =[5gocWH. ZO11OXG' c+fw@mH!fiS~PFusRiN;,< [SF|F^.TSBrSbu~`E9+:)&z'xO~73 c =?^ KLk-{/DS/1-'s )p(Ro<[y:0u+s-,LB)yU{=GiI-A(DN?v>`Q6PD[pr:rp Q  W - [  ;W=XoAnIt/VKXTC=q&y;_2@c<^ l4b xCgA\Q/@ARu'-T7@ ~/!mXDx(WGySHx>wX'{E;=:L?v"lJm~U{*d_~a28e*9& 8ZKW`UM2Q}A-=_W SZ=A;,-S 4wA[N,\ (eNF rI nJ-  I N 5[>WIdnU@+j z#WodJO~3SwU$D85O>b' p?7[>xw $h~UC?gM<}'qkc'zkL/ ]D t}Q*;;chd1:oU0 Xq:w134B3Yv+N_"DBf ]X,%3JwDq{S-n{6T\x_gC<aYY USGu/>u{n/qn"I7*C/=lh/GevB2W /@|Wc4/hg`!E`M(FYW5W H>C!0XaVbDEN;p<gV30{KdvXj!=H?:Y 1rZwCg kLC D'j=Gyb;L UX>\TxNs8J='=-'*\DlGy};u~^~F|KcQ!VqGT>=];]+l~#~=u@,X>y$?w h>YO" O R3g(ppoSn,\kQQ-0I':`hI-K{]%Zf9)`CAJ hd">-liX%Hi+b*)sf=>dw)Mlo~>lq*ck S8 PK~|z-L}5 F?I22kfAMD|)sgP{w>[V 'lP(R q&G}_Waq+D|5%DF.{%,QT4*% {q?v1{rl1g}CDR< V#--/O4>ziiT-RDgcne[IDzkWp{"8r9oC<`Cgzkb^OPVYEN6)gp kkBZ)9Dk7x W8c_,z5:Y USsIbye(x@*HE'Ud" G "_:'XQ<g+}@@u3sT8,$M2}DCAY1;\h(@H) 8ng(B[^W,C#}LVx+bSB8WxooD<7} yM<*8*lo.*rO4d=RnP;f =F I07cF"N)'FL0B42kvbzXyMw2"2*C [S D,1NP .b"^uk#iXnH chX[%[rm *O^,Vg|^wC("HHr?aveSoY=Jr+r1vBLLyWAPkuY;-S%C^POi^n%uVV(riS4 ; =u~KS{L-4I\Ve$! |KpKGf8@Xpw>oXRp6Ei# s\62S)=`iu?!y2`;|iNduG9ioa(H= ] B^(H[Pc F"(n"\,G_Y=gx[ - 7DrZ`u~QOg*8WG'Z,Af*F? V`d @X H&:`Wg Q'{o[7JXoN=KI;%<^Fv0< "6gBy#V8yOnl#xaW^`RC a7o\^kP# 0#!eI r vuyP`y[Rjyk9i(1";X!fG-~KS]fpY"+h|J& s)3-pQPf!/wbR#c<gi7;W!H#!!*2## ex1iPpJ;DZrLX1+XJHZka(S}2?r?gcbsTfMb9+5( }ouP*eQxv,IP<V0vqGGb3]c,U_T37k =aY7WW?+:jj%D0 gxO ;\jS%"`J~2QP *XDPhHS (h2#[VxFqI'x? %`0{o`Yg%oODSa88r\P0'q,*) )IngqL%RuEHEIp O-Cd)&Q+_OnQ0qrb#R!7e +!7,n%nHnq'on-LWo xQ~jIZSun3uHo37*,'?c`4xAi6XRO q 0Y!S`:PIIi'rF10'*#C`zo!H9#L VV7oJP}'o("r;n Pi1 73K(Zg-+7FJ'Povn ['#H<! h-ayD99'rHr%+Ih9@h{?,  (<kJ[g$a=\< hCnDgVS.87Ii;+*ayz!}heIziuzXvPba-vzkbz^HqxrH <qroO4W;z"nC 7@Ih_.g C'[yi_  %ao,2gSWC x rBWViuikHnL$ X$`8[aS! 9h?r@q-'bS1znkxr[72ay`uP0CVzoL* h{jq#Z[ -hbHSoVx-?\fo`jVcgIu `3,q\xK-FDQKz /i]gKBv%KV`39fx+X:dU>)+"0|07R nnK#S3O01:`A%Fhc,DRuK{^h=xLfYJ3|f-fK&fE!!=J3xZkA`VjV^q4:IDv*^-\7o~:-?8$a C QV Wb4?; ISgoAu* E5['ChSpE?U30q$yA ` *lGY5`c I0u0%.]h,;F,  l  |H5/V  h   oRoHDy_FHz ۓA,'crd2KHdfhIS4 &Mf  SY:<j(Y6J39A  ~   G` l.  ,  ;e   < 7  $ZMBTqK;Kbw xF  B  y^ "*7{JbyLRuR֗jpˇ\ !̩ϲ#dٶSj:An')G -  S ]# D 4 !3R2G 6Iq/}wmj7  I' .  w s0 ,?   H\? s W t-nNu?q}. +-۹ՄV*\āã ƹ p ݩ<#"dW='RtN Xi o P G +/<:qzU-C/cmC \A%W, m ;d,q:x1UA:=vG} Z | 6 e|[<J@2-fz! ޳M\P_D9ŧo,t_XJs@7T_0 V  8 A > 0 A # R?Y6XO+.z^"%O k@~  v,  .  B 0S T 5?@U Q%KAZY0F  L> XuU{S%'Wޟg΃HpjY\W))EIp<$^7[} e ~ * b DM i , P  Z[+ `O]6\ufB5 CR.<dV>4[    '  G5 e#<$ $ # " !Yilju#  J f  " {h$cjG7KdK-ƃC:)Xǎ/̘x% kv54 1i+ g E u 0 ,.>' G,]V vL~Fgq2*UU `) c   H + ^$b&@' &g $e #S !rx]8'j   [To7oQ&p2_PAǚ>Ä¥ÛRV8Xk|$27Dp n, H & Vw   W { W64 Y P |.`' QDV{>as=684Q`S: Wjt ! OB z \ _ &# O% P% P$ck">t JoS  @1Ic9kN d   $ eVZ~p0y(]^ج υNj<+lQyG2ޅho ` M / B4 l} ( dXsF I; R $m%&En'NL* )F' I e 9 , p!6 p" "r!;v t_"# -  p 23q#" A/ xOlt鸿}!1ť3F 2( g V u # "x [ O Z @  =<VM -Qx& m}P+xk#>H = cFK   T  FYXFst'  q hu1>}ܫ@&Wli4rx z@  R m d v V =(V$l B j ( ( 5a b Qr*>WD' " !~gP6pG<E#;3Y (\ >UmF?%Q $pNb7l-3  Z DdJ.XU#B} L;H^!7=H U }  g   >Z d(Yq6==b >Z`7HOf~+7kg * <  >K  {I^ f0+c] ~ $he*iC]oLvA8vM{Ɔr  1x  y(nG  % 7 _ L Pe)#P '$7n;`hK B   ~a =M  {  IF[B[Yk4I u NAKiU[nąsлoUF5 M G y  Y1 rL h h IV  u^ ,k ;Nng!~?)5Yd c #d J| m '^ S2ZO E\q`#y-!.a{ b~ZH,+g u 9cXsfMoUqխ̄ČæcQż;1(ct x U tB | c iD $ ~2  p9 %$Fz >p <]}RoN%L3  >   b  ^RfA@okm\ F O#F#l$VnY"ϾɐN*SײIa  Qi PY a0 ~ wQ b F *O[,uX  (RNGY[!Kfp } u ? \ wQ >&E-Dy\AXbD X 0#u, .Z5}xIͻʖ Gi : EXT nr]   xc Eb X y VTd I;t @/_q?2rS!GP":  Jw/Q^Z~ u[7 ) r''O JV}JE!cedwXP~ޖ 7  gc _N _  , r D  Tr 7~ 5vJ9g:"f%<v2O TU }-J<w)  cPesy2d{dhoذ#ϵqw mB̀`؞bMh 8 (g  / O o ] ~[ q : L fe`}ir)  ?#=~Bfs" JOBok#3&P*[A {  F55XmJY:PϫI#ȋh˘ }("   i i ^ c f j"&Xt E /RnW^%I;.y ` ?  4G{IR#"Z#Y_) o {lnwT*jHY,T,S ƽ%mӧ?z}R _  I= @ J E _ Ir 3G;~@P[\@h M@eeTut${ /b,p ::ICZI_KzaU B ^kXFtJ*$MbpG ѵT d g X L S!h Rb k  . I\w .0Sut16q#.M5h ` . F  SF-s' hM-mF5  _vN9x֗I̊xuAɴ~pH]  `? b @ ii NMS@: 9 (r>*kBr-+  XR99zn :Ql) ;: Cr^|9Mp/Q<B<'u  0 D ui7M`) ǀi9OW 8 m  b &"gK2 Je`*P r 1%!e 9D Rr}% 89OtP:YJAb" a0 Gw<(>XVq.A<UU %sxXQ`TyI<Ǟ,xxEk:v^ I L   y  0U 1 z lI \Guf)X D4^ZOAh\& -vJ1  yxNsS@uW9  f E2 ]y8Pޢjԉ/ĭlȰMP!} qa~   J IJb/&gsA3jW npQB1bZi!@w?{O@$~ d  >,exw ;4)S 9u LN$\k 2 R)T  77 /b2VQ}XQ   y k J" 3{tK$ r 8  pM+^6lT\zIRHE*CN3:tt@ g e_ ap _27  @lkftj z pRk Y$ r QH |%:EH&8"V <   2;To~'#LE 9Q}c @  ?Y~}-+nEC xD\?lN*  W f)}O N v SNjO51ѻ94%K3Ћ%,O/_ p q! & & * :  G'mN`' K ^@evNbt^T~X c *UAA\V/ TkmHR  9 *1eF~Khքr[/RJʌ^̬j l SV CM  gv}m\k+  kz?<\  Mw`iLc*#Rz K  [ VC-58k ne  2K$i q!L( ۚ*Ϩ^ 6d   )s  yB A "9 6 < \bJ  T^NK||_0'#*  "   B  .@^rjlt U    3 OX\b@A+".tZX%f|g7N$z Bd  ~ n8!</ ,, _ Y@6_2A 7ixWNroIW-X V>DNݑrރޏ=l O>FB,Kh  9   O 3} *  `l  E#q9  *    a+1 OOJ< Q    h-H;B;;:=fxfbRP5u\sy=4dM~2b M_a8sBiC  1 } zGw V :   t  : F QpL<nO(M#L#s3aB7ZusZDl3);7[1HL\^tg_>EWr?h//gR   ^[ 7 o S jH _y       u^   f *y)e:VoCD3y@YOItEi]b#Jk'wqUtu,!E;/D@ 9i? (   & {D xv   p { { % /  G^{!/h;s ;p H+'p|j$F!n/ccH -+)sl{:D#1 Kfjo0J  Y  v: k   mZ LF &  l w O <  ^H0/xwN<2aDhqT BAt5:qoNH1otn;xt 7T" I\m ( f=  \-   K ?R uH ) p  /   X #5D+D]+ 5i D1y .DwJ' e*GgExq(#enKiK#PCJaKR#>I%e%~  q5 n / {0k   _   9 J S BL o2h);=Bx!zqnDnMo%FRNXM#HQ^O$RA)),l1Tw 6] j ] { #e akJ %    O& B P  XI ] -W.LU7.._5auReuX),3^OB\f p,SB>h& A 3   5 c     p' LK n_ qL_^`>fGqD%(I YFtKve6F opWK% h?`1q -0I~ Fh\{Q.t  I\qJQ{/-U6m$1F'0]e]`sEm>9 s/nmi(Eg hL?%(X)"7.ZG%<p5Vce~QK> vumHv.lP&RQx|3x"KeYTvqy&^I|n!3bgh=jY3Q1V6 A:i#@!EhMP?DYJoR"bBieNSf4FAC>F"i'tcWd+(2c,YW({7%Y4;P^Dl7S?]P)/6I4<W,D$Ewlk?8F^,*B,.!0QE4 . 1VdOc+t^9d59B '(9.+J#h.?L\itlteS-9hC[NM$$| J71>4{ S>':Cq-0*FK>\K8="PREk:x)6")]d"#F Z9Ieg1jrdN\tz6 #( V#pVSu"E7Z& :*\rS7d&2B?`J  W#Jy9F^qxX<z*%$ibVbyB$0Z[B#$14-2r$C S 0#- + 9< 0BF# uf!;+2B7P8o}bP@XCIO8aIO#B <02*@VnHQ2!PuSgO`Oi} }#q2xng$!vh$oXv2+B8+^F8O ;$-O#eB`B-h[CL-Bq~qquV\{Ph?^SHukcO~ySh~{gnZ8fyq-%L;O7S{j#f7W^${gukuf%o-arv?kBL P8 rYW%HO1SIva3*;rH03SD)j) 4I% A\VWg`n-7LF?'Hj LFB0*g I'qqhYyK* gc7j~hv,4*)`%o-~"{?co;k8yPbj @+*k? 2k<![?+HCSi*i9hOhJb9rW9`$ Z x [(aI*a+q8PqI8i$@-PH''Ha'iSS= +8riyVg< *%;%n~1F qJb` N\u;qkj2Z`"Yiii lX8yp~%c*v8 'Yrx1;74P(LIzP tNSgFhk-`Z?jBcg?,<*nrQr'hWH1}v^VC#I<P ;aqo+[B+12 +<9II3v_ uQaH JX{$o9g;%Qy'BR;6cnH{pF%u78C^#bo@V+PyW B9 u! uP=A_#OV30d |>>:CO3W=O]iT3rRJ)/]xls"zTkhrW [[tUuX`no~_67 u`(O*Dhzlla8rX+=Jvgjo!My=^{22{7'?b: ;YbuXq6: uOLQzxu<P&Jm33=?IeHh}z?q[ikIxT=(SOW?`=a Ox"n[yB9$XDfOR_xHt,A*s,%}vg*D=Py~J]p<QaYq0}bFc Sk(9l>;yo^,1o; rWe8kV0RYFjOxx'u\Y1r{Yk^`kSKr7fD^gOff,*~Z=i0{-f#8r`1aF9@[`K==D4)~WnZ'!90{VFvXov??c'7cn[\z FF<\4#?3B 'V?'n]AUFuZ47$$knOaSH;!B8W\3I;i<v9Si#n(?h- (O-O';7qv(0y^xZo( TCB7hS+yZvg$;S Oz#,%=vOB8I"a7< h@[IV 0(i Z=K,;Ko', r01yV@(*FQ*( *Wv2J#+IJ@,^kXk $;.qSnqVIV o* ;Ja4-ogW+#;WZ${#*h 'OBoWW4<F1p"fh{1@gooyG( $}~#k! X^ y;z]r`Q%G!~3NtT6 R&-(Z`%BstN|* fH[1$S ')"j@Mc(l, d*[K] 1;  OP w j  N   @T ] A O Q Ffkp"9JaBYnhH&jO x? $Sӫ ;@=o5]k&hcfjHY)^|\y'eL EIXg=wQZ^&h-Fz,7A~V & 0_ p `( td9 1 0` $     ?zO<_ni_b_Oz$Ko6ߠiՒ9_(:4o"]Vތg:]=cRxA;v!k?bKxeQYt_g+4m%GFgWyU11.C__\.:s&$IS6 ) &  o v9sTJme x dm W b r% r  P|"]fy%M)r;,GsDд!G?Ol`QNtxe9 ]   ]  C B@B`e. h$mS* j/q=qS*|ti h N F7DBAb K 02 FmrD =  @ J ! ? ,cw,= `[3dѓם#ZRT R*\G   Y   OfrdEc   e _ s"(nF\]Iq:Pf9$*[~ٺ9: *R Q}  >z}>[-!x_c  }i:[  B avY7 @k37vG 6  [  F AG !   A  G`3. e  z g'.tMF*B4kc6u8v ز TX^  { + IlOt-3G3 s J    ,x'cv' ^)t@{AN  u ,\     2 5Bh#+OzA  z  k ?':X+b~*%hIt~ڣZ< # 1" G%60]   SN @ 5  |=J=eQn 4- 7O R $  w GS V 9 l C ((  y NHS  0 q ;ua~kL  ^  x >-  {  %^p&Sp/r; o R uB bd  V`vUP   e *pGuMK4q` 2< 3hzX[aId|\Lnc> F ~  ^iNhX ]*  DE0vD<#>?U<f~lrj X a   q rTyTfIc^zSQ 5 o f( CDks[S~>!ݭSֿ)xџ-ѵ`ӊE{}us"m;@  0  DRzc ;  2 e Q    -{2#?rv|w2yBbG   \s \ @V4Os9I ! | zxya'a@zk>bnԲӉ 3n ,9 y   o   |  h Y[^9cxPi=5 9   ; } `  r U5 . v\ -m? A H <`}mhw}@ָ6Ҝ![p9D.c/d(] FK\)d Z e87\8! p c  > 5 | 1s j M=k?7?~C "  . R 9  \a U p l y5 u 4k  RM)`>3d"ELխjғLRnlMsBcV9Zd  ~ F{ 5 W=Cf - & :! ?|#ZY"  ! [   3 @p l( P[ ;  1JrrI7,Upa  8jr63!v[_/Sҿ@" Fא}nC]   a CQ > b OHt  "S y  ; eRqmD;   Vad< E  5 P [ r  n  $U <7}O[;N*Q8Y`DjkZ@׮>ߡ#0ZIk3qqjiy\  j Z FNBTX    M9<?$eA/mOIE _ 2 h S   L U     WLucy* Y  N= >0;>kSH x~ ܞ1Ol*:+.T7.4_O8f Y W e ^w l B uoV ]m lP  #  st+/H V UgBw}14zc ֌/w)]]!   ( }Xz \ lr @ ~ 'LSET#N :P{RYk>T&B' 8JSm  YR i  C J    T(   D(m N b ^:o`L([|wp; 0׊pC|ԋog"`t3hBq w  K* *C B (&1NB;heWB)<  &VNc',jw*w=ܧW^ s1-   t ) l Y K T .  kV/ 0z 5 vdsg=_|/jvj/8p$< +    Z,   Q( .  F \c * 9 .7 yy  ;r"V_w35+F /ܩJXLѴw0zb}6U|  /   `@  O KE)D  e t @  4 ] hX   bfhl2<vlx"ְٰԛN%fVx+HbjqA &Qy Ih  !^ = *qE0 7 "L[ "/Iv)q;k8h?@= . g >   \:   B * 1 ]} g@ c c1D/Mbh 8-@&*8U-ErH%p6WY )  p q ]Z  YBo'fboJgKsSrc|- /n(4x5U v  7|Mq  a.^J A N"!}.SkN7)?J     U!UzHwZ @  +% +NF^mnJS19F|MjY.e I t    !  @ OK,0  P" ~ l' ] '  5`! @&NX<~wnltRNnr"{1&ۂeQp1-{A 8 9<t^>8"HG& ,X ',   (KQ!m@0e`q  a K7  F J $ T  3   l  u #PX:S ! YA# \>o5u9 V;fpޢ'Klis]k y  "   w 0  u9 t F   V 8eQ 8DFAiP fE99F2ЊˡʱU&ځ?js z^  dj  sM^  w g     Sauyy  V(\;  |b  # = o  ^   $ > j Z  ?  3 t >L   ' <7   (^mySp\|,F_U=1l>ٟv|>SNv+ Q  2  qD  { \T3 rL  nKNV@BH'a6KN<ӑ҅I3؃SnhE <y \Ai U 2 p - O # k ^   kxys<.pxB n  y 4 8 N 4 < U  j P>{b}   ~  ~2;*=DblH:;S O*,q0E/ZMc?~RS PTiDOldO<|0X GG}c3n>CeX}]?~a}{"x7Z\`1] [   ! ( i <w\$`m_(UO  cm b R q q` -+? T P,  { / C +c Ged@x VBtj$Zs @v      + DI j /9ZyueM*/Ru`y_e>4q  2>  Q Mc\ YO8vMyj[ b[0aH6t`;{HL}`g>ij 9  8 i   L 4oq.D"m y]t+N`EPvi pHLV|a*#QS?g(v}??!k J  G "~ l C`eJ\9Z i\j{, PE 5 B     C.Y*2/8RK\c#&Z'r&V@_3D)!D ( )  wd( W      &tjxe"_76Ke d[`CW4mZSF)6bE6YzH0Qu-v"]S,!"?F?ZKw{fSz/V\P(e/4XS=-}JL)  Q     e H Z(Do+OY'@7l rJ4g-`\HCMOK%':l5oP Pjmr -   1 F  GhVq70?s}Bs'w-M#79;PcXzJo`Ecv]r z9'@4Ry#I/rtQQ, ?  e$ n[6: k  I 0  F Zf Gr-8 V/e*,f#SBk&U-#'v,y  ( N y 3N   I DD668Uy9jQ ,k -&j+vm&j|mbUO-3| W `  w ` n  t 6 b7@!r  1 3Fj{y1]~n?X_Lr;{TF~+"4Wb/X'  O FR q L  +    &; D BuxZ% gE' e=\~%8Bf/8$D^<\ @  QU6vZw >  DVkgFX2i$A1F1.;,S{QaIq< R8p0:I?V ^ HK!sN. r@ ,4s_~Q q!]G$szQf; JH  m + e % + TVDxs  3/Ik+cIXSy4,}K!<+ l4 [' e NG'j ] Z p PG/}!F )U st]2p5hY- > rd   B /  :Y bJ |6|0+dpu;pYvUjA - 0(  pm% 9'  *h?d1p[|$ml!r**(-EO ey\   / w#f 2Y9g i Rm8vl)i K7:"u;3RQ@,JCPJ;8EyUC s  ]  |  ` A0 Mh%m[*L=I j#t|~L`eP:6[S71|/ l  >@{D?[pYtT! VtmWNT33[U5G99tVxr4BF iQ}g " H0.=fR n N@ O^6sjtd pd~Tu0 D   S h |s ga\}R  D" dK0E;{* #;ER,UNSlB]mT`7eYU k  D    es   p}) j'-VTZB:nhi <, Iu  3 -C A  V @.Ae4}  f sAf.E&y<\kw|(|T o]/dO #l G  cR: Ak w B:x41 \,EuV?9UJuGm T"j R/x u+ C F 8 `f U  K  f3]Zu\bEq,3[J7N=\?NqbF^\m v C #' F -b ` *  p E!1, 1xO8ya:BmtvG ZcZjf! C;G&;a Z  &y D  r ! qyG`'#r+u+RZv03[b#+_*@SVF(RWvUw u a  {B   m 0  t ?P q?5CP%oyxsKk$]J.B#"4z&~>c~r&fUOZq M s tfZ,{I<;&Kd-F R?'D O|3p# #gFiC j FgV+%Y:t<mk'bUP'= E[MB0Zs6f\`0O|+(V9^38D=r~o+I4|t[7#g0RqE #"i*9mmI]xPBjE3,% =BF~KE{D 6 e`J!nyDT3kgs]Dn?FW8$qrZkm`gyrX6-f' ;*vfY8uxk`  (\U<_XJMW1 ?8=!S=Q;*6WW^lU\CFCQs+i   1.a}-? x( lz[b<41idl|z!L|PVoaZZS[7^?`&MC^.' Qqb>Cbb;[gB2 LCq^Wi &8Iu>QJ*vtgamNVVStg~Eq&2m&;P-cJR;8 1^0-4Y-^`DIQ (} vvr ES6F/Fy3{7c|Ede<b{1lG yk@4SdQ  K<co~f(e]:;|mZxQf-h+_`IG\cڻWس#aZ*QM-IR   ]  n 0? s h3   ,=f bZ      r ;U   ' u & m  . - Q  Y: 0 m Bi ?e u_  < r 6 6 @ E( u %  Q   [ 1 ^ n C   , 9: 5q9A?S>\x~/G:qyTNԂu!WC46)ʯA*I8u%q`%F,$G'baO L } X Xq + Jp6==#_Nb~8]|hMztME<Ekyja2H5kID F > rN t ` 2 rSc  d  _g   _ '(ru[+eu K  XZSS'rc"VO,'>P(8:kk u.NZ YPRE9l4<  I(dI{ދړz QXͩ@&Ԣٗ-6> E#ptQ=M5 \  ulK!,#N1] JipK ]v'Gr 3     N  ) |GoBE} Z$g"aZ{Qoh2e!CUDDSu~A6_IO"LG?}rIg0{VYF\&\4&@$C(Csv 2.+bRqYj]IR+V8ebkXyz6!5>NQ|~THc@sw$hoT }N>   R _ $ H 15  v,Sl 2S Ci Y . .   * |  ^ y a G     ?  O 1?}e w"aVXwYeXg yk N8ghDyGl8@^;) ۓ~aysbC ZtB2+>9S   1 IN Bqh!2:u1f]Igfb#DRLMNAGH[i? uN a m 4 ] o ht(@EqkryLI>vC" 6Ks}E376H' R\G+ !  j`% ^ ";y)yDmB9.g5g;T6{;O6  }    P "AtTqV k5   8"6?,O!9AubޤjeD#}Hxd 7   ^?`xr> b  j F !  u ` xH +3R\l S!Ֆm1ќ?ߤl  . M?m \ Kx ` sJ  7 qC mt T z1A5`!HIusmE\UyoZ   a} C o  Q }x |  Q:. 9 ~ V hpDj.eUoS&<{!bJi]'mUVgZw_N]XO2  .Z('5p+N|     QC}tRZAUIP*{ LӽA7ӌؑ|^l%!E xm i ,6 | qC g ^Y7u" 9 HL n7c?3&CcP@<{@   @ i - np}jg`4F S .[  Ic+ `". Y>DP |I?_{w9[O> _  Gn./R%0Jp  9L      h*>=T&PپTX RE?غ "bCZ.F^ @  F  V %  u+WGaL s P l Mpg*{SIr.pHMU?A X  : :   $T\vVx z% R 1  [om<xx`9A&iw"xP1?ot Mp Y b JB 9n}O [  3  <  n P '-dHN[K cB0Hҗ;zcԋk֣X^k"fV ?~ }5 ij   a C  Qt @ Z -i  Ybt2'%}CsKP i j^ C j A Y* w 0 e. wT QS2  ,  8&6v&6s-<,& ܎{}s$$5  \   lI@@8f8 G   A  = y2 E 4VcU 4NN,@(0u޷~OҡDOCqoլ5* d 4WE ^ 5A 1A z K kp !  yy+h#)(WE~L`$MB.iz"au 9  $ Y \   :   |:   9X  W f V$o7ui &9Y7 }m6hX߈w&i" `, ;AB% ,LH z sFRmK . k 8(]!w^zZr"yp!.3uT י_yW/Dߐ{}  ] 'g/Ua { 6 |e G  C)s~  1- )"N8'}klx9A>)F 5      s ?    m " cA ; T ?p \ ^Fi H`QF#4 c"NoI_e  < } .1 N    Z ( )    . Nyn  *, |luGP+qܔ[ؕ5"pLX#o Tv   j[ H YV   C_ '# d  + C,m yFD^lmZmQ'  b -H ; J C P! J ? v 7   V-9w"(JF -}Qf~u"t  ~  V b 6$\@ i n ~  Dv '  # #pa TGf,B[lY~ 1լ/\4c8JZ9 f    / R bY 7e Y  r  rq vT=J6&-.a5O,f> ' Ra 0 & c%E6   6{Ep;5`'*3"$kqL +nc$h3.Xh T G MB  CowgQ a g z? O o6 o ]MRZ`ڵ6 Bqofڼ;tEk uZt5,R 3C  ^   b X p?5 5 n j g xs3mBHT(h^D]y| ox r 7C U\ + z5 `D 4l c"%^9@]+f -@uc-,;~hu(|-g!~)92i>D,;d" g 8   K ~: O,7 # ) v 7]M_)q&\u0+WyۻٺLK:wpZ p 3 l Z   o q0X{ 2 o *:  PJ6fmDXG|`@h?2 2Z1P% N#F.l 6 H ~  { [ i W8jW~ nQd (4:7eK `XBI %R `%e"4  4 !Dnz0b]Zv    ?0tkHkH>TW;UC6}܉Qܞ r=1zzt    #0 &SY{,x  Q`q9    5~};/Gj+X[:AVbI&~2-mz5zIe=51t^W4R(XdJx<*zt#yZ\\ $ KV @Ga/5  R  u VLkv`qs]0]j4mrLQI>?MqKu;5.b Q R j35}^ Ef->  t   w  u Esu^%p#M$R|#,s 4l<h=iEKFWZy6Z6tlwPEu{i'/Q}4Z`\mcjXU|#s k @ 9  # |N)ATM}W^[I oUO0L#+L[N4Maa9W$ODp   n,)0Wu? ?   !  r`   6C^WE ^H44'^| %d'chggj1;2G*U\8t l};I)0oR >D } F Q 8 / XqY   PD7+cCH>*P߯e:ޢޅ?h4hv S  l w4 * ux N\ $  % ? :qb{?ma=&s Hf%B<@BR{kOth9R">\Nf/^^9FQbJ8``}=5;^AL&uPLx#6Q]j4Eo_`r)A  #,\~L&QOCl Z  <v9Koa$ e^zO;\8dg]nH9|++)8 ( >l_!H.: |V A1e9,B" 'V.\<}I(O%Bx4 ? {8N[~UV kySDh+1]{P|tu+le)[gsA!'R+\)cF1_c4  / S C @ < )  1K"W}wC  4I/x__hcV#/jB~4B u6U_ 7  Ps  -  8 A P  ($M6+EbE-!7mj0G>_GxHb 7C $ * ? > "  pzW  fX$-._/oy(F>msKH0z k$cAbC \,  pg   )tq7s  h'H-B \'6gq o= U X  r J  f u ]-t 4 y;){#mrDEF:7 sUM v W     G] Q{'-g+UqRh3*CbuI@I%'U43Q  C \:   + $BxU$a^2uDZ(!dEOl|Pht|yH \ E  | h | +?g xYf 8 ,y#VZ! ? S ] <  P u&3~ KVB,4?qg.l[5[ .Go.n2`~to9w~a  n$  {|B q l9p\R)woSa9;`P xs[:%yXr   Z () 5 tu @S>Ors\<}!G }7q " ! W[h  E |w@J<Jw| ;!PlX3@&XK Y  k Y  [m 3v.uec>>&J/K)zq^Rqb``7 P __h %' N| s , w  $.:Hs<69,jq!*r (k N iU xb) ( XYK a-2]iK $UX dtMSl+`[RA`  'G c +V rr k t9(vO `~qks=jMBbo"O  > ZO? WQ QP zC5V 9zV3W$ _"c3  cw B Fm gBE9cw)Vlwl?szj^ u (X ] ^4"]Z,!7Y' G% [VcLj }T0h T~ ZQr{ }M 3 p% FhF;] y /63LAVWq uqP h  !{ [V'd Aqt]&cHR kz]eU-w2{Gj  \f Q  yx K 5(U; <yolB?>Z  %  1 H] t,J~ C  ! , y f/ _%`!1yV{- % 6  VSOl J  ` _ { 1t+:J ZpK!E{EI 3i gq  i     ] / aD " H $ s^..!9 D߫`-  #u5!WYI${W[03 %e_R& pq`  /rl eZjhLhS=c/|aM@sFCVx] Q<F 4/K 1Mmn~3=nOqp+U]I{N } E q!hd  7VP ,r- !OcfkO>i1 uwvr5:- | :9Z. xTh] 99Y!pVk7Qfutm${E1Imi_( !Ar >LH J Vxwg Q]aT"!u2#YA-Q]^+7Kfa{ WAdANM J @ "r;=8"\& <M rNH u/^ G< q| aH   e#4:8b 6`57 e:TZw:$~  WOT rBD~ru'<*b~!N| [@7Vkx-vW^l@w,) m% wH+ s M h3x@)0W|yG+Zbo0KuLjw g1 9 hpj oz <@ $BcJa6a[7RaKy{_n V c @ &46W%J/j-V'BBjK$]* h1ga^Y~Xu_   { k hh aG^;/EY'V2I9:;lr^EN,O  f  C.8 Hx?&VFk0S v(Wod9W|!^V  z  \ "H EY5lM\cInY|r;ia<]Wtn_-    l L Ac t(`_"Bz77dR$ YhS o Pf4    o  im 4zz k%r2di@' )"f % zT <   B  # `GbX a  z;0S8vHKywL8:t7+>P,gP 4 5 g {z [B L PZBN Z O[   H OJ['(@=> )p  Ap    ~  BU  u ? p> (  +:z4M:T6ZO"EJE *"n:  T Z /] k 7 U  @` W & E#@q )_!C2E~$TF~CF2 7ZF h  v o  d  @  S  cm."ibYpxyrb.F; pIOVaB8 X > v p! a I  G2 ']plaAD1w= ( )}Ee>c$_4 s%YEql   %   g]sZ#mI{8& }$L.LaV-|=,MM"ikn4  < .   ^ MK2+ X f0>HBmN>$2h'&c1rtD2nN`1sl83MLE^778Y~({`i|3AI~j1F@0{v1=9JC0G7T5,s?x13|GA3IZ}_|HIpnU6]CFL<W# ,-q!>aF-k4s)tEImcZtW[P(ET$W t8 <ZD_ 6p6}rj!.,I4^^r2xH_%tqC ;Cp:ihih\IMW9kFQA"32"_-~@u:9]6`$S 'D n 4?P/38Y?Z=~X[mi"U( f \Cv{ ]#)1@6)H_CXc""P-[ vl?`EjWooZ{li#v1x k4^Vyduto@m:[w@fL_(*xj`u -&+LEP%HGlYS'd| "fPJifZ\hZHsfnM73A2))H>tZG]>Av,P{ ~ac \Sgw#lAM9{[, ^+&2?NfG^(S. ,j/};A"}'XqjI>s)tYq1a[hMvrW xzw~c '- |   $ F M  s l  Ni \ 0j  x ]  D c  [ O U  h +&0qp5!'Vvi^xK6l`K'(Q Ndiw`/IiV#Siy'UXr~uV8W|  YOQO qqJdZNi  4  b  1~ [ ~ = J p w >   M B9#rb Z 0 x 4 l j Et:< Yf8XeFF8l[{-rYm}?P5 H@{Rf,F S>Zfuk|lkM?~>QK  hv=iY++eC%@&1" G a  f 5I{ 4 T8 y!n3! z S  %h   ac}w.hYk#XQP&'h_ k R.aq~u@n$p!$(J4rI="N A=~m Bq"nq}eN ] 3 R X Ho S|J - p XF E$ vPHh   Q  D 8  $o|G-Qhr+D-dtGL_M,;3/2@  @Qr?Xu8*X ?QLp+1$7vh=W;/<hscU kTm0     n A;z#!  ,  G  J  Z aUL ~Q\vzBbNP >m}=kY$Ylz!^x;a63usA} qxIF. m,{-JI huz z;E_Rf}PP$|%Nc?o,E  J    B  s` O4 w   tf >  Rf I % R }qh 30kx<1J_,&mR!;ZbJuX[TONYCR]B`Jz s!xS Ba72/ dL*Yab7R)2^LGE-ahJ'xl   N  > f P :  dh - {  e BTEq[j@{r=w;qi~74t>WY`??5b1G,8'NZ]Bq  q:`,\FCT+i199l&J=_niacgS ?suis j5i oD uH! gCQoy7? -7HP$,e<1O+w,o-q`j)T-=%*nO#ORq k$|=K,[\+2*C @ZSX(+=S{(yCC1BrxAQ"22`Lz"p *3#8 ,wlDXVbq=Y1 ,B,c!=BBZ3;{2y_9$$`BQH)& AJR!700EiK$h1J@3W;f}$O9;kHkC; q* z(+*S8! igk$7BOBM'<p9,]y{< {=Qp$M2N$% *r+IIVB%&_hB[imr-FP@cXuZc;yKf?=qkJUfdR_[wJ=3p3#OE VY8|I gUf1-F~ vPP8-OY"j1? q;-AZ`g'L0LID%08oAxx::tf`U!`vOvQ{?O2x99!3U| XFe1x/u!e-PCT:u @? ~[U iM]i(!7tDI9G1XFt`hT pAArkL*FjE("=|#94+#F#[3*cS?-(\CfOCb%@7 ? }Wu10SKa17P8`XHPn?:FLI8QB,L4n0@%nRO*'eLHxnO$"W`a+HCWLPQ   5%!poG$$"[2DGG[slf=D CXS_\1J\~[zXybz[FC+r<8[hW3P u(2gJ9V ` jIv0$4rz9$ Q^ x$OkP<Vo 22xhk ! Vk}[PQe` *2` <'=IonZCP(3F<V0t7a:igJYu0ncc ?70:9HY7N@ -!RC| 9g>OXwdw |;x p@q) 4j-PZLSP"K^o4<HC {1Roahg-~l0p~*l-)!H"KOswnsM]O3uKC(p~-Ij> <.d$YhB/iJ;0hJ R LkrOQ@*f+$+t:ew2SlOqKQ_9hO3S 7 _) O h 4 h  i  W  7  _T ^ s~ ) o * _C R   "  W9 u H  j t.  6 Kr E !  iqk }  5w$B<a6LsO0Gp%9&%\{zA;{r" ~KiPW[JL_QWjJWh yvk)<-SRqxAxG'35(f Thr% W9ECX.&27[U<F WYE\= w@Y>kH,8VzpST>Hl,a3} |2+a pp,ai'Yc g 5Tb4ci:6np{!Br<*#eIM{7jQHr@^ t=}w kI-Cn);Sy|z2aNq U;, bR#(Js'&D\R[2qS KHaW?E2[SD{H:\;@~"%/3gOt{XaC,vc?%g]8uf`S{6>8 `iolb:)3`JXTUO !:'Y9K_4Hf | AY8Xq6+;uV} F5Q~?EN"oy~u?K]M"/u+K80ZD0uW]Row{2GZ8+POya5_yQS=pF+tTi)XW m/JsG{7tHB*x,:9j@p Ijq8 2g{l3/X[M}c+U n L9ODZS9TOi:@pAT@<, x_3zK=/. f $ 7K _ > l >c:7_z6A`%Un `J{#5~#=N]H"Q_'ure\,hxg!oUO&)6:urI'IUKHROw];eF0iqk5Lh<4E!?(N1vr=Y Bm7p9kHEsa m1Ay &1OZf;f,G*JG;,YF52 >+x ] S " % 4   nF= e  I Y R   H # -   V0 > Aj * " + D,$iD "  <B2C  -u  " -f e W  \   {" 4 1 %  ]   P ' _ t   [ <  d # ] b /N W : W  n    M RX1  S 9  9a / ( f P=38"d\rpwzlp _sQ8Kn?]1 N?P{4'Hx.@YoXVoi)k,j/Mv~Q.='~>eU"DZ q _IPk\h.\i98] < 'c(F*smKkaJ}HiqR|(!l9b5rYxM!RHH0D!j W$ ZD Hi $b *g40_ !   " "N& { [  Q 6ha W s w f 3L u X l w 8 z V}`vs   { u (1 ) d 9 T y oBj .r]5 (c k  } => & - ?  h+X  i 0 b\ nMA 'h^ Sf 6k *r<EfSx# -]_yD+3Z]N)')y!o 5Cjl~t" &qG$eAt>h2~P)\64C9j!.Rmo-'%eC&^neqR  ?F>ybD]+9_`4ZE' !~|5aIo~gw-E\|f/v~^9\Bk]Lg-]-[,ZZWf2/z6K3{*"lol=}rHyMg_W p0PP{eir0"K.G/FgraE FJNk7yn[v+IUX\:'n?[U.k`3;wDPP&yJvEA"iH xW0oMjbI3;XpJ3'>QFvA]c a y, S z /T    / + A+ 1 \+ b dUhL3N*]2C6@B}_^! 0ocd@g jl2I$u*nFTh^%(1yz]2LKk)7TJ<8%9K^5W,xR1%{Lj >HZ9Y?fbYW3Y<3  ~Cu8bUvD5_\  Y J*v5LX*pEE%*%R ] GLCK 3?Z4rk$ dZ 9 }l  h g  :w / C bgcGRx~Pe/@~f^$j9$=N';nS <C1$>qL~x]L^7b'Hn`M9Zb.# iyR(no&k52h33Nr I5=uWRCk}n r?bgc:.+UKQ85M2eUwzC)=G+@a[/EFk+5G?Lk8\EZ1,,;NKByucmD7(?6M5me@WPE-'HZ|O:oNFKvlKk[*$4Tc'StYS{Nx53q9 FiI0.+77o?tYT1>xK1GD,uL8I.;:2?d0C:x4WV #hlN;9QW)$bKEL.p< M #n["Vgiq P Wy F%mJLWyNq:a8+-t|}l,3 c]I,=rjU VmF="278KWXlElk]uc1'+G"!b@4#2TZmT2bOS` #1jvC8hJS6jS's)QJyU~`+ imNr,M^h[$J 0=vZHs>D'8zS>@XY@1 TZ  T  aC^Yc9 K+SRT2ZM5 od  0 Y  ;G:"9 [  ~ 6   ncd`3JWWwu*xR* n D OeYIO: r b  [B @ t]`}fiQ-4 E@>SO,! i W ! _ OO D q h+  6 Z(} f J  K Cf  : ` ~ .DA   ]   [ WG  #Q a + ! w C ( r I I9 ! ~ G =?$tqHQ^h R31\m~=vT5JhyW-__`^cWR-i[ {o/;nk`8x/{2(?k4  SV   - WB y HZr y $\ g  ] $ }  ; p 6 S  X 3 iw<  J ERruRo%B2J'{beL@M7 cg[WLwx j3$ 3iB/vNv_jD)b/&"A6D{;0g! -w5#hd'H )i>QFWnXJ  a  A e:   W  1Z `  Yl =\ o 1 #N T  Y +  \ |  U | 1  6  ' # <h w Mz ' O=o ^ C }  G u h H { Cp Ry(i18)C9JR!PH{,/zZodBbQ ` Yo^>!&vE .+[1D,-&vc|tsv"{6IEt\u_vqk|-Z {j]t0rF;mqD )Ju%a*`=tM`-2$g+xJuri cgZq!~AD]C:h4W e~pYW0 p.1S6DCh%kKCa.)0eYXrAx SN{\O5([E0izs{Y6`&sG0VSX3] & + L C i )  (  N 7GNc]^huo$Xr9dU%>\dMO|OO>2qK7HobR[VVJ@/i5)^vI)Q;KJnrL ~]ju*qEo>>f)(qY0!)wQxIx);5)0r<#D!kk j st 0 dh u= T r 3 J  G   #{K ,* <E {  7 S   4<Ukcbdh` w'%.-wc|Up03wp   [ j !^ c~&^TgTj[C N & b  |j 8 ! #. i $ M! "S om dc "R "A !     U  sedp;`gL~cy n/ SzZG  , f'bm1  7-I}$JO<!)uQ j143GHf.K[/(/bI~\w~|2xla3 ~o|Gpais-6^>EڻP-|}ϖ]{S6Xi%AL4{$KޖX/E`~ߤߤ~{S.ߏޝND!r{-e$hxxT@Z/1 dE%; !    < <'B[ $1*$# q#/ Pq;c#UeB%][ (#_j"K!""a#`B/hhk)\ )  -@w@  <  < J  D v : MB l_er;'E*h|R 4MJS JMO1 %aT= FFf j-  !9kWu  ` s P d L  ` )  j$) S=  +. Nu 7.whCSD1<R-F{g i?]& ah߾14|<{XXQ\EELg*] ܲEހ|")@w V٠px&mXt|;]7vQ5VuOD?o(\1" r*y'7 *<5i@3*4(Kݢ.B5fWXb+P|eX('J`VnT=mq"?)tMF'`Q uP%/l%Vvn=_XBlsyf0sYz6 Jz-EnZKKOmhV ,  Oh\d * L( K [LDhi46 D V ]Bag z SyRrL  c p  k F[ G , " A$b^FQB$ N:18/XGJ%\K=l*bosUo6HLIyAPz&,zSqc~q p*1XJ8gxs yl2VC D6BP %?{@([$^mS2oMYa?[ju[DSFrbq2KE-!%)t$`7cX\(1 \\}zy*  y   n  V 1 w= ? a Le 1 l  * Z }Wv 1 G h u - C yK{4vUgW_!(@ i6od-O+$mo=aKv`''Yjay#ip:{|@PkGTe%i iMLK3CniO6f_o6zP 6-"Va[1K}Ejx}nn++&!UD9a&Sy O786 oCS[4i9]]!!i)WXY=ar!xTf^|,f6\<;@aILx+wT"alW:-@2MPVO?abu|n7 _ mOW&#ufFLtMZPF O4\UJ`u;:W :l9)2cXDP9?cqx r;$4i(@B tU'@qcx`8'[{LqqW vW  {  `q  ?f$E-\oP.C4%`^> A|Hbn0hYig'I6`.H=3k:3SlH4k=q G$CQ'Ts,5=l>ErYh4E!Wc{kj%]|hdrh}iZYh $, > FyEASR  r w ' " >a {   ("  6 s F[  r ; M o;bx /~v}xJ"9qh!7fh~1{pY'#`'ok-@NY FOX,Me=#4.`Mwg8arqB! @W 1 B Q \]| 3\ B Z u o - UJ 7j4(:. r  6 ] U  ^( Yd'y$`-6m2->I]qf(2DC f o5@EEw+)&xtbf<[>)X;zd'SoQ/:1O+<n  l Ok  jPbZw: 7 N Um   + } /J  T,  U( 5*  (M+}8,` R  4  V ,  3   ; %=^ yWVcE3 }0  $  9 mJ & T f  m/t  Ii9W 3\FyyIIXirEuS!jb#LySz%hT0RBg.(a=G-*?x4}OQ,fzIQnJ {%Fu#JI#hKUz=s4Y5MU\nzC2p  w1NEuR7xH\QS m 9e{1%0H):rVCI}yyCW],['J6gyGD*ZhS$<+9^ xoy-*{< F>1@IW p/N R~!L|5j"JVR&&PEP> xdyD&U-UsO6?a@G6gifR%cR9c rN `jFW~5 0S[vy:k0'QV(Pqg#?&rtl_~XI k:Y5;UXYmQ &F7G6UJ6Jbl GV<^nOqMf{Lzb il.A2Zjo_'zRhsj<WrvGYrq ;<vcP+ wb\#9)i3`[-%kjqY>'bcj?a(O#xBv'^?qcC8Vij;l twN$w9a@db5@ F %,ouW{ {HZV@ E  " $eQ9K}(lSNBZZ ;KV ]i}7g GD eYZ,UBS c=*$*d4\k z%0j'K3Pq3cAu+H_bJTs@.k2N 7fs[?m0}XUC9Em9f5  }X_*z .  * 4 z 1q@3R J  `  -2 Az 8ps}UjG+*W\*iZIDE`7,OCiG(?dx; >K,R 8q#<I5Qxx g@g~?(jRJ|I?Ce(rR.Vc7H\ u#hz}S*#?2$'`y?>M~"{>A PA< 3 n\|>T RN u -  D ` F e } a gj \ _K  U xj'S/'Lp\9\~p*!D:h#V%S}uIGr R_FW gkjBv4ow2n;pNw`}Jmxd{W; w "jpFJ\$uqIHgP_bs}= w1KnByJ6.\BZ++Px!Vi7h p ^v <Xtv2g   L. W  b 3# 48 n ;Q)agy3N x s} )Qp*bj{(A#Z 8 & K p $<R  im \ t       Wm  f|   d  C  z N 4  UP | 5 a s    I 3  G s  J U  Y P - 2 ]& : . X  ! K  { & n HA   h: 0b*%XP"(w('!+@j0&W{.cca:c)9>vE]j&I%\m|՛cՙ-E Q9֗[ڦmz4|I<ܖczܲf& ZC+pS;W' Sig 5vrpJye1B4O5 w  i$O _= jF>Sa\   Gyi Pw#_ 7&o6+ !35j4B\r]*`>Ukr"6!& 3 q<"1&w!q jtP;I [ t2#  t+ G;,  /( MlvZ TC @ &u z  Q %P _ L a0 =} 0@g J>o  W RFZ0T $*  :x 1 a$N ? e%XQ~-I  ,  W{lzRwXrBr61lPxi݄4Qqb2U!5V3"omi,KQ{kRK6!hZ0vnj .@jP4f: a$0hZp7BI;B$'*# *a{[TP4 B."Ya{_+ <\6_G:J7_4 dY&..J*vz( CQSeF{ qB(J/@0( }qK<Q9sC|"[",| %e$3 x MmH8 z  K% )cW*O ?= !  ! v 2q  3 g ^  dT Y a n x ~ ~    A 28 [    & @ kCS }  q X |sM;R2D^e!~@@ ix$Mji;xqCt{<vVrBH"n<cvh0;K":@Z[03i5~L%a n@ 5n"7'i,hvE9/s7g`N%h, `+0K6j {pXQV9vLBw~@RAtYXAZ1`JAZ ob^+2Q;s9CVM{N_M-{I!Qf}RJ]#4j g) ma7 kPHov TlE#fk]Pl7vZ1`=)O^rZjS'dgCt6%4iiOf#()=I|l  oS7r  s5hfE~JlDcPl0nuXr$ > < = <&-aQm& !Zj7D ~,D    +cpFmS " y #4 c }    h zPE[% @Io> #   !bjrr~ 7[ U K LD <~DQ G ^j@ <  {%  en-2c= &S@.{_?SiJb;g8[vTdyI%4^1srQwkH&VU 3|~u:FZXyM|`p-[7~t2V]u9"m}yKy{g[A LWZh;,r:%_( (S37-,{JG#Yuo'e5?EZy< `V,k5E$"4E K0xZMo <-;Ux+a,$ =(&zVIb>j`=e|2! QioyR#k)/S44E?o0x@$ g:L=a XqG"~6xFjImoW^Q,>5L 8S1hl E }>+S6u | 1P  HJ hU  $c[ {r  *sp2.p!X7`y=l &    w 7 Wz JS 4   ?Z \ u   2 T    2 Qg  y- r hI %  { I / ><   _  j = q   s  - \ ey +=Q;M Eu/\C"1$uahn7yw~P\2)}Dp2!2Pf ^i~-JF!?Nzz3 igw d@OB?] \5+|  c    o: 3 j :  hf`  #  b w s  [  ]w R} G  u  I1q  Q- 5#   A O 4ER T [ s Cg Z 9w ^ 2 5  h  i V < > o @ pQ C  | k MI  D o : c x ,  [  /E 3_prU1'9hXA^:gQ"0e]J2m6XR  ]g)X-KFGxA ,  8 (       o[tkQnDgzpcL;O, a$ =Q .{  O,"& %iC Wifo0o0'{+P6;WnVU#Dti=`'1W%]Gx<XyyXeLQV=`llzFHFK4 Uc'(WfH\!3S5=n Sm? ['sW${T0CNF#A`otA>q7qF=lQ_IC~@y~>,M_W J4}\y;<y %$OB (A`}zR&c{h/B);.S^^4s\IT*k:s_+VLJ Jf*F!F<JC xGl>Z?4+Ej<I;Nm(Zcw\RFoL pX_\vRZ;`)(qIoJ`]$9x8oRAysc{;eIB55c[jqwAi9M] .{\,Zm1%jR7^KVUmOU9Am(([ KrD;"/|DeMrJXWR([o4a9|"- d|8:jPXKj7V B/ K =R{_v28 7&jgZLo{S/ D? <CJ7Z:zRq:!Ci%!=KJb/]xRu";  E/Ni9Cu%:'PD 1nGS6zUv9^09Z k Y[+\p ?S X^'r8%8OdKi'1:'I9s2[\yv 6j{AT/T${.Wlk)?~r68Q8^J"_yi&Cn-W 'mq ZaZtD3=lvK#X[U#gyTy&qj=_RFkL0+ ?p xq U(5cC79#"H pAt7bX-0/]T) u-/#J6)@6U=::W ::`V7Z4p85!( &.ARW #@ 58 wu ` / ( Of - R9  # +Q lz : < 1 b F h 2 < I r  % T~ p T 0 | +  ! !  )      |    M    n  M H Xg i K  } ? )E ;Y   ' F 7 > + . S { H- t9    ; T R  [/   LlgvSK@y Gk;@Z+sWgv?t2cf,II8Z1jpk8\?h$g8;#at7LiXf`Lc!pR6 x)w:`=K1z^[`: ~EJx T-o&R `] L|+*K&+ByF+eW[~2brC~S!S]oz]fJnt7Z*S AUxpE 7  F YK{k C A  ND  /g % & v /  m W Z   ~ S @ &    W    N 9 h E    g G    L   ~ 2   V q ?  Dh   i Y $z '  +x $ #  v  # B  h \ &  < r   (6 \e   Q= =  ]TS  P v-#c  , *m Bu j/ 6-  $  ' N p ^ u P 3* 4     J,;d = ) @i . p       J   f J4   RT hz < +&AKKWAVqP[K3-zvXy&CpGR!)[ho`i @iM>H{2i?HwjTMdmS+]U@S_yr&=(; x-0,y%d['F;L,@ZL1i~q/h;gFS`ps]ng,1 D5~iD50#N0O~-3Y9L$FR@zir=?A,GM&"x H=*pd= p{QLgB:R"gRCWh /4 McsSN:9e"vU/<^e|fV<>{=??QKAOX?i QGve +O W>V-^ f%bPLI>PZ;'C{! @ a w1  y VF   7  h { e r  ;=*'_dd0(!HxGXqiI-:`(Wl c4EcmPha:  ; HM$ K .S8 f }a V,O',s    + L o9A=]5vaAg NQTG>yjW C_Z77V{GT@ U w?5>cAZE!,j0"(t  Q   TE)CnVY  uR T0zvA , e hj,N{WvHP& F I A 0,  C VxuU|./ Fg\ n  i#Uc N mhn I HY Ic\Y8TH /.\*(2gz'G/ckw eW=q>4JY%*r Oh4iMsS0*L&yMrMR=Q]ZQo&O]UsIhESX% SS[$`4Kc3W*(x.%K'Z=q XwIc/BC80l@Q f^YcDQd   ~k[Y\ 1 A u ;:  "M   'j  V sk @ L   B.>mw  F l W O A 1 B jb E ~v  %z G  p 8 f t  > B( CWUQQqfPsv-}/Z.wQZCN<4o2K} )(#83[z(PrZ/wb | 2~h{Wx0H7^EfroN0<isn5 +l Hm+rz'.fY xKkQsW D?mt&7 bmS)F$<7Jxu2}@;dhgS>[%CKz5{ )vYq^{#<lL}#fj_KSK VUM@n RQ&+pG&bwk)zu>$es:rW!Af,2_W\?JWO*j b9n-Jrv 4[zk5N$:`BM SitbIND! e-(2r]x^D {Q04bc+C-MliSBxr 1 $c`QKzF=Zn(~7(=:)G]zOr4%T^v% `OTQg|B_Q96. RlnQ^\V 5}RhMxug Nu px%q+Brhumd%z$Q!CUuUn:EV-}u/[ f Qb`t!) v u-a~}Q=O9eN+X p[|]<wFwfN'[nMC),hore!F8a3 7hZ1#zSf<$15}#1%MTU$NK 9"^/n&k +++f-SS;p'%j*e~991e7_ Z>F)  } & rS @ +iz x H ,c t m    J  "? {f  6 RS;rRq {1.J`{Z2GL(J]jkM}paF zG s P |Tf|  ; >'  <+ + [ N f  IV \ [  1 & t & { + 4:)g)bm*'Py$]Y Ru(zmL75Hjf+bPpoH7k5?+pXXnIQ! drJr&E,cD7T0Zs=i0w0N,8"E =B5n#un[viHf7>6pKuM7d:6  e1fb82 3+u  7<  >&"b  e W  Uc  EXC+Z P  5 k @   s-" 3 ?   ) - L s   Z+  ^y*; f v: mn o p _ ] s s %W B J Y* x 2  g3 G  w G   M  >w o LY PD ! WMQ z:  a     l K\\ M 2 1p ( s7   a y4'uM@qP 4WMP ^}f91/\/ Epwku("q589(W9s?mi<m%J1VG<@N5?,_jT!Fw:$iE)4y[w6i.vD@/2N&  \ %WK%t<v=J w%L-[OTIp#7+E0i/;N^;} mC J' 6@ YR1u= e^e d q J  ,q [ 3o q # ')7 > z 9 \ ? > J  6 R " $ 7) JV@ V wW   za , Z ar O n  #j h_i :] , U 0 E<  "P | N @ )1PRh VV 8 ` * 9K 5 5 _,jFp Y`:!7]et@$B`>>w "s/Y &[jC`VWhK3 B?lxl\D O|%.`!ok"2kM >bE7EZCLZTNkU'-bIT2Ub(`b48Q.Jc'^1P{ 1REW:dkCR+ XNiM.D&EqkNk$Y&x5n6|t,aJa=Bd93&hgU: aoX=z=&*n !%~}*ZrtbA1<:Z h\fD[Q]0<q=g6*z}9)52|Ds[1eZ >y\/#iAu`8!_is %Hwj_]HgT~ vlG M Q  M^ %. 4 + + a :  # Q_1 Ks0 StE66k i#]`K{,h `B38#I JUx-} SB6nI_rY *!q[LhD+>"vJ><9H*QN}Y,[ 3Y,%M_5ES |&L+SqUNPJ / fe}m1_wd(:@ol I+e|,=h+z(P$bo}<,;w)37JA,L j?rr+ #rh B k  h h  .t 0 M qto"bo (_w=P^^(AW0K/\EV}k<S@++R<\0vNmHrjIoOpy04`vCOQS M^1uN!+f(.(r> >v9:QoB,3ydHM?hyii2[^f :v'IQP0BwFD\r/ xo3"&GJ$c* `9%+\D=esR&l+8O/}j^]0z;BRMKhh["!shgP[m@I}c,JWBYH#?ecr_,;% 7b^=SXzZCA2LLx+{B@." q;=9R&y7 52c$1 0g6vmD7,6%P%%5xS[/h8}UM\xNTiWvLdDgC0z &[XnCDbr9*q",<SZf=VhRjWo$%#Gxe?"{"?@WG*VDIT}j{vew} <@kEi}C]Ls)tAg*oaosh5j8bv 1I~is13 *+1Lh1~ OS   s" M: k 0JZ k ] Y  f . {  t5 ~ T %{ X  ] < Qu. > 5 *krb}%< o1;*wsSEVS +of#k%M7 AuR$?u:2*.fC<%++HJ[IEv-6=43 un/`+,}NAP6nfq[ h  7 e w  d  p57 A  fI G; | = k Y  `  H /  Q T  O i 7  G < ' Nj  X{  6 ^T#2 q [  " H  { [ Y } #p;J<`NXY,+:d^9Mn}uZxi#mMl[E)0wA '/^;K/2vYVR|Vi!{8K3rIfMTq PznsqUK]dF1}jn?-o Z#`u$aRnDu OM2XAO1WOT MgLY?O1iUq2[n{N_2?'G$~qU&&\vswR-\j ;#IGM39O5IOZKXL>Sg;@{-+Q?<3mfn#+2vp.aaW1lp4i,A3:y]twR/Y,Q1 |!fZ9* T? &yEd9=a @_dn |jV7WoJYYG|3L@S ;UtBxUc YgGE\$-wLr\~1D-i%;aDC%6oTPh~?&*3OS9r   %E  L   dr 7~ F   ~     9 n     Y 9v8 _C  j J Z f - uE{0 @3L6,%8|\ N> hf M H a  ^ ~  5 1 M C> 8 ex \ w K  u 9M z F b 1 6 R ty CT w N-  ID ZH e / Q    i y Ac  m \z AW{n.[~>Cf?Q37;,92)^K h7FsKt'fd]EmC4*rZD& JzDy3Z'b (9#NY##drjRaO36VFWz /TltxJ gFv>OEBZfQZ<|@M+JK 7@ &!  3   % ' G J e uc  } %[ # a  ) i; " -KD T I #bvF' KHPJ. o#%`s4#ha  ek6Cc 1 e4Ae%kFuLP*n]nGMJ @ b| <4 J  (   a" _ )> 6y "& "    f5m  c #QX{Q67zm7t~ M Oa`  UH3\ yw ;6Y" ~ R4 .Pc9v^Y ]vy<IPE:*q2\RGbXT(6w8;I]o T *M<ZPlAX5#!',n׽pڋt ^.oz"V8UlB0߁*Rޙ=.Zߐ~ߋ~a]D߈ޔE\:yCi&|uwbVj@F iU1I$  s 3 +'1W  $8*+# t&/ Ki4`PW0 >4v'#?*$x@y"P!y"A" +juIX2PW!G ~S2 q /` r| 9  ]S Me  T 8M6r &O {T{!`Ef=-q E&hbV ]iXB 9i9? L8 . h n V)\LAe  wx h  XM mKm\X ]0 c W{Q V` E IR f CIqiZg;N;q@Y(+NZWz#c("}x4s#uܧTށ&}.yxXa%L|=WܽsLބ} @T0ٕGi7TA]OF'CR"nes-#l1kU{|xO]QNcCݣ|_7yݳ݇>,UMT\)Lzj i1=SiclV2u5&83~C<1gEw {F!/#l&[,$/]'KhCl@&9{^ '=w))~&p A 2 }|dg O /,#  Gc)S>X@:hymQr* m }wp #qQx# e? {  < } ^s 'f O G !hP%~5[%,=/82NmCY^jR!aBe-b4cZof8(%,a2V/,n7.? $oasUgL`L<">zr kl$!Eo`$ZCXkF 8j~cVWe-Cx9cCr\;wvSK;h ;{MTu15\ Z Q %G* [ Z  <    1  v l D  T v e r j  #Pq ?9  Xz k c~,  )hSX+87baiI:_pjMEhiC 0<VurbBc63- nb`o<uv;,Xb8(> }&QWO=wA AFa  W)xgd`|SP@z9J<sgJ&0w}UI!m[maw2>-6@r {uM} dtD=>4.+: 'zM?Xv#OxD AFN2^T!J_0i#&Y18 n?GG9J <Z/o@Z >w;;mqq[y  W.SA*4h FILES]R UKy k@j2hDWT`C?gi iDs}iiCG{-/|t6h  O 8#SQ#b^[ Bk"Sh`};fI1aMF] o  E  f } [:V1lkcYsM# :Pg`f}PE Xi{}24)U {XwL#v_c*=@CrNx:Xgf|j +>)s>PO]W$xqzihdh+C +Y:,Q  v k # * c s  u   $ _ 3J S   1@eD5;hfq)f"\\oL2704_M9#'o: C 6    mH wo N D J\\ %j4)F w& a   ~ h@ >D M6BU41Kj0|(Xlx&R;F9rEyS=H27=uYP$?QiDE3Kuo%62;YWX%,}hh b  9l Du -   c  Y $  } 0 H ! = :  ^j$LH  N/ +  V   k   :O rZQ~b13 j;  '  M tZ & O \#  rr  'wh\!\ {m#01Wcl Ka .Yp|-E\ /Z*  @cM p0&+sBW+:SgBlJ[x_.wFgJp3)v*[hENo=arm$^j\}~J2o"  LAv'uKjLCO(2d;#0[ez,z7:-7QyTyJ~!<&4$N" MeN~6-2C [n(4K y[45VOe#2&q7i@}I'Lcg@2w A hA_?ZZ7K?^- 04j0N![# 5NsrwC( A|` -~V Usil"80  p"7KK|OVS0"+} `*kxS*i= ?{:*Q/DCs)` u:tfToOMgD--*+}*VHJDr 8w+~ p(H>):UiJW<\}_[v'^ybx':LqZP8]Z'<YnW[z $'PFzb^;oj*@/q=q!j(8; iM$ij"k@gG.I}gPlMyxw8Id~y' tO~hg ev./_-}&^Y3!82"n;9W`hrf HBh@4S /; <!Gx2@U,Lhd~/|\jFJuzo'u1NG%]RT,I6Gc6-*])Uvz8e+C0Mn#]/`A NRC_}<'o)G4cmO9e'tPN8"= f8 `- z} wUb4 @  * 6  =F^E=r o A"  a] w p ~)c\\/{'w1m`cv{oIav8B'?\8ZyE~#^I`ZGr0[N6&~mkqZQ#F'Y;q Qjv"9)3nLB`QEFxTOc$)&KS'+ V!CC 2 q`  EZ UP u *  A ^ C e u ] \c _ RI r u oU wkzZ~!(k4/rAYdKuN[_` $-H} J$g\ 1I{:8[2y+T>XE9xv`1Z\^,[:fH^-O~kV{Z@~5wtEUW.}| MQrN__ol&ji Ed5e:" qH-B3cic~0V 1t O Bv JAYn; p d  [9 y J{ y> Y ::'Nkhk2K}j e m{Gf" ` q!/"K7"r I ? T / .JY  pu i |       Up  _   ]  O   u! N+ H  R b  J d r    I4 3 * L   Q \  Y K + - y S '  J   A  l  ` =2 x  nA 7#e*%\ "[+-) '(4I0q>-3c6 u t((lWvL ^;Rcn~J]6{rսY`Ljdּ 7r <ږ" OgSܵ2w |1aP9 `S*E!DXT %|eg d<rY$4 B$ p  UB P" ]-9IaP   Af Ww*(\05#i +!07g/BZu^$ `;Whv"8!&: p:"6&!z o%zW@L et33  s* P{G"  =,(Pg X@ > )~ ~!  O! &M W F Z, 7v *:Y JBr ^  TDZ- Q!)  ;t 2 \ N = bZU6M  /  flOzUh> o (+]}Apd݃.Ony`2Y 1V3%hlb>yI qhMF8iV+wzVW'Kz;qQ&{Q WxPc!4;;?"$WhS  zJP  + \ { G s4 K-  l  o X [ j  U C : m !  I g1 6 C F 1 R   * m. QT #<SD5 e"K.p*4{E-M2E!=/(  !{RHeEU2g ,, "X'- o G\<*  o  H "hZ!S ?< (  y 2y  < o c " _X Q a h q w}  s |   9 +9 X     ; d@M y z~j M vrD9E+9 PWv9:xgvEci6qv{k6 mr{-bzCd:<`)Ra{L'7k*H=r&Mq_h3xIL&W )XTb1&b(\R>f,Z (/G2g siRJ{Q7pM=xy=ODqYX>Y/`FBZ }k[Z&%D6m4@KDmCVG&rw |GKXxLCuV-c`&h]-`H>kl Fd >"fhXIk0|\3e90Vb !{d#xZ)1fvK&?1@ rr[p*92@]"y `F/)~<vs$HM sQhZq6irYk" E C B B%3cTv+$\n#:L9Q    9lOx\ %  17 g     1u fRg8*^"X2] B-    /;yN<; - ag _ r kL SA>q %g 1;o pT  g 9- X/X.,}S` -|Dy58JX%|7pQ;X1cx[v}4?s8^mxvvQ3,q2 D% ct\I`}yP0']x:r(ok9e O[*0p+AYQR>Zsl! (&T,Rc5Qo%*{D!mN]?.[G?>=a7K ^L&Q>P[E-G]IcnKj%Va9UR3S8]Y?OZ F?D5+z&,&3y q@KF)_o l%y8Q !IuyV[G%TZNaxO@H8E>;:Si^vF(*MmKnNu8 ]r jLnfTZQ>:J Jd.tGH@o>  v  zHX y 0 9}D   k`=ge"YZcpDv5K + "   v d  1 4 6 e   Z e (b wv ~ z3 sR7; 6Gf= 0N  . [   q+D c p J o <, + Z h ~   mA ; E ez$r.!pX .lx{ bP>[J+`a+ Za_(T;/7{+\/sWSC>6 ^BZuS]q$ ~":  >_j z o 0 < _ ?D > g ,a  j    F  $  G [sc NXpW *W u&W @  CH i   x v  s  <$t s 2 }p  w / iW   ?{W O | + a ~ a8`@"-  E SB 0 r w    M T  k @8 N^)/ yq+9nA ^o/Yk\I3P3nxE s   e L 5 tB>  ^ l o /  7 f      Z E . Z hfqv]h:Y\v?Hx9E_<$'K s g :=yrSCbJP7fw\`av[=#R uj<jz~n-&gL(G[lQeFP^Uv aq+LY #J{kW~2;KfPv0HE $DA m^XALcFNaZ-HK^uAyZhDz9 PCZ{B$A\Bceg3WIYrN8[zXk.J=LzKlnyZ-)OdzF+S qj5K7NhjOPeQg`>hE(FT3+Q7F1NHdn#G/Sg+xal+<ZO90Fc1{1$1S]>:Hhl"F%FF<gn}i~{h-^UC>v#V SL :Gjzb~cQnBaugQc QK+n>iJ4!Cp/, m-8Q=DuOELH*AHI (N 9Nf2A>w0#'XjfnIxGAw#  |   4z  r  9 r 6Oo 3  S  Ce uz   2y  g 7  \   `  L-  i ^ *   } F U<    a   x   # I  T q) ? bj \   Au l r  1^ ~   (  Y 1 k+  ' n PT O w n@ ` d IW  -  6 L n ^ m H ) & w~  v  + 5   . g b q Z{   ?    ,$ ) =  (     e c CRaguuJ&V  oJ5F F|Na 95p94tAuA/ip@&a'3k\nmPJQ rd2QRpf]YpOy8PG.j}8FWeHpaQqQwvp.jwX6 n LY{y("24 n{N oe*k{B{Nai.w-6-MQ?K~!Y2:>V0HT?fSJggAH0t{H wa7SR6JF k4) &`zua\t[8sH8-H=&X,=i,G^cLsF-5^lJ(1TawbW6? x55;QJ@KN<iSEg w; wc;  DZ  \J W my 6\ 0f L (` f 1  I 9 .P 0 z  x /a b G/ R}E P Z  x   4! Z[%J4TQI`ABO 5 I x0 P'{loM~!N 90U4`"~L&(M(b^r:^~u^3nP 97L\3==9hCGJ+_Isla}B9Y,oO4eHE@Mmy@4o$Sxy' ^}9 XZY@Pr^P M,J.^"QQuZ2ya"DF{oZ!fz@GZ8Ak/:CPDo=aahy/d (Zn,- g +AMhnN{DjiJc5`)#^+AP[K5[nljU^+[%f %M[_ Urm29/@-0QL_9",RR|tPAodfiD14de S>-Gg|S8Ef{=Km{p-^*V=7 H>O80{@J43p@f! y,Fpz}'X@k[I;Qi5mRX>#'#[ct5TVV *Y@uARJ;: hhV#}{y>EjgvL6(KQy$5,9Rh F&65{pMv@2umF32qP!uT>]li^bS!D3S ySjaLJqOf/[a v8LX FtED!mftBq&raIqf:|!O5ca@Y 8^e9l@biI3S;"cfI51{vXq3@WHQuOx9,!`ylGE7MpKNATf)weyEj; 5 I }:g(/\ )B63YuVI%}. gNplPoH*72dc +i%9t Z*R{lZ<s[ Qplw x hIr*@<C+1Zpiwv:8+,H$KD{Y CnZ3=9EUYUy:B)-IC:X=}mgp_51)?se|+MW {w)\jL4]qBk|1L&~*v&-h_ F6M5,,=oI'~%r/4{nhE/4m _V<makU <@AswT3|r6GLT%^S Bu?Y"WlQ r>hTJqfGqMJ2kv*.ZslmTu6?F ;*Ce7Y|{;wa8FSV  egu8<$T)"A;t)d7& `{PY Yx<{!npcJ<n`|}}-:Yu hf*Z].&@zi$Y n[FcrC U%030?J kL"&N og\/D;Khsz "Kv+TOw{9 _%[1yv[Kz5wkl~(-2xS3IE[@pz`i>'IQ [[LJLXCJQ0Lqbk1qF' *7aa`e^byI01;I#\BL ~`fu~pC_zb'S3# \SYar.ibOLqva`-kOzP$ KB!}9X$+17B4r<7;0yRv[#rJ4 nvyII!4gyb<7i`eenXnPFg?g@C(FCQ$b4^*V#+n7Lk@#v2((nyfW"#Z+[X[LZu+J+VHP'Hxk?^Je27PWZ[L-^*imC:"=X+GCuNXC-Of0V ]X!JH>:Ao7:Yk!9b!kF%5v,xb2S7hkCQ;(1$(LYZjS ZquWn;RxSkCS^^FkBL!rS9S aYv4\0Z{ C7 '9`-(8 X040 +*J[Q#xqVh8V'`WHyrnh[Vb;Jb[1<?C-n7b o}-4y88#QzP^g(?WL2*0? +# ^I3uI-) : ,7VRD30-{*kg[OF`OZ<hOb,K2 @=95Z9yprIy_M.+ ;?n$V eyFb$gg; xRIL# wVr|,);8;,," m[Hb ~ q#1LZKP1y=oo#kV2-1n'7g 2h+gX^2xW(}gSOq^ gh,!p+c%+v.<+I,; 2P1T3Zu$ x*- qXin P@O C`X0n?X$27(unq<g9[BZ@xr;qZ`0J ^7C o bSqn Z8S* !20$`Su}xhurXIQ<n17 81e81`BuWq 0ujH\=fa~yZ;WLDL\gf0C gJ2B'Vo F?u4y`H!@H4(<Q# B1#@2`P0$;4eL  uXbqO @0n ?*C};roC1'v $9f#WHSggSAW\f4\7Z n#2-($O;@ L@Io 'q`guBhVyF^1# YVqv`7kK;r7fA*B-1:AH0104K%f'7: #;B0?fYI3fOvhF:1?w;~ "OFK'WZgFIOFY-W1;D`-OkS?= nvDhF+rVbn '`b-*1 1$0$7#W$\$+h *u7!S+ 2V<SOavqo;V;YjuoxL:-yP#'Fog-%D4OD2FBY"uD1ovuHcouaJI81FKIaJ +KF\ZPH9 \{9b@UA=EoYs `i:&3]Upa,qI5Z;4G  aB,Cf<][,p-"^bz^T]TL@/zh_-p4k-3npfV5tJ$ 7RB Kn3  @ C o= | w   n_ b )  8 L  x 6* W W x 5 Q    J ~     " { t  ?  F<}@ej9Ss0 % {vu3<o] G Qp6ZVMR!u)Ytf2Gp:3RD-,@xLh1'B&dA}~D(?  >  u X J  @ I ) 4 d [ y   tW g + f F  !% + x p A o ^ h f  O W Y d  N " j (  ' > M3G=Q$G69 T3 sN^V9eFm~ekO0[l&{KdUdkrX) "!moVIj.O|uG6.][#-C[hW"(PmR r r*  4Wz  b  O2 {  > 7    ~ YZ_vO8LeFsBk   h3 x T  B 0P    Iw_YQrKM?^c%wz?VV){]nZ])Xf2sCM> <&cv<}V-T!@UnWIotkie;Oy-N   u  < l 3 x A qd 6 .[  T   6 ! d ] Jd~/9q^DLl5   u ]  *   J X x % 5 , WK@<v 3|I_ ::_KZ r89q yk4{b @ F q ^  2 MYAU OS{h+)w $]' ;*0 a3$PzcmA L~b0=.}7C$US6vh?\na.0OhfLo :8-v^pZq`2r $)6$ A;8}a. KiMj`\)([xpg&_-[+ !qW>3 N+M1x$ccuyjc;8%ZeB9ClaPnAr`:W2}9P7;*-yFy,PtZc[)fl{~,\".FM{d:f4j,i/I;eZ\]yYzL-4$3 [wPkC8,<S` *$!@FLS!WLx{M<z s6@d0-> *{5p~Qh>+o(s%}ztIE~ *kpC_W4S?f}&-R{W +a^5n3+!=J;p$ U5_.}-P" k %p|S ^   Q %   &  2 2 X g F  e   m $   c; MZ R1 F) P 1 i b& H^ h6V5IK1wXIzw%'voD_?a*7ni}Mm%@%^@}|3dy~T &= il T8mP~ 59  n &  >  J =  |   FC  Mfo '%=w(>_68FMkJ W  _ K f h  F 9t R `  e 'ww<WQJ&6x[#hz`3Obd8AYC0lmud= %IV*0 tKO qZE;v @Et{/kh@q a&r9 Q c  ~S x   A   3  0 s 9 s A >s U U S 3K G qs,F6K( 1LYA <  < : ' sX   D < $  '  # l] J  Q["!kPTk#\=$P]P+f;?~wgwq $v2NS3_ T    epE@ 7\fk7c F *i FAN  x &t~] jUUsXXfyRceJ4Bg7^0}y+0?1Q?V :~ X e  4) M=^ PR t J9VQ q5 h* "1 8! u1~ O } ! =Z  8 / n :  J s m 0 L g 0 @  & " X ? Q B x F t  S ?Xj3r{<wbPj&o AQbNVt{WHB]c xF:(L+`tm9D\m:vGj~;uJL5LtGc1Or{l;FPK^ Q#qeAvQ?D' 9g5 t<n[$naHKX=pdmhiWcF.1Yu7tSb66(o|n@f~-'FcP{ Ir`^)PR*bhe$ D~z=MA=<Y %&'?{{#V!OB5TUNum_w m2 W' >#*{k %NnRyS~uIs-U# mhxTs'{aOml3\qYHuE36dwmy3a {0^Cf*LP[DcL{I?K;o!gh%:+#8xxggjfI_3E(!@Xb_Ybj|y|6J:&Y6y(cKNhXGT?{)( [ l5 t aDT6eD)^#Dy9(E+! +xNm= 1Kk?*%t0VnPO'qY~vv Q3=;[8 '*  )LZF#rn*4K4) 7hDtZT*+7'gn)a%LO0tg:t0x=F # ~%-( 7";3#P$O}7WqIa0 `Sc4Q2(hoSB-(x~u7:\aqS)`hI4jnjn~xakkLrPq'4$noP#V^!q1(OOxSB[q_QpX$DbkwGJSDMi!lQ}Ig}yXgz1nSqh$LjPgokHyra~vaOCD_jpx]F< @ tu6xQ 1aPWr1`OqvX[VhqSC#+SXIgnkorheSkWohvvhW @?WaQo}!nq u-S+`oPj0^8PnZvuyxWiI}=L*y@ ,B;#B!xfvg\VC+P?eSi+uFr8I^rP "CT8-x5.uOP$ aXJv0Dv{4rZog`aZPBc-ID"'doq@#962 1(c>wQiXO7\A,#'7:9INYXjj:A87vD{`0R"BIR`8o4 ; BCy;vu$1\XZ3 %I  %$9\DA3I$ (%9~Jhll%,eX\XifkJB;8*2$!**8=B+(5%, ^VO5gBI,ProvJI#VXhVgSF?aW1P;P'`+SB-#o^`YyRI=jkqPg 0L@hjVcBo}[hia*#VO #*@J1b1 0#<x0CkBnFnHZ(<;98$Q X7O o\nYF84V3L~)gK{,=x HyfSIuaP#9'"`u3F%7qe89V}h-#e'!Vr+e[qz^z2F!'Wn? A L B D! ,ncVc-:-%"-?%L^B:=IqWf`xm{]On\A;tjot3,)#wYR,?=:WP-  c3HKo^`Z"=WW'a,PV=^BSK?RVK0y,^Zx{ uP,ZH g Rz*w'0 D ;3-"7004Dy ?W1 4q r I;xnv@(vCQv?**<;k '@@gkq`QV[VkBW'0-99HuDR jnahRW"`4 F^oy:c'j $'B Jx4FWvCe$XrWby*o%"1*8.J;GGl$ 5,5_++_ k9b{vMyI %D$WZ[8ccD52B W*81Mi$\ KIZ@Ibn IZ9@+S}+7h4`J+ nv*PLPOzBo[C#kH #; [?JQV'WxgP(Ou 9-ZqC?VPXaIok`kbiBb28[I5S=a3B[;3Xw$GzHn[CO J9; BVvSn8*[;Woxa,njK8o S  g D3Ip"G =L8][-A^iX:XUJ14#- ^,u;QY `Y 8V4~*:"\))WhFL :-B1#PNP,_LE\Q)zFA;oV%u*;8*Wu1 VIKkj  a@r? b?uheObM$G,:bERxjc ,,\!1yZW +'ztSPrV"p\tCf|OCLu0C9{ C )csk3BQ -~1x!b5&Bf [` g{-2s+A[oH~2`X m > \ 0 x N 0 dJ u  BEo 3|u)jD 2 R 7       vR{wA"i\"B>/#o"Dr&R'O@2M8ZTٶAmid b֧ٺ;ޖN|*T Y G.sj/4 [ #Y2,<k h%Sy  c  2 [WMyW)%z :lw5'Zf !9 _ /Y*<{-  gD Uh y  e 0#  ` n "v f  ! es4Re  hZ;:%c=&7rRp0$2"d+NQ4Q% \wޤܛ?՝, `"/ڵHOD D-]QA7v %xZ~\=xnQ{  /K s*  3h Fq'Ecn  ; m8&ml /Apf9kmB1) f h!>  ;= F4 8 h '  | 3  KomPz 41x`)e~_ I m:~evO)x@qۿ}KfwysSg?I$ 7<VII Q#,% CZ h !   T  m *  f  6 .6 w  - z  # z;;U 2 7  3  K    6 d,tG]W$$r@ '1ja%_33Jqi8AVMaB*,YF|\^Y2Zf9ϝJtJؐLޕ?[GU N7sJ } QI:( !I-KWh  P D' {8  ~DGe( A#_@(=  [#v  ? f  i `[  > . Hu   [ R wzUpqc8J -*qpa}F'G/'o''ON o7-y)1,CA5l;Y _ lq}% k`q6%r# F/ o T  4P n T i  {   c    )I ^{ bpT9|  9 w Vh 4t  5 C3 "    Y `h N " 2 Z Fq$6!./$X!Y/YtSq\tTta[Pd0Yk:nejr7e'<@XN>Gl\}<=* *fg @aC ypD#( OB > B > F c k a ? D " } ! / 1 A a n B )P  X  m E > f R  t) V  } \  S8QXqly[,]vym`@.[U}Wl( AL(L[ " *F%vK!G`"UQ;?hN5{{=7-=iAzX*Qr,h]6tJ9[ JAL<Zu}bk{S;1a,U,&aC}  ``p=T"S'+GJv.^Yhac G[bn0U>eGih QT/'5!s9F1a1.A^8I?I1%sley^Pgd'EOVvd+i[S_ijkHV .Vg@ *g[)]v'I!%[h]Qb?po=-f1Rkq `)Z {4\av8)Py ?InBFPrDK17f;qhcL`R<[zX[yXn8=|wyx`3t"7 8 HH o*1*f SZy)RhF:KYuh %4FD4aADRKH:qKq '^{x~H^)~WV#+I Zb?(2X*?Z;Xan$u4(oi 7C;PB LQa4 x4y?(VBiv4Z?BCeJH0vk22z o(a2h}W?Q+42r[BIv@gc %@3"** G,bMoir8P_[i2sXJc\fw9Y"=Q$ \,c!R kCJ X%X;kob+7 +JL?e9~A-uynKO^PF '11LY0S7Y1;u%SS#PH;L4v;`{okrS!9(yBa ^B P!*OB0yi*P^^PeVO"  29P\iS.SiZC_yhWzS<T alzK$i^[v\zKsc ^vSWSOqvqcDR "P1"1*7 j3VBja40'uxwOo44v)`~o YD0cPoV;$RSVhiPB??:H~^ +'*Z4iyH2uCyr@+1#  Wr u4 B{noo\a`xgfn;?#8 %) 0 '?7u Y=OVY@ 9Q]n8{u{X,NF\&K63KDuR>BG'm?44PkI~ ?(W !1Y =gS V@Z#}1[; Ikx X hkv`-['0^-Wo~ZuW{2S`H1C%F)4^D<< (!JDIF7Do8H"AVY^F\FhR3x{ VVbu~kKX^0RPy=h?yPxgIg(HJQeOqH1? R;hC<+#F^40-Y/1Ba4Bu%n='AX)p!Ugm"Z{y8XOQ0`3soRI`v'Arjqq1%rJ\5)W&>z-kvzPG[vkb_rqhSb' I7q{OVInE$Wwt@D(?'/Bh+wKwEDqrUwTT'>nU-7<]zMN !q ` 2e Poxs?N0 Z s   W t   i|[}kQZG50t0z k5 Y   T w5 9_OX$ wNXzSfr+tA >?-3v)[2K^zD{Krp*:L͂ikΥACٽ34e4j MC@M <8 \M;+H]'b?-;c G o e{e8+ j ! !g waWYc;VY%RKd:C;h$AOB`,  ! n   I  - b Sjs%X 5'wEo:Z=jz<*RB\ i-4v&Yo{el)TO߂Ifۓ+=`bBK5 n T9 .x4 L OqJ 64k# N P s= `Jjeu &]% 8B7}N (     Dz u   " B AM\KLVV3".{^#zA p]jEs%7OjYQ=L!4l M5 d1 (l. 0 J z 7 C $d ) L   E  R3 7 C g  _w:$iJj){)p|7QgzR]    8s B B )  t | | w  Z+>!rTO7zMGS^'&YCQp4j<'CmW6` @FpdzFMLoAHݷ"ڮכIѵ%mRZj t< umRyuU  AK=8R  *}Y`."  `H*DEQ iKp/t\Pw i %  wa td 2 *w 9 K 3   <tja93vt'|_MNXj1`MU<e4-8uVZsz"P.\Z;_mp{Ym-*7m,~wY4 B  ,~) O8P J % ^  V o  o  U  t Oc 4  ? 6(y x\ | I ^ _a1   Es 0  , ? Am Q} D P .A1kDX5qSHDnR[-bB'L:g&XTX$PSU %+xig)G/rk2c07'$n- 7\"< c|dM. @"uOnAzK$4JI]-D7Y''af@ a     i  F t B  W  -   _ . ~ K n  h l    /   Jw U P  uLy@=;)Di!~4VEf}-M;-1/@ le;J_fUbf- 1Oh\t~|5x~-poTg.4"E^i hC i67_Em,VV(M4M+V:)5F>Eu&dn<4WuN0OFP"Wm[_rHtE{ceX&3,W8( F',91 'Ig7b_e+ @veW;BD!/!UuM2I 6gQ? H0\y;khufgHNYA 0Q:Q-q+@0pM|SXMS <cnI #;-,3Dl</q m3h>ZTCXe2H%$,S+p@s!;;o?+`zy x+  yy2!Pk;u|cN^# 7 B'HC'X2}IHH`yb@$J8fK 5<!9P[sQIXab!J,(KBg%~ -Xi +hX\Wk1`k}O?\kyjrfLqI  Q7zRC2- 4N>=V6U3nu] x* Ih?xfqrrh!={ CHu'<F<9Lk9Lki8X;^(F@eZIQJC`1 oAa0nBj~ A'A\kWA8 PAR8\,z=3xD0)6z RpO=C-xmq )0' *1 BWB~c[qWu~Z{X;`jiF 2$h!SOCui@ICZx^xvhLIqOWCQ<^S}(yQI[Q`7vC@-xYq\VO'P'8y jjvc?S^1^=h,KF`B?8f; H@xPn F[uI,Z  3JI*Q19zZm98I$ag'e\_<\#M42V  zIYHS#H,vaoV7*g;F 0c*; |Ygu j[+fz4;A#D,`Pr3'u 7P`--nk5!r@(5<3,32lDwfK+DJ/")CEM$C5B2 )=+hkwHSZVBz4r}Qfh`Vv AASZhYLhP^:W31O:;?Z{qn{kqj; "I11FWh?IVkyeBHa' 2<Ih B83(!rXk=3QiaSyyXboZqXV7S+OSH[2 uc'*P{nAD34L7-3xRu/d` Vxt\AD9h=K-#0 =A(^S`Sh/{]qU` @v09:jnbog P7oqvekoaQgJShII;-ZfYZ+#21WL W( ;`"Z:IScS  *8P:Wh0)=,= )3^IWB-JVqb:>Qx9q?"IuY#XyA~r4yKj`3I ;HZZhBoq)oVd%5HBj nk'6@Y:0D{M9c oB,OHy&SQLC{`  1:\pwK<yd8E|l|Nw RpKC$ra.Q:cUfR?lIyEej  OP }_57WT*spL[R5GoO/j  F E > |  T ; + jd5'i v  0  K,  y DOfs8ajz^!=ztEAb2 JI)&M1u>Պx=ѵjҧ*ַ'4_`z\ L 7 C;w_v)l`   z a % m r t H > <   Y 5A)%:^q#(pfG/W#F/-V.?V !\ S I =  { + / VT #covq PrfEO$ M{2r&N m%L}/zۿlـӨ KД@-HEwcD 3]gPhDl?k nKt=)3D  R \cKTc  hm8 F`{d  5 q  8[ Ug   >'   z i M= +   SH H ~ "= "[P;B59(9~7ixT[:h|xin>)Qwv*  w` tK   1 O ! ; { l G < E  n . F L L * 8 4 7 E } <| S <\R$m*\/LhgP179ka  C;J@%I6 X u      g ` H5 !* 4MiTb-<._!  22 m D    B  4-  M  KtwW9T$qyIzvk ApB*p;;_fv`:+uN&&- woDE~^c )`;2 !nuwL{k&=?lNjvgG( |:vB^S!<3C i    M P    U C$   +! :>fd!R5v"9n O$UD+BoikB?0`uYu-PXsu(QhkZ:!S:k65[7F"[`iy1z [lT<  C-UJx74qvnI9>YN"e>SYwPMTD|0l8u b9r59p*|sLv!ddFzGcNeEz|FWT1 kD Un!Pb2eiyUn)}0u3fPO*4P$oe82,(ebl}gE9_k\A5QX%0&fJL Y^ 'QrIw7Q{, u`B49V!Jiq <e-G>V"wefx x1E;tqQy"xl,+\>Rj;Pc qO[~n3Jll S SBB VqR&emK(O3+qbDZ&K.KS r?;QBuChH-B:|-%<y?d|=,GlwWCx'l% - /dzW1^TmXA0/H6R@Ej];)fqH(" 5KD5 YYkrac9t$mg&T5R {V6Y vi>cgfULKRFo0f-  I^UFKG0F*|w^)_ h"uIee@UM1crLAab y_(r9</=]$ C\YRTX[i #e(^CZ\B~*{`!0uCP:BX;DSg J}hITcHc$OQDPrg*bX[!X IV`kr#?Y$Cu,f `Vh{zgKAg;BROz-)&n}&f_<:2&yQh~hs}PwTGXW<e()@w&H~[UE~fR@C+gUK|)UV-:H!A3(Xiq^67mC` !az oNat nahRF9zc1%oWO\-Cw"37CmJqKj-bVp#7"y-W07t)[8 6B !p>81&Ao>6CiQ& v/7e!) n>"[wd[2Q1@x: |'m_|nq;YeD*x&;!m !*v8^bo@Hcv!%gLfxfq"J;q%G?c(`$u-I{@9L[ !@h+oByZWW94 [-Bq@V#-@< ?XQkBr)Ai` 8$uyx@9Q8ghVQgG8WJWI% (Gy\KCvI z[NQ}bQ~[S(k!Q1'"vZX%X8.Br ^'X<X@v7eue! PSV UGKV V<- a!-9eBw51HgE\IBuIL$ ' CQhybClH>5YeR$9=$bCQ6T\jX%h<[s8~-_M[9.==P}!A- n#F{Z8oPuStx'9C73w1A F6om\)H8,J"R%3:9"/(#`4@K7FK1hIF)jqj(?kIvIPGv[@=< PSw5B.XI[lX;_Zw"G+XLZsbsiLk<; k7<#!FfWafPcY4xg6umfGV=KJ[`-2X/o7@mod Hp17_AO~WRQ)z_OYj`YBh '74J!7y22j-:>%Ji\U[A9ekB\=2 ZP'7z,Jq1  )H% {='4Jg^  :^7jAvcFKRufZ-0A%hP2JP#Igi12q^o9f9Ch&K/krb,w5>i= $HEE&/lTcDU -:z@P)=B  r'8J+yrqui'jBh):^ZvP:#?^^":0"? a~r7?\=% ? #=ZoL''*VV3P-RhScaW ^#CX184S?CZ n1Hk}WQ<H4H$v+a$Xh#27FC;+B?W|v1](#/7q uJ+wdXH90}P| |zwfmp~nK0FfYKI' 1h;),)Fryyf^CB+[ZQ^qo$b+;P7 ;$ B!QqaP0K7@j1?2\ :) fV^Pj=y`-~*YAH"W m7Vq]mbmgmjqgCXpf/ #6:]:`w+ 8C\iq8Vuo!gone1 9D_+%o;M$ (2[=, yfu}}J0He}<I! <Pnxe4@"W. ?xo1+ao09rg4 W1 zWq*J2#@+^ #^ PHukzaW[ x[BT  bQq` iOZ^4#*IknkF<^L gjxaOvHxv=\Fk*Yf B{o`qpD #0"' 0KuF\=cHon^*V^qfS7Yo`$^7Vzx+'f+(inn'Wx klMfahl0V="'4/K=%3%[i,)B;Twa~yWi.< hiLO$#:\f=@m>bK*Nh !C@|P/Y5szLSK6LiZ6f$X Z- i4xKtD^a^i`A Y]66th]=GgaN5܇!@V{oEzg v, 08>MJ7A [@v ; Ur @W xWc}MPw(@V;|Cmt1q}V t%Q{f [ 1N ,   F ) i  &{>="ZN (@!@|+w$o %si6Zkxrl8q'152rTy]{q{w- F W%F+A G Z mG\l@En 4+ W ? qQ   {$+a4Nxq F  ]  T l T J ! ]  ` %  v 0 ZI  Z5\oQ4u;IS#F[Ey_cU![W^44S?I=XU%,6#Ij#x PF0.BhW*8T&8NW(/y k K>9Ye\iB   IdO    ey{5x%(  S O   i Z S  ~Xc_ r9{s|jr)P_@:s7-y(4 '0I JE9MH%X2WiaWS&>.sM=:Bpq7*`{s|5LF$ XCQ!+5lw y8$VU4+Qti5" J)T"4+ .{.=BpQB+1=PP2u38cUmJo'k";".$T "9$BQ O34/(\ni;<7qv'?R,{0 kOwdV;M+_XPw99W9b*qKaqq;[wfW,Jq!CixC()qcYL^r-gcmx>;SAu31Zx 1b29R YT:IBl%%@TO82JC@`g Fc"8ANB,_77&"AN! CiQGJVKxbbN@nBca0ak[SQAoID Fr^ggPhr  zbD;H%;5r4 2j9CJ0[q-6E)NV/savtNw"9'IB3iT5JKiJx&5 jQ &81"nx4cy 1!1-8P]Ud}_p[!(NqqGj'xRWhO<(;w2P[u K#"=pAYe Ocd0/2Z/+$NNhq>UC&ZCsJl'of>Px<<n"'V)a.{$y;/hfkN3p=+}-JM3QCU{Ng$C+A)9Uc&+QQ  :{\wpZGwzZhwJ2I9~rI$1X&y9vpv _J5"2%, (=@X8"$$Q!<O <u=u0 K[ -BJhv @ &Xz H ;@3C`Fmyb-D?nx{R*J(F#+=6V [-uSu]&=v_dXFQEi!3$VnWxAHI-<3#<zYH^8vn9Y52j8[hm*:S?^!~fs&rem HRzcwL^8ANHN? o{DE~9@>ah }@h+KahHrg0k^B@,xK X(ob` ^F,qJ=O(\Bi9UgPo^=\fBNx"YRK.4 --Ddf(k* D<@%za=:{uQu Hxp|0t.Ed==Y}y9auj $S"aFX5hLKceO%hei[>3LI7*H@lv@`qi2pAD9=,So8O\k9q-iyrfZ(2uWBOnlJjV-KeY+0E^Xam&^n$@b8T6o~k6[M|s(B{3yx;!y(FbD "Gh  h;L; [{u9K$wE7p,p-LJZZhD$ %0K_Qtf#" "xYI%oj,1K"AYu M,\[4 C<:L,)3A "}&cEmOx2;[?okKP=TQ5E;u88L##$iO{aHxB8'dJXJOjc6jc/y IZ4rq\s%qOwU # xq#W90KZ7a;Q"mENHB`JVa \clO|O=i[_G*#2c\T1tfv-Z 8!g8($Zgtj4n0eS~=nz9h8c%.V$^FLOqtK| @:[?5nd~V\%]|AtXpv:nh xYaDAf/ ' V{8^vD=%U{XTk<cy2<c*,you)[40a" jhKVy*q( +22hWK+[jsiB` IEg0qK>wm[zq-URgHkp6QK$B"sss%b="hnqy,4J9 vZ{[HocR I<}kB 9'qrh~{U>:&~F6N& g#V`Cm jrqk\hKK8C4auX)yv_%BV#F3Inpl)ym`/Rn$D=?gP?H'k M""IGM %`#'OHgcy1`17cCx2 ~8~h=Wh;8,Chq I?<vS{g`L{0*W=Z:I6%]R):-2iAUDh0`!(DKj$Io^!KW:)]uO  [iN]NT<pN3 "DY{=[C/c XTAZ2oiiI) + -j*_1Mf+pySY9(TZ2* 7IY ?*8g-  W^#[8h6K_XC'YQ7n<][=?5F ,%mHHo)h]f|f#hOgS% YW9'q )#WY;oyb *J?rgJr *^r-S' RH7OAP DRu,0x[')JVVAb'""p' G*5fM9nw,<|PbGt6uep.2P3+o3uByrvR#BL7PL$n+lp@\Q%S}(=,o u2hQ1%_W8~9oJ(S)R0r{^uA"01xR =4grcZUqV%WPoj 8%aOvnZcVx`{jyIo20QLx8*bqrS08Bz7J4iS}`k`T?w@o*bBCbl\h" .Lv7*; :3o), ~Gr_@;9PF#-zt~8,2#yACBG xs,rI fa4 5kr5 y)/)S}kVp x`swp2_ TK3 %by[;rC('lk P'XOz [{q ZK), 0Jyc$[=ee68 'WA HI} ]B }Q}0t4Mcjd[ d K 9 +   1A =  ) A * )    C b x t H 3 W  7 w Z  _ j ^X~3Im?1hC+9jzXcnUY#,nz0WN]>_4b7 Cnzܓ@K#\oP*S;ܶ s(\S1 hc O yD r] $ C[O6M5-Q uR2n X-I O Y \ ?  v d  h   |  kT      F .L  s K 8  [ x ;w+" / c P Nf  ,3  h$Dc{@L4O<Lk>@!j ><N< Q(9 o!Liߞ3{Hُ!Np:k(rc "n .f5!r = +OM#D:Y1X   Tc  >;}A% ? c  ;sGTO1&vQod D 2 H i  7  6 Y & w .@ ,n Z QTP     4 Qh>{Xvg4+18e%KaxVKN!H@6*8 pSXo,{DBmDBoeYO# o d ! F ?8 L f ( 8 aOZ)#DF9TD Tj l   6( #    +IN`$5{,W      v 4 I  4<" # b   ` 1>obgo ;uuM+"5p %`eh7&lۓحcӚ)da,WPCm( 9@ W3{U. U' /bl/Zv! ',<k  l F  V 6  C 5 o n.  Y ?K " ~  * t Q =  t%r! m  A V  F G  -> Q EhGOm 86@!$ ^sNJW+z>uA  l  S (Ugi$} &:x|UH ? 7 D[  !pM}"tp`e$ ZR G WH X O Z    aah z s L  z ^{ D4  /FJ{Wb= _5.'oF4:bn05 YWKtO h9Os(m/h[ZHp{[j<^#9up$ fnw5wIg[OYR-xumxn5?+^k==hao *Z # M5     D = G  ?   7 '  B  c  } N7   v drK~jw8 U=2|>2;WI)3cLyv/!ZlIov2="?lWe @n9-(wHrlvy8k%2C}<X/@tzQ~],C a!,b)=`$MCQ6i%yT8km e#>v>7yezv 9 r{gn4ga!4O4PL-HH!fxH8VAvQIil1 a a ${auWO-wvCp<JHKr$Ubu!Zk=$KI<ofz o$,LwoY5KXirc>9;C *X"!=]K{8pq{uiM$2W+PJz@(JL[ ;Zk:,9{_%jI918C0P1% BxV[(8mq `O(6/w8`!PHn#/7gHKWuUH;?AXI-1 "BYqH*mP^A'@H6c8)nNZ B-I\uL Yp gAH1CX7 YaOGpby(I/6O#c_u@~ E2sM 1EVV@/e.Fu[T^Q(s^)2nQ]]e-b(4ABc3~+| n 1`u7rSh}F:r1XVHn?S9JOO8#k0~u>v2x|vx=OnxR:-Dw_3|9m8/U KnxXcLogA 7R"30)^':ka3i#Xhz C! Z='$Q Sqvg04Y ZDR'F$?O;$r QiVB-oyh{Y`IuI)8Y'KOYz~`S@8# &^Nbx xq~g#^ '( ae3zvhxbhLL0nV4-[(#+W5++[{"vuX`WvWJ}y4gIR=\ZD x  <?9\;uW@XP SBPSSiQy+2[_B[bBg` xxZ8!5,!D%1 bo@P 8 "@*BoOo!'SQQ[@2<$S'7xaxZ4iikB(-hSX2oi naq'#h HSAo7Lu 'r'Jz'yxa,JfMk@k~+TA{:& % & <"fUi_=K<`,Jai naSoPh+9ZOFO[[n2 ?`2LS9vk9;xFWPj'D0#*Z\~g\A3q~y;fao{`-koSPn8,h7B0!}C1?9O$Hh7}9x}ZSa*9J FLFqrWuVSg;[ VHrg-HugB \ D)a:) JWW 1-;* gu9U-C(!3Nxp 0Gx x -|'VgUHn ''iHAHYtFuQY{#a0#Yr ;4 Y:*h {v~4go-xo~ujWkjqrL ^Dnf;81 1xN=]93Rq:b]imYjq`=g_mQ+E -3:XUu3~0?^cW{"`W;Aq$< ?8bh1'$CQ<i'z2xXaonoziZBO'7iqV Lv qy bg#- vSz 7C2{b7xVPoVD:jCx#O^)V f*oc8^%aPV R8 {Z ?"Zn' ko'IOI?'iyPu8Z1$?H W4}<2^o0<Iu3S!$1<f@ i8~ _QT @_Ba9G^oBP+MlPP*I"So`D9hoXZC9 LLe@gee@SV[qrI-nSP9? 7O2}bP ?r!#?k {jbV1I ^Z+e?`e[vF+vu!FW[b`[-#aSn88nHWu?7J*ko0P y7i8y0;C^vO'8+1(IzQ 0Z9zkg-! + [PJn$ {WP1cknaFA4oL#L7nLB^Vc9SkvbQF gQa 72P+{Oz'$$q=\9+*u~vyBkL:1"4W-D)D v,1*c 18*8^VOaIaH;nf3GHRw`1zm 88q:ZvqjXX,p;)81g 8w)3L=Kg=\:HB77[1FK\#c{HRY 1 KOcg-y`voxa cv{KW{hBP ugykh<S(`^1gD`%oDaPV$YL4:FLL<`IfSy(IO# OS#8*c0{IjnX(KAh$Pb$a($}X ziu;ikP9z9<#rD5n1k '}+5niM -*h4P}oggOi9z+S[Ti @3BkqWPyPkwDKTT{@"b78!.* *2Ifk "1nBZ8:)X4[M_:Cyc`k:YW"B 8zQ$^!QonJv#V{73*Y9JP(I  ]<-FU)DXS{2DiYD+ @reg}uoo"-XuZh-Ky: WB7O:.*Z\AO1A j%-4I(ZsAtdxS5(E}UQ'u:/FKt_& mOc#,*F8 7[    (   & f w 3 j ? V _ k   o % X b x *   R $1d;:9i?J",Iiw(?N-J6 _ bi;ݥ{َ2[͙9Ϋ%:J$U! Pi] ) eZ'O06_ S T 1  O ^ m  i g   [/ T\ . m   [wb  ; } w Y g TYs[]`iXT y g C r 6 1  R" 03 [2 ]8|,/MDr.zo/|<4_aV=h=TC:*>>o^dܞXyivӀWv͋ЯrԳ?؟^+L=wl? 'VmS ePr~Bs_i;#$`Po}=.  Z  k G L_  > F-~x`[/J D)M([~S2  w A x  Hy_w   w  N S24%08:fa0OL3j/5BgkdGiQE7Aܑ א46UZҵ?2 !}# : O   B< ) : _ . yx  [4)'2!Y` IW /|  8  I  _lMIR8WUxL!i"I"E""!-?]]ld Q n  /      ;  Ut  =2 K2="fXLRskal]Xv.gph\A}5jo|Hg N[ӺXQsBT&Wn[-Q2 eJ"<_  ;1 &  H  Eb! #" S w 7 l K , S +*h}TyM %T ( k O z Y t(  I wh  2 mz g \ 5ob wZM9i\zM#\+! JskO:$Qs>?U0MjgOh `q}= k@G9OU X1"xIp16Ai=411%r1ek-<&h~abyL4R+-1f" G(OVH#6<6+161zukU -oaze![aw -6/)*qYx=wZM+ z}tm[Y2WW' scpGR;jZcnn1v[CWq0`b y0;x;aOwNy#>{q~uu2?h2Gmqymn`NgE/ j9`8A)uD-/oh?T)ku%30*`Im\L^ N FVI PW+?sG"mD, _PfU!?%"W3FDNurPB?^HIY#Oo((;Vb*uBxJaxr5C5j /zcVrVb~_DQ&r1Yk;kvaQ$P a*f-3},jw*d>i+9)#6O4$tR ,$fjppt$Z\Lyl1~,pA/Z^,<KzZWh[9I^`1`4<^8VH '##L #K {*?OyDiL7#KuY*2'E  ,uL>>&>2+Z)O`9BRWh\D9 ^@:JH~~b8"1U{#}D~vQp~cc8xuuHO`!+e]gjb1iZqg@_@xFd^kkz1x@@qHXQ*9i9 JqZWS`'hS7\4H ?(F*o(rkVQShoyvWW7Z=^~n ixqgru~qIY\^hrVXa0XV}``0SB:1'4 01!#B\{*LW +r g0S<g [H S0?+`Z^^r*KycrBh~ \KJzDlbz \{w! pkZ$%P1=p$w [a18[3+$ Vyyru yF% foR  ~WfH )A=cnn[`"icqPn17EAd*fxcxO')#DRL="yAcKc8DaPc-Rux{ABp@mVmxXd 9q:oW ZY\krno-#&3| PQ\jh! (0e$4?q.5$*+;z{2 y DCWfo~_ZBIxgrieXH~kP#1^*b70u^kkZ-I#*fP`ygg:dg+C9>n#A @QOX;tD>kRO*0zbq:1 hBxKVrbP7`(XOHZJ3SsCriXPIMv,zbavQM*9CYp<M }nz@0ihpnZOr}e$!9<k2Haxuvk`^ ((rr2P0 gxu~PkC u=K a78-B:W$%*FChngVP2R$Yeno\%TJauIP!g=GhI"T;*$22+DD;o *xPvXuBL?9v`gW@ ch\0f!'~W;'?R "`Y:*Kw7|bInjquihHuxqxI:K7~y r#;%29WfJC2S[I?Zr1* I8B!*Pub+1WiaaIS4(yWS2#'~0)cKg8S) 1tV %b9m&>O|HEV[gs 4' %# J-xR|*/&7WK %"yWIvkSA7:%'`V+?2xqO { J g^khR{-P24 FzS+87242 ~-8*( [ZanF0QJ?;qi12Bhv1eXr1;qz;W^az IL#ze41 zv}xguZ}r_HOm` (>X&qXi'a'O 4%uHxLoZRPo4vr4[70+'gIrnhV9 9j::BFqnxbzg!vhzH4v;xIc^ 3`x`OhoyAc4;7:;=A:G4,trz`-x%~auK0uc{AO A%H jyV~(H9"Xu 2.$8~h0="jZ8+}oeHViY0#q`NHx.1?<k+=P<Xm\b <[{vC_s[o((4]S' QBF;:Mp_8fAq(LG1kx& M%3 >݉WVZp qu6Bb oECMyC8U .Esv\}%:  L J Y  C  Q4od<?;+; q w n  & rq  ,S2X "4sg,xdnsW_)RIyApka|vg'[l:e܊$ϥ1rfɦ;)ʍvXM24c4 GR la{ km N r Z /<$)gbRk!nbz"1_*  l M Z  M  f   B1*n!J6 8\   O    9  O x 4  .  "   n EP j l U  7\ER%P^'=e0/ 6eVr*)_ =&Ed%a߅܌Ohaqљ"Rft`:8M,  jr4 !=Y##S!^T%(J ,X p W p c    Q -:<Bx Y f 4G Q  } G f a 8] w i mX Y  UW  C2 M'^6hM/w-VkNTN*)N.-HX1 Mz @ W  ? J  / e GMbvB#[-uI*E>V  !? }25!"#"g 8t:~g{!a  /0nh!kILr  Xj   F    *g'ngA|dNuA"bT_6х'?b$Q]2 '@G  ?? aHX} I=8T 0 [/bl;xO  J- i   i . o p  H u g M  3 Be >   f y) Q\\'%em#;|<DzS?{@1O=W Xl . ? Zi<zx=5zq>vo CYDw* T * }}rI!#O$ #a!:$ Q>  \5;j.2 |@ EJ o = $  F!+{NK|hmh,vnJް}:%ӺD^5GNpԉXؐydE+^/ !A>  y >i #] : < r),nPPQoUY&VA B` (    y  Qf&kPxSC    _  }  3 7    x  -   c] , C &T C8OqZ %c1&hMww5cxmcUKq.]  3bN-%#G} }   iYqRZ #<$h`S@i\+)~1.fiI,Mv!nN@t5=bYCd^P|-kPZrx0}O2l!S`csRDgap#=GoV~QkHhYJSia;rL*OFK(EwJ>w*u|ZR0%K tOugBiq7 S.c w_f!*qUTT8j<fXwZ>2/kzZ* iz%.z4h*l[Kb+E 2 ^M_\lPW=;.f!NifB'Gy%yPfASvhhZTKb4 ;*~W(Wy?[Q/ {QIqE= \ <Xr=WCzb6+<& PBP4%v{#;%F01 = {rH@?Rn q2 zAK+EpY?LaO{uv%{x)O-RF^Af#hY($P y 4f>t~ ;7`F5?[HWrHz[xcff{kQB hegy",r?OWW2{u`kO-3Q i0.XKm[ FWs"M#l)5o)t A16GL}Z5 P9''  1$SPm_jj )<_(@)UGEi>yF-@<7'xaqV~% T=Y pDE<3Z/an_51WhT:>wN:JdM#XqGU=9DjBE>=wLr>r G]ffN  nX}pf9Z3]BTJUSt [=\\wpT:3HwM&6$J"2pTDNbm\/q6NE[5Eg wcyypZEg/46+i}A" 3sF}4\P7hoVW =k K",7 \RLWfnp8#IN=Y!=n ![%Hq>7[)NGCpJXH A=jzx)vfi\2 -oi?WbS+`poQ*(fYHRL +^sgI9RT{lw?8N C?fF@r'u'L*r`^-?Y kkrR;e1LPuaF1:a9:W`hIu'0!2-p;8yq;d#qJd7J; ^RRu)fWjYOQ 2E VH2G:00Qj(:z`!C6| I%0h`1{ Rq\vS\un3\: 0KV;8=u;a}0F;+$'1rR~-Xb~xx hFA XfLYxfy`HPvYozVqqE Qb8/@R:I'gX]O3"Sa'A$-4hWjZI Q[ ?"%jhYrP7*)30BP7'c7ry'~'?Ph=L!aZ yu.8PJkP~y wkbb+}&p'C09XZhC\5!p=,* kSG_w<S^<aW q`VZ1$!P8'ohxx`n}z9<\XW13, L zf(3! ~Mi%oCn;2%!nu5 1!\K"f$TQGoo3Z28%oD\8PIG("GWgZzPz22@0-H[o*;QJ(7gBai`8"yxx~Zui!{; <I[@~P@#+C oWHGIISB Q IC$ Z2<ySiygHFbkOXib' Z ZW W kISfQ #0KZ.exro(uWu$Oqn$8!Z(SXZ;<-Q-4u;02 #Z@ LJCB`F^h22X '-J7S@h0!{:CI_ & :0[-~R|K_:AYqGK:3&y)l![P wg[qj_)=QXfP u)fFW{V2A]u?#1 S ** @!(1yeZH^;?9 72\9Z2r+2\ F2B=?~Wv7aqaB7`jv= gy ^:7H,I1AhSuD#S*3##fg=W=3v:a"=kZV`k~+29'#$1 IIOy'0!!JaXavuFr?[nrIbi'Pqn%["e$?3kb[5B"5b<}bXJi%y8vc9p_ \8 !@nzagh[BPO^J BOLX`h7F!'8;JL;QV*;B?XgPB4 !or~L[eyaQ?PQSg`hVVH\1D*BW 2'Qo}(!*B  vPIIn<`azSgb;}k hxqJW1-'+uvh2;(,*2@*M B rJ8S.7-(CF0(4!yFu\av 3ZF~ Hgv#9-VRIWvqBkkSBYIoD 7 VjB40V^Df8-LZCneo7AH*),RjX*8h::?yFOayjRA~g1kqO84BYgPF7w&|dDnj_8n\u-|%vkPNAg\A _,K7F70=({4 LPj89BFVgHhZ){q~u=I^^LfWA-o Voxa D, )K^aAxHO'U~)=B;4x1n~oL) DPVyVrISg^%`0ajIH*j3|0Bg %~39^oBnyRn<[aXe?aoI @zT~D1aq-2O9^zq1< -S2D{yc+&q^yJ#14rJ]9A82I8ug@21*7d!U'Kr V"KzS*{x\A-D(V yKH 1gHGZ,!b=Ln8>yb[e 9Fu@`Frn[^"H(j`ND{aJk @ 'J8D2[  < b 4  X_  y  { ~  zor g )vSNGZ/'7+*x9qJTs<O!+Ir>; 3 61{gW2G]'3s}|[Mu4)Gd_Yxh%ZJ<ͻH"\^T?Zt<3KidMRU~&xvQ! }!#.(#"""!xv/#\{;3Tvu{ M =o :   b" U NI6 + Y ,  U 5   S C + Cx# "-Bw+<}_bDXq'M~u)Kg3X=O @۠=F>^?rKWذ°?궲[6-Y8^* r r+d4L|. 6 a}&,uJ}Io J  h #?X  t C Z n&;9 <!2!""Ii!!l1 f, K]l Rw.de  @M 3 l e  q *  Dl`1LF2N #Qg.$dij 9< e~^0h_WVoQ80;]d[݄80.XMfֹԷ?ZSp¼k(N4鵺94 H%+/,T00/n/ji.iX,i*_r(v'&#:$.!.bO h n I  kfCG8KW>o0o A * >  T   I]D w h  gC+ +zrV6P@|h-y ]|l̀Nj輽\2踸[ |zp=Tz؟7o t $ QB)H%H:[3xC 6:,J:1<r  (X 6  imkuL%h";V1i" &+/H_1@1k160/,)' % ] q  ,. v   <1 8 I H & P       c H XJT| -1 0ItXiiah,@s޾8cJدՔ8ԥ?҅(BOs樻^唶sy-)`Җ8 hG@K j 8& *++M_+*n&XiWkC'.^ ( 0 B     d`   W$1}`,^ d Y  " c 9 *g /-8  h &* c #mY0 ;d@{׮YzhXҍY`ר/PJRAFXa @ L>H8U Z-I?. b M\w]u5G0rxWoH{Jd R$@ B %X ( g*J 7* F)'85$!ZK *  VSrw=   R&$t7J!`#8,Ja*02WBoufcѝpț챺엸u푸כּCZ5^Xzw  vu to p% 0wM# /&h'aa%#B Q  E6h(   r } q  KZxSvBX|L+  A 4   x~( ` W & ~  8p05R1~s}bn\5\LZr\{,?W0 *U * $ EoR!%<1WqS[Hawf 5R p w|wn]b/E #R9 M OZ  2 / Z   a   7 e & J  k <)['nS(8RCE7|Lrq03i % 9}/yaTCFqbdQ;@y/YNRXM%[GpxQ[@[v=b   t.{Uu a z  >w  emcv  *Z]1*gM$)L@h!Yz s^#YY HFhuS78{n/ ]__NP?8lbpNvFZJ sZ7ZL{}8Zl.8W3f#LI;SVn[`bIy7I0"`V4*?aK)Ub*k S{([i=3Q(:D1KyXh~j'`40)y4ar3>82y@V1!omXk]|n  [_z? I=%Wv;0Kc^o,lHH\c 3G {][ly +77njC/K{A"~ABuhT[Jahtf>zNwA.f);C#p XxrkvRwJ#sMS7BB!WIru![b;]<RAZT@n|9`/ n*] -%/~<5P(>*=2[-Z_)<VKnI~{aR8W1' ]]D 4wz3C#"PhT9c#~3>nS_mSP3'NCTyE3%y{G~I P_a Jz8i^P0(hr7ORC03?.M'\iGkZI]tKA is{WYaF!1v{q'Fn\o PutP 1(1`o uy1Df\cLch U'~9'S;UwlFuTYTDFN(i'( $?gMm8\#Nb gF^i"Am&) (Q`]VHIV#w`m*hPO~h!"=o(Ny{7/$hVWbS,uneP0,Wj!r](:S0<jh_q#=Y09YY4h=UC"~ )9`0/:i"7@=O:7?`K1^nL~:&S[4s +fonqa12;I**35 &J#B+L8g(^b<kyW333="0hA@aa($F?bPLFP2IbwC9Gi|ZwCir_Mf8= 23 c: "a?MW[Sb% nPe e\B,B\kplDCWW 8$ J9B$  S.v_Z[C(}`#04z2L= .  !c@<grR}8hiTJyy~=h3Gqhks3<=C _b5Z.2kMJ;p$k"K;P^J^q2W#L1 Hu)vPP\,"o#h= :n=Vd9UpOU3@#w x\gwx~-S)X [;#Vr`ZWbv#109LZ*}zh} =$B("+=% CJ9=I b}Wrzeu I8h99J$v8-4LF+?bn`[^Lk8X^q7-9 x !i?<49!@ZbB8ibX(hV0-CFZrvyzvbxQqxhPXx Wq3~3_!b 91c%I <=Q<h @SxfJbls\hh0S52=I.Q*++C(-h~jyI@HF'- 8W7+ OA:4RBD)' AR- #,*LuqK{k g07FW)j"4{hgryyrnf`vW`O$~7;g'Iqb127Le*z^q}z{nbC9V\HF`f40x*(B4A^`YrfIhK`'PZ,ZY Z*R, 8)P%u# ;O;\)Rcuf{horP4F'YRI<Oa L Iz[^oPWe<P![^x`ir ;$FJ##}yk~QqX(ebcL{qVjShI KBqqQ#+ui]O#+R,VVU~DuSS R7-\aAjxH)Ka VvW2'2' C'SH2?nkn^ohxeXkazraQ2iWghquoC~ qcFP{rx18nOA0nLB8 :1vY08)W fIaA-1=1Dv42W72C#0#  ;$<0W"$2g ;ch{ceQ~Tn;F$n2PB*^2z!V@x_ 8veSr! Xn4 rb^2?W9 C12+Yqy*qf $$oyhvr)n43k{ e<eJ;? v^ !4'LkvIL<<('(B7 P4FVkh4O([Hyo}nxgk[ISPWO[2JV`^7 ''C44 0F?HI+ 9X1~79S7O ZFIy" )aHHB:Zy\L?%D1^u{9{;Vv1F~'--3+*izhy$?(PIqhznuhWhbP[}PgguLaoq,uYrBV-1A %#]z439|g>FFb :3-S!S#*Ra)~6)k7o2o2oHo`n#BRh^eBt[hSl92vv%W?hjM/mgnY'A9*I*c4D/B-N X )3BtpQa:9/#XcT;YdkE ],eAP_h7Rjj])1\0;qV?h<SVW<@1]PepbxgjHt{iQ#SgaFy2c#ssT3+S<;`xxk%jBI %qfVVUxpXQnxHjg0&14H)= H(j=P/L=Z pfnu;K,(77n%bS~ux"Y*SKK"# " "7B ~UXpV6[~Dj+=(_% rj!f}W4/` ] x 2?CF T U Y F 1 b H ` lB (+!B~50$KaxMmYov:ks C {4] -lQnbDh_ v!+j ;(9rKBo W/o?Q|da!t7+3,!ILK8IhAt/ eR [lz)6vX+9!|H[AAd ;1nAKI'IS0eO;7nho}~DvK C 3[qn\:   h  0  W  be:y EQ9S|vg%0vQ%)v ikE.!!VW{kxtK z 8 %  a} " 4 j:R2x pHE;`} H  *<=%TUR/2O_=GT3R 3WGl3ldS0t]$/\k39BhlcM9P$9$v[;Oe^On^#nLgn`uHIHqn8,*gxV7'OYPR^ 3UniO xJOH^*%I8gBW3YBy?7T#Rx  &g6 Q pV P} ['kLl/]QV O=e Nmھ<FպAlהe&H .) ] % " T9   X,O$g ;"g"YFlmsu4FGTIHqj>wwmuh4 Z V       N $1fRzcz<[ *o= mI v ^Ig/ehb_.deaPti(OT Pdn~c Ht E Z y l  V"    { \ 8 `  *  Wp  8 3-?\ DuZL?HvO$:ehqeXE`AH@2T@A~kiz6``3q<H1+MWe0J'F N - V?H'eyhBProO(@(h@1Q*zg*):|b20;^?~cgan#x2n0!Onp09@ gH-;S=nxq'W1LnIvvuy}uk`XSoh?n nn s _ K /nERnBa3]; isJ 7h)QX<KTE\o%A Xw3Z< gf(Y8dH^&L?Z~[xM&8-AI0n4Sj6@-N&iN"}m=N=A 9 )2NK!&evo  R)iMN2'% Fh~} 3u/1tX#6e=z)trBW|K S#td-@8N   o  a  z Zt(5vwuq8:nwGB.z 95 A  vt  H  E ` n B) ` ; s2 'M LB9gi6{H@\iU"5~2.3l2Tm  dapCB]T_h0w;lG -* Bi' %38o^v\3xDWL%x `yzp5[K)]=HI[CKY63(7:":d2ol&XN- Gu8)`*frg$y(HH} (3$D?Q%J;B $LBB&8< C,J{a$Kc=,W%'\ {h2gCT VRQv*_qW )".Gu=rKCg? t @ @  A  Q ( + 7 .' * [:pz"vW!T Sj@e~8!5F it Q _ q f 5? ; > Bf } > y;n;$u}.I1?<[xU]$.&@/3"{Q < M /o" ^OKHqkB|29QK8PVP^%`|Gd:^-I1  [f 6C7-+9C-R]=`Y_ &R27jv[ @ @OHoH4CGJ@Q,([!^1"zJF-(HavnL neF rnB!v%,5! KzoOq^'r-;`O0 ^ r hOY|JK1,/Ngz#1y/`cS.H>2F,12 " ar>IDWS Z ' ]a  8 0  u K e  O'@_.-xrPwTlTLK /\y?6'ln=<>Q=;nRPn4"YUWC4\7Kp6TStv$JZQ)HGEv#^Gkh dr |  J>rh.)Z81.1g<v[[Dq=01 I/K{p?gB03"?jF{*) N_=ApnA7"#5"K )+@XpUOVi-G)kzWp@C]) 0 U+(6E!Bh T)Vr H7XJ  &1&6U?a K@ 2 g ~y R$ W4:_ZOsVo^d_m%W   `   < &F  q 'z  ~b ) W M` R -\\uMnIA4F1gohT HQ[/B%f~`+j(}  -a#rHv0tW9R~k i=SS*?$abq?o A%Fo ?R3=3_:)0YcLia.Ir~)0.jI(Vp{o\ a " 0GGuz[|A`#A#O#A>3E Kuqw~N@auv="4ZVyK8?h-F^(!))3-T5 B=Hy[Jw9bhGhCz}iQZo`CZ++;X8kp8? 7b'0XKW_]iswO $      r Bu  b}ZT$QT ClkNGAY@5<D#   : [ ~ % @ L E  #8 m gW k , X Zl<`okp,O{5[59:'r8Z&T#I *VP^ Y0hjO]D97- `>0ymXp8/NIC-&00bq @N2= 4-#$[C#4u-: MMK=WK8X8".[r")1X 4 9U H6%p|: k" 2W]FjNKOwsf?U  < ;  {  ! ] 9 c /i b  % <$ @ 99  Y Gric ROq]?0vx\5q`QK],R6_\m{S;@"h+jf*D)<z<y(4nCe ^x#hSAA`3 "zA@mz7-mC 8t2QnRco'4x- , [N&_d6^7Gxu 0nAF[('F0r`[#qF*b P3Q1`};u-vZbvyHOo' $ z~XxbIVjO-}eJ oFnBaCQX_4R_H%n0P8v3xoH_}PLNCz"[+jG6Ci_p /Y   o ( / ]g CtBnr |c } 48 =# 7 {0Q F^r`{t _;#0 xiv^6AV)M ~%kOAF+Jg # x6z} Y 3 i:jVLDkV@W!sWi"8 k/no3bXa  , r p3H]cZt p V[ 'G  l#2;2IQU8hJoC#n:[)&V[KO4|Wf3m+ + Q ~ : ji c miveLoBNTWT-nIP=d   mK 3    O  ,7 mI ?0y3xE W2 w<W#\M  .mE~-#s]K{ '  1  ?BE YmDT^H n qq.iITNB'5 }>$ Q   \I %  .KBw{0#{L #?;bfW[P< ra&( Z. n   9}4Vd]p! d}sKy_CRJO e r L J #  3h$D[E P =F([]z9!Bvf`Ii j   - 9   l<Fi6Mf39 Oy 70TI"tK;4hwiP;( R r uPj.eIHfoM8@ c'Zx%0jO    + V  7 J P ,N_(E>_ HX6w HHCjHfY&JZ'8X=B Pt %[*`|??{TKUK|PvkcClEA`:8  $6c4L};'n#N~:HovWw?fce4CK~e!EmT<qlSA%q%fq<I<* k a %YguDWk #!9 *uu 1au* k3 >K@,W1  |U)fHz0: ?4,Kh\\*7*yZ2bvISJ8b-<`#1 R;WLSXcikaurv9Q_,y"*Bj=QmHMA%H5h0?(zo =4r9ZXIszwMSX=IPChI1^+{@hSV1'Bq%;4W%fkZ $,"yynH0+H;V2`C"P~fj=3_;<[J9;*^r'(= !*$+<LW%c(oSr*`z n8<!z}(`7ZVI;2H?P^? <W04IJZV,V(Ya~nB,=7L14Pauee^o7gu 0*[I~uj  +1n+ QX@o0"CeFX-OADcIP D {~:Rcq*g!{CZ8k) [HR)oS)8gqhzgxFBq2Q`7^r#*oP0[-F2.k(oXF@WS4 gkoh"3(r}<a};(7 #9H7Vq#h8I a$# !~KFf`q;-z;g?~aP;44 -7%=`q[% iZ>VZ)+=!Cg g`6N3$ *|x@0D}cB;4@$&S6;g2P^h[P0 !a fZ|q] =vd2Z?Xi@%,VVpA9'?Zf;ge #a;*?gy1kZ8%K"?V31;B39wq b~E!`AfiU _J7I]8 qj7j{6hZNu]m 0zEzgRv;L \f=L eo+nFP%Zkic,Ir2RwH3qc&|%0 h1#[*%"kxcB.@>nrJg UtZ@;;1?dyK|RmOmkz=sm%*J*)M  Y&=+Ksqc$>`w<x6AKpQ)g>6X%\9 (2KAD\Mg3[i}lR=av<P_3DYq{".y"\.D G;$i$J,  I5gHbriX8e0}2yz@yBPHQ?}+`LOFaaOZy*K;' W:IR z*a%Zf#g~a0=)HfXVU%zp0&K1M[iEqfi_38?K]m!#\IbUnyVHN=WQ}?%5vsDe6p!{I=I69aw K(R&C3mYd]pnJ 09&9!~ C2uf! f d0gBXLH4/I>~ 9uEA H`>XC~3-2`>:3Ex(Nd_-9/~>K6 2O-iiVnx/ 7|GCdE0xQm |)R1)SKnV-[U>-38N`Y'PNqfXzD-R{jYa* 4A 1m-Hr0 W#A xq0H3 48bD2"-$xPHi^D9}i<r\4bJ!y Ix8zBH3PS S!MeU)6UDQI\BW*$= ^V<G!vhuge+n P G8i$8q3D,M XhMhxkK5CcfOgM=r[(x;b2!\LDczIJ ==ox)sC2X3M9%h[JM<ivDW BIn}y7KY0F4Bg#;g?!LCkfgy'oWn0nk`yLb(2ZH 4W.bGzb1H $q$V['zif~B*rJZ!P2hhcvM;7 Z; h<,L`7P-`n a'n^aky ub7![3"3+$ nz^([4aJQ!v3oI C1as%Gb;4$$78(;hu4s*7# `Q;rB,#79!;j7?+1IWH{?hCh9-;j"'u HJVCe13-nuu\K)-Y =~Skav!A%L"Va4oy`QB@2- 8 xW^}(@V0q0S  ^O9I7\k\!AarHHH#B=w )Y7h(vakPu0 jjKFWyP`B#y;hHVVyP*exjV %;b*@CZf *h9 io;*0!0 W uV$ (4$^0  2   h #Y ,6TsIu EVa^   Aa ]  r  A l k8@^=V  @! }RvUm`V.R}f2A8~6[ai`޴{ڒ39>ɡŨ&㵽Ǿ|֭+  E 54 !- !e mN!q F""%$C&))*)s(&R"PW3  < i \hoHjS$ d46  X  V  Z 5  " l l'Ci\, SqB ~dO<"\߸9؟յG\@@軵9aފdZDSW䬷gFs*؄ZtI0YANO ? 1>MgSkt?ea7: ~=E)>/ ; . T Q JYL  i >G Z % gI%nZ. #'+V-04562v5h3 04,'S" _E  Z   R 8  *P n F  L n K  > >g2_w}(/i,8Svk 7p"Q] X<ۿ@הc2Nܰ!պ|҈Э`lڑV~{Ե2Q" ~ #<>%g`&(.C(I&#p| 3Y;o)- )}-& qi&zD!$('V*-n/134555931_9/,*'K%MW"A K TT,~75dY[#.0yx4[E ^ m J & Kagf@[}4*ݶqٕԩDɇ6ۤU#)Cӧ:9>ۋ-ݳصSFJ~@D!JT,NaTeihmVV  Zh-$ B(+$@, ,<-:-tW,*(!d%w " 5@J_5w!eQj"GI?C;4`- F  _ d 5 U (_K,Cc'^ nsOea4ވs)|⴯cg>RfX$  O9 p 7[ N!%'^'&$% ClC~ <g^oq~b_= uTA hQ# e h :s8#'*xZ-We/0%1Dt0. , *L C' '%5 &"R  -, 2 ; p ,  L > N 7 H g    l =  A8#W3:Q6ۼCb8Vl~R 9vf4s-ŷQ#҈2x $N q v~ $ ! s# I&X'W&$!c} r/nK.ys]m`v Q By}4 $U)5p,W-/U0-/^-+( 1%x "d Z n,Z3d1   Q 7 [ h?`S;"}Tw|sMɈñ:8㭳9ޱzO쪼Nl8lרB _ ; / ]#]A{|1I3\^ e[#'2f&FS|y  Hc c P Jr#(G +i.0Q16(1m/- * ,&@"Je!='rb  R .O` N/?&s_B"r|"2碶嵲îήz P럵Q1A Q "-d S\F5d9f 3<r 9YH ~B  (2 ! !X H > FD|3Bb FCwTd~DVՋQ"t⻎ޠU$Kߕm⸩yIG~'ʯ"y PMfs KV! Hpu&D , Ilpo  &!Wc G_"$i%\%Yi$P#c#K" 2 +     pl`_: ~5BLz6Da#RK'AC, :{髲n!- 9 &  , 7` { l m z*H{-c<}BdPc 3H`O  W Y"" "c ! ! a ~ # R   + '' oDvQe,P v yaq5]6]hwDʽ#\ػK=@+̈l(Ss: ouJb yV F@ Y t%161_M_"wpQ?$3% v_ ] r 1 ) h i    W pwR(-FhQ+#?CQ02=߹_< iϛQ̈$ɜ*j/̘ѕ`<[nZd8`-Sc#ki ffQRJoAXBke(GQ@E}/ G}H!  `" Z  h , ' sj|'u-6 <t.{7Y*_=s,ŋɤzؽOfYs{z < aJ_-=nzO;/6oz$A3llT&J@0b+W l    M    D + 8 } }  +Q|G  sP f %xx]UnD$DLvIzsLO:ގN(fO5'fк`g8[lZWUo[~JE  7R;. AN_P0"A{f  o ]7 Q   R n Iy IF jlj18_Rwd) 2 x Y# E   B   q  =O 7_h5I$2\Z.BFc"?b;O{`{ %NOlPunSVr@O-0CY4KmII3 {/+iK\D6wzp$7yu];dlSPgk[ #RD\*lW P>Bt 7 K1-*0S{;3?|-V%Uc+kA6Mmal'i:<>9EP4y)U_D:mY-%j->6Ip8hc!wyrZ #CCG3~z@C#is)X BYuqZOkj9'WG&%,=:%mk4FS F3( V}=Qz[ete,_3=  %9kLu{!hX218; f\<~~C9 x "k! $v 2U {[Ri76!~3 V+=J88D:s6X"T5c* JdKdSaMq-2c:[H)y(a?[rya{ $(wWgQiy< $ Wh D$,F4vF fnc)xg~'=o ~0o~qI*Ff *Kqq#oc{2xL";TTF,?{x?|q5k3Lu=)F>u#LbDx1{ ;-BKo':Zy^OPMJGWcP;  zKM@qJaf8\H{?OzS@h$+P7n^o?P9q7Qzkhq`^xJJ$VH`o\\]S}qjclfExuh#fGsg;q%tk kvM]VI%kJ%Es7XA* 0BD<.Qmz2;-B)$A&W)k+LBj+r,ll/b/TE%i_bX;TqjK1$9DaD1HNmSDo]_M(T2" "e!pI<+#;P}nscz5g<3M +<W*CeZX u&z'' fKH2!#J-%TzrwF8of KtF-\ DHBP gZ" aZ=Q3)r-nra hIjYjrLh =ShDP!P"8"6w)[?"Z T x6//"9e~HEmv[s^^ XJvnp6 2)AheWXMWU=s+_@||{ ] n9#XC:)N:0p)j[:p #9qK6[`&H>E"3G"JtU!A#/YQA2-RY6jQjEn /`(b:3 R!!(>@X(36Ufwbtt3`H6 -(  Ef7#UG2e~[J0(H3@.TXKV:j Kd- ~u , HFI?=(`BDr`*k?HJn0$2P1H\oyZ33 4kr \`#+{,1jdq 0S?(7?F @1h-yWJF;`uybWH?bTK M!2* B9JBM\GfD 8G voyXiBL91a+90^@`hj(' #h~ J`(A}-h` ^R0hoIO0)0Sh1P LgrVuZ%$P,WSOhkV:h2T<g1nS<a1ihbc{" a~\9e/ <=K bCcq) /]5eA< xz%\,XX2sf!bI+{eGS3bk~Ci3".4?%*9*K'}~`xuiA?Wv1T8a + %2[ViBMna TM@2fJbz2p1lIC Pi9lTK\5%i*i vBIS~ z*.vaha oH3#9e.V ry)Qo -eCPXH=nf{fg"hi[;BKx {y,v2k}$8(^x 'O$D 4 *X0LSsr@o7gO^I%gL#*7c~op[ ^$+'P [bSInIg1BoQg4H"M蚹-=PւҙOqMɲ.нׅ@#fpk#פ  z \'? #n( .s~0 15&0C-'g [{BibO7YC i hj?3",%D*K0 v7D#d?(5I1+ P*S5*#T(Vp&nUc$mRLC9L2+O # 0  JpV3M/T  ED   AYnK ~ 5o u^~ULn٩NL`v Bڻ\ۋiŖ?İӀ s+@?zh[L `Ly` )04rZ7;C=32h r(;'vjb6OA7(& +~ # Fl )/i1U!8#B>#B!D;QCAj>/94< . * &@ #n  )%AN^m :](  h | uSg5 I t{/c426׫=隿5ֶdkܢt~fSϧh$^ Yq   "@""8!;%8p0Cb 3 x4s j&ik_/ r&/_5M;c?kAA?"<|7 L3) r.)3$D  e 0 oG=x:p  J R  B \v yiX YN=FG燹!ਨJW(s䯞   ')|FV <w|i} /m f6|"0'a`f D b-jpJ ULHN-ZPT08 @ } y '$-X<2Yw58*8k7;4*1 - B)f%?"U*_F(2u w ;   r  <: }k`H@zEY.}傳<_],h坥=鵩qW W ~~' L "!`C Q[ a!vu r< > ;&HkSf*d )-U%& }0A ;  _ F $S Jx"D`1Z Y* j   *)N6MJ>190X$gYQv^`gOux SL;qE{\x7,8 E7'>py{! #qM'KWoD5 ? 'v 1I u ` UV y u g 2 * 0   4 . 4\ Cqoha4 xlr <f;t,`9K|I )g'jN  (     )q o AD pf V Y J z  <h:o*xiLX:P;83*;5O*Gu@4#BD(dE*''t'R#@3^=@,Q9Li,#lMCp0vq41IS3{YS ,R_BiVS)@Wb{hGwU%Wi;QL=Po@Bf=K!IHtJ#:[G\/HoCWl<w5W)$gI\=fbEcI1<S|`IJ4Lbe3o=H[GZ4[+k+@1'` "jB{-=vO8%|,u*t*FyadvH^[ofw#Shu0cg#F<}Tryhr)lRu,Hx<%1vcy\yW{8"^v;Io<iC{G@,[O h#-OZLtQn0sT!@voAUiB::H,'y'R1ADc ';o1PFP}8 yro*O3?`cPZh)%sHHl1C*ccjH@BWuh 3}V$+x|)P=3IZn~RY7o:jnIBAfj8,)1nN *z*R *fyqK?C-AQ30pL7-\yPnk( LQ}i{J-r1-:*29LzRcS1F9Y_a_ik aHxk0i*8<=S1^!1#Z<!B* %-yV1SH:1x-V!-m(`# 3XN(y)W9@HdfSV6j?,SgLkvf=r{K;B/r/AJcbhmH3k;ER!Q]= 1A\H`H9&6J>Qq-W= Oe6pmoflN{>])6:/ f u7`cx I8f0HZ`u rqQ$#1$(@<0v ZD"=0B"?%2~{82yVukJgi^mi[}nO 2;V$r2< }iH'W7O!gF@L} f~GpW9BWr9BBa <C!BhBFh@_ r([;DOf2"L@ObO7ga@Lr4aM3Q093Kk1a+ vPrv \{ZD{h=P_ Qg7{BQ4iB<P;B8b@cZ*/:skhasG 1<l i.G<V<vPPO'?fLkux#Z^Fr v=*"C`Zq-eB\:"B%H>~!'7 )ra *LrQFP!:Fh 1Vq VIS@WPIeovzay ![$@ok#8*!,sB-RBP?xZIZ0 +;{OanOgaaO8ca[*f)F^1h?fOD;^r7R6K )z x6CZxPkzHa1DSY4r uoyS9  !ta {89(~XynHWvn;hIn a0nXz8ITC,y^(KDWF nQf[w!H-{"- I(gTb2[+v~y{O,tii5NBO a~I!3G (eH3Y'Vrx8RvS?y_+<`{h LI@ ;rw *oxSH:X;e)9I1-Qo72g-TvAf[4Xn03<%\C_3i!+g['1Q?;r ;8*LvPM8X ?ht@fG`j{Q+)=VJ4X[z W0zixXhQ8)S% 4 *84,`4* cWFgWfxx+Lu;QQ'948P@7Yy8vL` Z1*Aq<e j\nz\Cv qP{hhSxrQ ;rk7S2FPBi+IQyJzPP(Cne;QIBQ1P4@B7 I{nkq?#*k`^(#i*P+@}g$!<P2g ;!P P<**#*{nhk ~IB Pa fx?' uv`'7  .GPf(K@p,%f<@fy , y%rCFb !*4I@v*n.IoW1*(J^L4'v0$}!`veZ[P8*LIJX+g+nBi-S9( g4g@Y-1xbbChugxhFKPgn?S%\L1 A7^AWB1I,,KRD#L3"    O3%A* 3'SVF;7I7-q0DKa aK ':Suy`yx~`!2*02 Q@ *#FC;-vRfra vV{j q '2'F# '!--H-<!I 0BgJL-L$!+IJ#Lyhu?eo2*vk}e0uFzgo(xQ[iFJo 1q@$Ie8[ g [zb[SL<WWuq Xq13I2A;aZvnqqZn4!*vQL1*?#2 1Z;`L<; ;J0 BS!FL}WZHV4`hnSgxIXax'7ev[n(Z?7V[`b4XW?BkoLC~`ZuCu`O~#P!h4I0#?`y!a-KcoP v\Sq07?oZ?:V87O~VS3BO) -,\8YHL``F^=K#P-Fh*V =#)KFF''DK3IWrPknjZyu\k^K~q\^\j=HF?L7g8IF37uXJ_=TU6Hi_PCd;LL{tqC|Do& >Y  w YB  j Y   H : A T  L EL;K=N#u$x"9#?%e'V5& %   R5 i D t ` {   6 y r x QL.nPeN^\zyrv2sOvU U}3!kI݃JTDF"Ő#bՔ>rDMj)) ZdK ) pZ `c%jhaC5BSIO{KB4iyi@O| = *c$9\6lqrk  U   L [? =, iBajA((  nT m y 9 +   >.xK:Fc+W10+Jl9wke[D#ʶȔvrAԋRfV(FB} xY0 t yzRB/G;]#xZY\ Ghdo:RNp  H  UQ d    4 vYZ ] J  V /   w  G uU T Ji p m   K xI E( 6  -L \K ,   >0 wZ;k"< qn:mik7Si~`iMNde6 uw;!9 %GƉŗvToRShzA ;@n6  NH8  w H g ^HuF[ "wq0V=x-  9 `an      F  2F8L D   0H     / * 6   1 ; 5 ] sA     O  rk&\<~V8= @!tv)+K׮&?ƨ<^*Q~:Q OS p !5)sMoGi  /NJM n ~If@X e-NxiyM}5 5e  I  wm  6       HU    N l  14 Z]EqZ# H   /   j { t ' % [ d /  RT ,a wma0!&[OP+" [}2N/yHSrIT/[ŽiInhh L c[ i 5YI*x r3l*e: muiN-1xs? G > W z t J 3  9 S a   8s  N  ? Vu e   hY  e _   . ~ w h w K  wo" -QJ_YMmI;0Xc l_^KӲFkĸlP->Z6֒/)` =@ (  #vI  D=[B fL|V6 4 W[[-bmI-3F^@=p  > * ( m= D  M   Jl t u &  } Q  ] ?2  B"  I 9 Q % s } ^ '  x  mG  7 EMcbdG{ $FC#:9{!i-k"$f^;݃p'*Ƚ&NJ.ge6JS  h & fd  ,} F #] v[ da| ?Y}EEBC'7k<] @    += $"=&6&$*A\&9Y 1D % ` xA9HSGn#=K6[F;J !J[*r \`}v~Nzr ъmXM,?mАNNN>/J2!2]+6 GVz2=QfJ`oW? %8RQ i0**[7B$P8Vg4_TBD+  hJyq3   21Xs:%%<p9$w(DT! WP!uS1{"\\*29XcVS`o7SF{v1,uxZyV'\ ggKDZap>f~sO9ePkJ@@u8V1/:z^n6?Pkz"z\DrpITT8(     3Y ! L,FAa   Uwf "+=[2f C~\2yHS! ]C}__  # HXf10Wrl6 >tW6.wz"- -{|g8(-cce8>: 8X#1Z9gV'9%: n{   ' O 3 b 1 @Ang-Vduq wI^&Ns#g ;YY~m'@%Ej  kS  {L_VWOE[Z@_VA6n0yuW2: `e >b;=BrP:QX^pC7@$iFQq 1:^ ()-< rI:]lFTp?IcC+Jfc 7?(]Djvk 8,*1YpGH5IN=.Mh_rZ]|z1 RK^F*cvVL%VAVocgF;n7=OQ~E-u0YYz#m =1kYq`F9O WoQZnyqhS aRv,y I4V*'@0xuH49kH;Hzgzzbx F#;1ye`Byr^--%-#(*Gu:Sc"R #%*;oKckK1#7H2!QL@FDunnXyxiaLekT\{b*DsW=\M(k*fQaJJ[*=,!8, % xa+F+a'9C* Lgee9 7@X  '?8hau};o[Oh7o yQw%z,CDBo,Me-+4AkYZlrlT%@RElUta]YlfEq{U\i:5BHB=4p\lYR &"&{%1ShpXlK@[{"" ocv[vl-j3Q>}\[N{HCE-6N-4BEDUj-pss}}i{xeqv9T )Q,[TyXvT}\^%JkPb<gS7;=8DRX8Aw6##H@qN"KX7=(Fy6N"/(g)FU8t/y Q)N%2) _2_'F([m8i_ "7@pVUzjqN7Y=)}"00}Q(L+V/d^.J_d[ss?T\J_liyoS<1@6_.)??bF[?E65!^T=m4)WM8FOG9[Et+>:3HEH3V:j@@(0QY[uwK0t-)'?1P#LD#-aV84h 1FHkcQ'#HZI{^O<qoJnXnohV`iH?[u^q[HB<^!7e;`Wg ;+oXS'q2iOi+7F Dx%k^q2%f$+J5. KM[Z(aJwo<!o {-~!{Kfy*< #z_;ieghLyVazLo0b1$!@gX}WC<# ((oenQ8a17ga *@Qxo84rS;iykHB(xPWP -sK =D3 "P% *31 y{"8!,TD[2~wo MQ"vguzvhOh`qi}ybby1@$ uWy#(OIL^;Hoj-+ 9 Fko@ib9b#1*? '9+ 7 0$JH!2JS'<7JX*9 h2i $;JL1`B?0He!@7VLe!!*(FI 8 4-H7Lgx1z0!`r[zuFHB@1JFqenWyi[Oy2'OI< H7<[7z^%x(ZXW4 18e-4k x vb?g[rZS29xoC`Xe IneHF-40`FnJhV9 *X*4(??a7a(i8P!?b[e W@ Z#1<!S (  -'1#;; $I<$Car8i<8- !gbzoJ1[8F- @7Z?`7 q7$QguxeP$O7O8HIb[<I-  I :{fVSROKrk xHnBnhxqx1ZAcH4 ''08;0k\FW;H\ LZ#W) g-BOID:)aAu rKf:Yy~o{ (7(C+C<;F1 '8<*; <HXI- JBJJ 1 -11;;#Yv^W:;~%~K8L^^AY?gOrcq:4= i tbYXm8:RH %-R:Yfo;o1~0OF`BfB{frSr #*(9#40\y~kHnf P-'%8Y?D?a*HDAgSS?g^`Zf:xKj nqk?BI#,1agrIAB0`~KyqWr{- # 1?q`h2bO[*BkSreq2gHWheQ(?Q*$(0xHS1#!4WQx-;Q~8fL;\Hk 0CV j1W-F+2*VnSKOKqkjx248PB ';-<<1XoeP2Vobz$"% 2(PsG zQ TPZ\G_{Irlvfl_K(wr5w<wGwylP[\2c1bh?aQ};uOq kF X--BAO~vIxF`koh`Ic:-hgFZrF 0cIHu'7(<@F@8+28FXu!g9W#i$[CX[} rPhnouo<k@+vWqbB^hhXoIH!u4yr1FJIr*4FqBoyW* P,8~'quqSg* Z?v~"0-" 7)%LK-caZvf1nk-=0Of1kBo,`u< g 7(@e1 Q B#[4?40 yr~{^rvOhkIc-3?qOfAA LcZn #r1,-8 ZVg\*H)O=\hfA?PbBZ80B#VCIOPcxHkyvK*R91 3Pyfv!VqkKI2 0Cy:W'#I:S:L )nV8jFDiW0?Z\BPy7PL !x2vVn'b! %7o@1rfZnn@fzGvjl<3)3`< BMC   Wj;oVS3OtNH  - 'z  U{ c \  C R [kY`RrPuKUM?k+]v}CcN1S 4]l:SJuaUHd[8ڰw%;ǰ/;Κ0Ԋ(lv  hJ |dg4 [G!3#v##"a!BK`rz] 7 D w Q T  _  n<C <g_xf~  Z A G Z    m ]s kG"Z"?7A#~?zi1H:y%7EjABsvL%X',#o7Ahݱy!lqoc4wzq]$z  P V f gD * j:PyFVoI=_9}y 3 O'o| b  4 @ < f Z 0mU:IB! b!~w!%Q NEF&   Z( sv  i   [ye!'0 N,hniGFgC}^SG,=2mSzۉyֈH6Ї3 ȋ݋ޘ#l U#RT^= pm ! ob@6 M .pH8wa=7%D  {   3  @<- z"|?##S#`"f!#8.7=/Mz |   dP tJ   3 W  "D % :dc_<\RF!t)- u4&tdܺci@~e_y!}"ʿ<о&߯xatJ*hJ ? B(Ek/3pi y Dzg0NGN:T*[(!aP"%`iJc  = s $    g  v  2  ?(h|Th.[5oS>AmQX?& `  A   O s Y P * #-j0K~XJQ9<tUQ{_@uOK vi&ZHB=,5LީIGmw߱q߆Ȼ>˩<G ; wx) ]P 1U7#3! \ 'eDJb Ih?Cs.[3  e g  &  1 u E 9 X 9 `T; JAsP N/W s1D r 7B q }  g> $   b v ! w  B8;RIzG(g1_qI^ pjSr@' > *Z!{I`/Ux?[K`8Aa F  x5yyw`    Nx    / V  ,  [ . G  N D m  Ex ;\1P3} 82,zC?0Yl[ 0r_F>k|C1PKY6עR)j9˭85M:ڟ%ED> S$ <  W M v d >B u D*$Gh$YDe^y'x-/   _ , W B  m v  @2O `   H / #  * UT,/qk819W-ZJvys`Dxn##< L.1u+eѠ<2 `kqw%-  OQU k * T: &< ] ` t <7 +\psUl-Q' wkS   ) ) bJB2 O 6 s "}  p $yM|   {  5 j'Re%q:j]!8y^55-20:UvF~#W(s-u:*- Zjڧ&0nZM`/hu1 6 yE#)w + 3, 4Y b Q ZQ x M lj G  uV  +U c   'T  c  p  6 9 >?  J  z 8  V g S '  \:-@YWP.*=\QC \&Cja0RxNhRc)wo[v_WeT:p)Z@ns$+7t:i +Ck0*[ye9(ppKOE,#C$Vpqq,9V:R4V*D9BZGT ?uL`U$-{o29Ko{'[razuQ~SIK"nWi5(8{u*W kM"PQC@a7hXW.h"B5}}}B:a]kuC5YP<ir[4KGy}!|?lInl|]'eb85_K<+{VX;>7]HE]Xqv1@^%\Z[#8ZWCJ9 <#z*au2`#9 e; N ;=#='L^V(^1LVfLZFx\3h'RH=?8f3\a B: 88^{7 7*S:!)'c=i xyPB;O[^iQ e ^AQIkin2yau M,corS^9kn2z;2n v;Z@*$Q24i !(.  a q_vPQ{p@f1_S_  !<[[G!D*CC8PPM<XzyKMQiviMspl +!=$  3+ 3 ZaXO@`r`9ix +aPS7unvbiy`!WJkq}$Z^1=i!-*oWp{Zk,}Gv eqr?(? aor2Xzi`<W89Z_Ha(3*iv"= 8 !v?00 ;1 ^ao%0j+4-Q`9ooxP j,;r'c F)  E|if3'LWn{P<nnS`FhOy7g4^7F1-P1o{^!'( CVyk yH*-^+uPe7zu7n (PnDV:f~|rE:7m\uB??=#`2njE|7v m}PG%=yl^}y-0f 7' & p#_-duwSOP? Z00y(0J?^PBb[b2oykJrzkQv!! 8Mf*_;!LxS* -G#i  *!fa54P?#(( uoXI+rXIhavoLO;28uQ+{2?C1+7V49! ( -Xe h@08<B r9aQBkhz[*G @  %"XPM9$@KKZz={\C [aqIWhbBP^g*;Xxkbv<+`{kic_CLVqqxeXgJ1P^JLnWbvZy}xZxni.G5CZrS[2x_`}@nO\a8pJB5bZv~G*b{{=rQTP$oXS;(S~$\+5   kyM [HuehOWXBh'a!vj~OKF KoS3;-| "iK&d *p9~HbCJbX unFo7BxLq"4YPx(7x5p{E<:h]( >   $ t$ 1 h @      pY1"&w 7,D&RYS,"H @,J"HZCqQsB;uZ[!Z?Hv7AdsU;3+LDZ/i*BZ b ) CR`0< 9 d KgaMJc&F$t@"{lOH O $ ]       2 o ,  uy g5:C K  q MZ(jW#B0"{5Hz+?D|OD!FoH,p,YB:`m~|[C|;ݶp9 hAQ&mX,B :9t;zS 56 8 L M-"o"b^O"~K ^ +  s  g   0 Si       > 5 \ Z^  w  t . s k D    VU@ZH"m(?Nmm$P>h Ze@"~]cSuw^Va.:ci # <  x  t /  0 b * k u  t GZ  +  < S  8 JD d =$ ^cQX,On6YN-38gmS@G%G~q^ޣ܅^t _{Ru;X}D  QR  z! -DUC8=wg c0(`n cJ|J|h7 h /1   i~   E [S Y W`  & D N4   ML\A%(p%:o.YZEG;`AoWqXw%6|D'm$5L[Bܝُ8׉Dد ۈAD-G\M#dp L ~ N b >~C+ / <9)SWTEPocjG{q|&W n J S !" [A 05 e U / 4#b3t+n  ! " /   O EkMdwj<)[O1Xxq9UHJxiRETG  d g Z R=b9BYZ3_9E$%  Q 3A >8 LT  h`j[NHK!&8zE ;3/owf  vV,#'w>DKXY$ y CX 3+T)IJI wKe[LC$cP|Z`O~?xN_7V%Fr>}C b  6 D  d} $7k%r:U T   0  Q   <c<   A t t " @ x hmB18NGW UUyH<Y.7! `Uqt&M3=<(%% h3F =4;[hz#o9HAQ}(~-V{b&V*4`0yL [w$Uc= J/r(R;{VP<(, Vu'0P) Hf WZH^kStH45 -I CklwFNSUo]~qaaI4j;0c-w62;I'W>g};iy6Ew6qBvk^n3& ^] sZrcwS8rnBu@fN.lP]~kN8fbm<_zSr?r a-nyPn?\! mu{@ $  z  T   7" ~   L  M$4Ml6pe&0Cp42E!ubbJ ` >LwPjK%@>eQyuN   : g$CI E2 ~j#MN$w S q_'/RC@<4=(!hMs['ZQS46aJ$%X=1\Xlt`:oJp=bexPK dt(78 3H fW(@JrKy3?u/ 9$#I'cd/0n[A2;LfzSHJJ2OB'{_RK:z& g6@4"W2fbPBv-vvdM!tI8F0g {qSh_;[ R d>)s@mnb<dudeVV xrcKR;ef YACQLmyrgL;7.6>\r} gr;"[CnW ~*@w__8#Bn F[ @^ U4TyIBb@;K-b3~V"P@S & !@WY^Mm/2V19!;8zg^M@oP)'uI{ ^ 8JNXcohIo.S BVUg@ay"Vyyq[_??KN_tC5:vs.7A>z=X U  8 H ;nv_b3] hb ! U Cg  7,*lG;)*;${+N*W_Fq+y  kOc$E'']$<-LawYk^F~5ABX1C3 Byw9`(+ Zx}e[ P}sh~+osEf@ P_>yb<pokhhi `.TV2BDv 8@7R  EJk }[  9 o    E(T3 qqAI):THWzA%RbG(u   hN Plp|fi R % M ! 4 WA8t|PbS{Yy]=CD_3"5WOV+4n`<+Tv$M.DTZw!BxJn;Xb1c{Hx#K~:Xzf_E/Qzt'VL+Ed T!"P"< 5t~9^)\]m":X ODT e/Je'oc7E>fhT\ fghC`}RC16Bylo4 ' M r r '[S,,gc~a'l~d 1 % *.wZ uY8nLrbiEw0F?UX-?yxj  )t<x12x'6-2^) - ?Y!mUw7po)K#{R6!E~z&7A^C:P ' &YfUiD z *8:oj:F~qCE(7Wn|o6(B]2Xk 5& _:,uE@ ||GM q p==3O>T,= %||^@6G@ ] \ ;6xG{ R U[e;7f5K߱,o&{)HuD  Y}$OPB]3*yM5c~ag ik bq0Jc:s]z bSeY-kh7rw O  B *R)LIIlQ [Xt@\^[dl ?dhM%@2b a fF }R\;^PQFZCo2\C#M'[H; q   - n6C  e = iB`nDTr5,T}5 c)oP1Y;7 _^!P    o e V <  q ( G 9GX&V06b:OMt[ L o( s + =<o;-ra D ~ y 0?   R   @ k m  2{8 h>nGi0z=FcuK-5)({ cA5$KWfi5&]Yp- DGD2H%WTbv n")3gq4Pt y   V w V  #  d {a    <  2 k X 5 > M $ <LOEAx(H58F}|SxKLy`WmL[vf&G{>J*%\\eB# bXZ3q dCxV7^L4iysAEg0 %BCH,s gd ew )@3   _ L  ]     4 R   - z OY=H7?R }3&h{^< Cdir}F;n X5YUACY&g;9ol%>t}n 9[jX  }  t VR 6l >ils-F/-Sl 1 azd1 =}vtLBV <@  F} K  j  2 n  z o C  ]  Z Q")/pgXd<TLx$Z JDuG 'f]PQL8Mj)TG,a',#4 k 74 9`RO?0#0/'W"M5%EWDi0>w K ~ pK#    B Ai &  WKN9!wyxCqko$H0fxGvme+]Dw4kD"Qg@ 6%*P ? [7 _#\um>t0#W^=krVf'EPZThQ '   #tfyO D $ F c K X|h9e;48K^g|?jj~jRhH ]jL Qe)2 (|!xv /I [a - R +aphhuu/G!8\MUF{E*[O2stA<E  ~F A " ! !    eV ( "-    VjYOl.dJivo ;Lbw r*W'%b* o  AE3@ 7 'qli1Ib*&xInv #o&#*zx}%.A   < h(61|%/f"\ ` o] *`0rW1tV~&m?rDx X] D    OPr9m"@ moe(Pr 3 $ / %.p?J?4uHuRe9 H 4* : Z{bV)j#yaQUL[qrJO`tK7_Oi~]vN5DIO,/AF}kK Am :nK!)fA]IniV80@Scff`ZoG%, CCL[I~ilH2s\C,!^khz^@o}saxkHcz~spM+v`Zr rv)- {^B: 8v,POASn8*4F ^0,F=p1jY*:jvkkIjIZoq#LSaWq7i:?k3=HHn$;$v X@@}H[P@ixF82kqJ4++@C9\+KWJ !Q-~+Pf`IqW=WzgZ[4!!B*v4Z$!@ ou9g 4SP[gyr[xrk9HbqaSouuJi `WrWTZQ8;h^Jo1@C$kS;P8gW+- Vx`k7`h",ZBvk $ P?aWSVgPO8H xVSP* '<(9 ?rg+{zXSZSP*;<4WiObnPOVH(F(9$$0r '*3FHA\Rnn`ZLSDFoW'L*B +u ${Sx($k(oC? 9VB9J2Ja1 8 # ySquK+ho-'"A,?n~yK~*aHn=HA\R,?)RR0,0;Y`KI-, '#=Iu`nnrauo8cP8j04-K^PSIC8gL;qL(Rg  Wxhn+2< '8jF8 "*Bg-- vWq aIV YOcoFjgu\I7HLh Y4 88;0 %3O -hcjgH {0 ~ScyHhZRc`hrSq2(7'nSqzirhag[hQ@9H9[XB(I7x$}z h(;4BPz@!khryrVY;vZohxL#'*Zx?cW`goo\Vhoj#*$(2-`?$`4H*b-4WbuJe0XJIknngaiuC1(H'QJ91H9JZ^[`Lk F!9LJO1 X(  # '#B ' A'*oun77chkuojf BZ9Ohz@W@8B#  ?IL^$ nFV ({qruzP yaY#u,YLcujxu knox!u!+0L O( P?'2nrP`oZ7W<I0qu<o^a<Px*0!}+i$L'kaBX?B W !?4'-'{uhPnuf7c`8= cK4,3%P Lf\`I3A1'7,,HAA LI:7kjnD3Or'Z HWruj^DY{OyS#q*VnP2$I$$SPXx`H1}(k *H!$ L(XBauuH+`1?$17O 7H ' *{voZ0-ILS Qa4buu z8( 7 9FSi2bJooabx}Og^x}qxoaeg<n+JF'x4+0P[2r(;^y@aIO79O<PZ[VOVVuQ*n!7 - kJ@Q11B4IFL#7[qS 4b$n n@W= Z-JFi+Sg8   VKII44\IO=PuDLc:RDYP`7Ov\fkvo^qa87%-Y%o* xD:aAuaS7" 8Z :LS R)c;B4 LyD`Hx9$ $e<9-2$Z B??*(-Qn*7I!Fyv^k$S`}^7Z9#$??XVZL^Z--  2cnPB=YF,`aPjj0r"DVHa*fH,td|~~- =WqFA8F=rjV`o=WyK4u ;D-A@'7: ^v` 11[Wx[8iy?HLniuhOZZ(Vy*oo ua#u-HQV}<2Fb4F1r2J7PL7''<1H S4k0bI' nSi1kZke1^FO(B9 $7gvq(}2IhgybHq+eP^J2yv(BH*W8 +vHO7Z*unC`uaeVih5B[@n(X LaV$rY 3K)A P?1j*`7vhcS;<@$LIT$bh=BP913bGTfvc_$GPz9sy~wsZ2 CS; in1!+!`X$O^~OB J1XvI0Q?; !!WX7;8 2 Ivg?VzL#$^$hW;xq~  P7\*{1SP-DVh- +-CH!a-e+SeIZ9`bO -I+aV9(!-H`q~Kck?qB{;RRfF?*'" 0-"Z~RW OO8aH?K;qgZ ;L"0BArRho`) D"r{`jnH%)gPv1,h~YP^u'hSaY^{'o)h08A='K1 `1,W7,4OqaSPYByq 4e<1*LB #*(8I-L< !JF7L#V!ah*($ $-kvn<'^+QBrV0!HO$CV8$g1r'8<L97B ?4?'~4BqiLVr+e+y1}'y h*}uS+QqI@h9u i'i'ee0(ngvQ}irX$`@#2$9 O0VO 2+L;X*+#VxIiL ;g 2(~ +( #(0CIH[ 2a<zLu<$'^oxCyBn^[@o}zZ!HW[ZgnrFie HC@1*74H70 ;+*!q{vAhB^ySo82C!;Lv"n1y'R0;ZaS*33Rr0#-Q4QI#7* ' 'y~qRxfRngxKRAy^xunA{DfnKhL^nnyj\xkLHjyK`\LcSgn{av;{QX;7[J `k^WoO}hor( ix0SJ4#;;(g@-<h$;` BV2C$ #qg`ZoS`jjhLgB`"O{{\?L-#,P=I1n;cqhq:g0A~YjgyF0*+-7C e+VICH`O+@L44@FL`?7a+7Sk(7uakH;;S S<'8LHQQZbe@Iie*<I!}'o@@oV4 <4(2 ;XzvP~Lcc$ZCb!k gB @k7nL!*!'F-90ie C1!{D @!q a0Dpg[jnzd]g;GZY8_PXaZ::3=K8=c@ G Y% dH# `\K1`{Z [x[-L7+2Wih/>xG"<f@Ml_3&R7==Bnd)q%@,V:Cc\aU m,obU>fJ2\(z0zx0;~:~^P7YxQmE:W05P@C O":AXjc*Jv2S: )/\xVO=N:pH~{=u^LnxZ\` Q;^ Py^?97`xVOPC P92{8a2o7O7% 2JFVi+H7<J'<!&(Am3a zqZW ?9F+<@ Poqhg(nB^Wklr%y~7TXby\C BXrSvXZqf 7!@VCG( yMM 8G)25yc/unK$!2Cva0!#I;}^"zc\l;DtsjvO2BHO:H87! i/%j(8SG fBy-#1`'{vPYWI6H4r=aNsWfY>rgkos;cb9dX_GUKh=1G,; (PV)JhI;$4teuK7E<*FaBP"A Yfo<+\QAZr;unoA$&U&gx@klcB4*1<4.4w   HQR[J,7D_yiVSA;W P,_X,^hZ]$F2L^KynC31Z5AkE\>_Gri3rDs,B[7/# h- rk:U_%Q9AUH0O=A$EyK"`_DO$Syz~;]'*z%Pso`A/aokmyyMWvn:VzS!S}x`=B B\'Td)f.]-4'GPOMP.n?z@}6M v[0Gk~?80]dQtl]v~"&O7njVY?eS^ZYyiWo4-8Glk@S|fNQykoQ:6h~ 4&J97Yj=8yu C ( ; BDwTozw"h3ZZM2>Q'eJF+.x7x cQ$ & 8%)@r A3L0:#v^o]@IF<*Lyex"/pi#r@cO<*a:5_`X,0/m%WWD`=Zs0S^o89QbJRclaoS=KTW]FtZ8p$R1rw%MHO +9+wC_kXeAzK B C@S<B@GrkXlW\2 {Z#h:K9ffc0j~S%V{^': 1b=-#Siq9t_R "0 9$II+^hIBVIoagQ0Hqp>6 NdK_ipjW9nuo!O GC[U<`3\ xB WQ2+A?W/ Xn3)^:'w5,A|8Zf;^FqA[An7Pke >wnpv}iyv /@'$;a2 U6>dEw)O_(w)\3ss, 87;K_|0h;rqk}"r.-:!fy0vYL%#br5qjYiF@0"u   Q#f`w_BQQBX"xY[yt?43p`^'V? =kMW15yS?JF*+Q@jVL71;5z<x)v-8RG*2C95U=2;ig?S|4 2I~R4%La`<9rEkaS0A`VKZgrODBj^nY.y"}o@g@/uHh`&\3Pq/$^R"mXV  B u. #X 7k &q 5<h<enzgGjYDw[:d U/Ob ;{nvsM#*!%J$B5( a}VOHKq >i -sO@hb&!)<LxJ[C \,v ] IRn49 D .iHXB`_+Kg#pA mrMOO)"t 1 :  kX=0Puz7vIWy{8lED.RI TPj?OI7_#LXvZvMn[W{4XA3VZOH L F = Z nO &x3$ZcGr9Cio$xl*!Yb#, GT h'3#z{78ijK>eW~m   n /1Hk2<J}u~{I  -/a#W)&a~nc[(P0:y_6qd(>GDfw M i | 3aoY72Z"+$=K(Q[ QQ_T)"ikx8 ][~YrJ+nOn WD=B!*' o F ) C '  @ #S+cX+KHCj<Hc\&<[bh"bjSezQC5&&V^r(y,~n(E /9D`C-Jhda\:%WR'v2 $8r9DC EWsaTLAZ 4g>{WGo1^T 3g#O@I);bqI;(DD{<=eP+# tgQ;xZ (RRYdwuO>7'5?FseaYPeoG ID6fat+Cd>z,u^2Ak t2@ob![5D-Da.G\xu1LM:vRV8/pQ+ Nn #,\## fo&/6Vt8#bV$ODk++Wx8 XZ4inx=zLIoI2'2A0CHC -V+F(e#1>:2@i'DF~P4Y<LOyyqz4Xan +.@1" !2"2[r vo5 qvn@oQ^iF b[abX8*VB-!2? $$(8C1< bL#71\qx{k~^qFg7?bb22*~y(O@yW-@I+a$nZP`Sja!48*y 2*Xg;n@bbxCh^@qxSqiboxoC[hg}QVOSQPx[hZ^V1^2('1L[OXiQgZ`* CP#8' 702$$8W$;-+P Cvv1Zk`KkncgDYaVKoS^qqg hrvoa-7 \nunu# '!y{xfIRFO;#1 1c\Rk-{?8?4K 4kvVa3R^( {4I{Y?S7uV`A=7KcgOn?DIF01~vh:~P=u#hAokqo:kVyhKchy L(P-'Q9VFW@!(*e^r?C Z^ L4o+yBB09`*i - QOvL ^y'V$ +7hnx  Z~+'(Q9[O4*L -2(a@ZZ8hkzbgoPe'Za}S[^}![FauS;2a}bk7Q^ !-h7(~cqx ya;2 '$-@@Zvu$e4}!LIiJgZ4+^<0VOhvbv`r[WFhhXWqhr`x}ghHP;i<?B<rgg a ar[F}u[WQ0PkPS*QS;a QIgi@++22k H^xoiS[HIzHu$1J1+IFB?S 02V4yuz[nxuzxI`nybz'S7(<$++B5%M(r79#[LCV+v}2Z"kX4x#H!' Lv2^W`S$-k4[Z WC4=7oa-#z}D? L0FgoJC^ * {hxFb8-v<F?@Q0[VZ;1?c7004SX vxqafkLKv'H;% 1 :40=f~nv*?k \vO*vW8Zaf7`q4n*JW9 -*o,VO2P),vhvS9V(xYyySBXk`u7zOko?}+ 0ihy (!=3l}qr*JP`; ^+}J^I`9'C^o`-Og!!01 027*(n4WvzO#FW8G@ ! Vv#;CZ h%x yS -Wuk9guqgL< WO:S1<FSr*rRj0Ly\yF3u"c~%WS#B-u X+$*BaBOx@u*#[^7 4O4+Zv4iZ<r-1*e B+vj:PjO\v"{-\c aZn\unjo1o= DRyI{#xv*yx qZ ,uhcSvI9 XSkZHHD?3x#># j{IIV*aMU<^^-)ukjnq H~N&h9$%4"BZ`Ko/^3%(X\SA.:hO_|R-9shWG{-j5T#fRA]0m~pT _Xs)$&a3JD>Wq(}Ziq`j"`S;@W<J 4wE . a   < R l  G`u.ppm'f"|UlSrkJ~k6v C'-{1#K=@W1I'#RFv'N*W0);hYh!r &qOi`)0Z]f !?mPWeQTX (l$1g'dMUzUOCXYJ~%3GRz**_`D7b^c=>eXc Z2<-=Q-YM8"';?.;`K5w#~o5):ahH/w]iZ!_%mu,LQB3;zZ 1@Pi;M;rF(C%DaW$+2+H9WIz`'0A3b0d0_>qxQ.h)9m!T_oLT.."i!3`}/e=wt"Au)%L \cYL']_;KO Ou8J<9M.@G,5=.%$[kCw*"J<wkk_Mo\IB.wIXMC<q k9Fb[rz(-; 'q1"kDDoj;uW%3~oAyWHSDHk11S- DVAV- F`hRKcS02OvngFQ#Qk;?+1V^kv L;PhB8O$Pr;;ayonhJJvy7QiWC giI'okayu= ,!$@r[Ik?8SZonyeY48L#A7x4*W-$eorC1S'y}Jw G  )   SFwxNd8@2,CG#."S1}-&%7,Epi : `jF~_q6$6kuT I*$Z8K@IErLx@-]0&<);c;r/1< s<^1$Mr_Lz,F  ep9YHEbqD95 ZowgH4_rJ2+_Ku VN~VE+tCODP{*)#KB Q.D@wWZ{_M1C3BJ($IK"^Q05;@,Ik}gS'hbo+`  X8Q1oBT" i1Wx+yi nur1;!08 HOa" 38MD8_.z.@y_pZzG93=frlhwz28hJGWkc(woQ@CVaKh(+  W;y<D IFVIvkz@?WXa7(r,YZVcvqkD:)#?00"4yn{q'?,nAouBh;OLxryvKaJA#7+gvkhaIL uV4YVaOF4Hei C;C!22*( n0V $VL?e QC2$4iuWa^1'( n?F+4;<90F8v$H8c`hk\~Wv{ Yq V*farr^8"78*Sb'DrF1P(o I`gLr=Savk~{jD3-F8nBoL{B~RhWy1:o^^@Za7nOH#c?v?4P!7!k 1ySr$ **<@*0* BQ$!?B7@ oH`oBIK;Zr\^{Acf1F:SA3 Lv0^{ ~ruf17H0 ZjD"Oh'?A8Fuqa%*=fchyh0 1S?fv*Ij8c!Lxq?$<+[ j1bB1L[^[^n[S$#r@C vk4jrf;`{v7o7)8oWyH{nOP:) ,0y~nnaR: YkH~O{) yS`8! oHa-`I7koV-#@ J< WvvJr7i8FLZ@ #!+^(W * ;Bg$ + - gV-C 9Wqn$1$ 9v8J7XQ'B7Q^+i$xqx@<<kgXahvh74-< iWZB0n2Q' aQ0 V1'ygaP~~VK`{O1Kq4r~ f\g{k7vqZ`"W^n 8e#HihPyOSnxPkJn?X+I yz'[akvW8*kHW@oH'+HI?Fv`aur (9b 2{ VOScZ~^YYYg-AWZW#WBL\W=?q*v\)')RjVj!<;*Yqrc<8Z^?P0WhQ9R2099+<` @#Ho+@+rhyv oWvfn'RO{=*P\R{hrrIS^{\hVr8Y:ZrhB{^;2HW'qF;Q*n H4  Znqvz2 gv$+=%1"+1(\2iS<F}g Hi*V(xJ@P*ozOrhfXiihIOhH``kBYcjVhSW O LLgyY{qDa KfH#Zu0,WPjo 8 8o}P2nQZ H+J9^zu'Z4?kSarIo'*gi4-Jy 0J7+I S `x-?zSRDW^kQIJ*O7`K=O\`Hj~\R{Y08 g V+ h\17 L#n#Bn(;2ei287[BZ*Bqk*(PCooy^2-F-u7 `g!!I10x' - n2ufR\#ao{vkOWyk=74VODc <ViQ2 8?! C1H' L  {rckZx0Z%q,A?0HOHWjztFyVn OV);7hH1urnDY" ,'YKvrYn=oDIgBfOu9F*@Z8$VDq`f(AY=BOKW:n1rn#FaP4SW -H^Z3qK o{4L4aS#'^`#roL `BCK{'+?^oZaOv 4(L} bL2aa(L{eO 9H5o}Z !XP,[`, xVS`VySyFFVA^9-x=6>'nzu]e:t*~5uO|gzna,]9+MKwO!xNQCQD}EET)#h|)9QkWyM?#<]A1-yD0b<v+0ViA8j]j.F+<`8gCp#q .hWb.BTT49qC {u=fO'"uF`lwzny-/-od6ZtTWm_o?b^/XI)?EF!eRgssTvL1=*!\A]Fw\P4:IZZu51<3J *(&mB;-w%K%,{~NCT:!s~s*#]U odQrTJsO>d9qw~7!=]05\Gt2M>}&E*pk?d3H#tPy;^I1kukO9dn{=~[_Mp}7@tPHG+"h1JGukY_Pno0K9wOCg@=TN[Hr Wd@R@xL!A)G]Q,z:gU,h cdiDiL)\3`q Y]s@|=aO3%8 O2O%aYa|7k?COqV%2F;9~#QUv!R^e:Xjz0F-lG7oG-m ~;g'-XI,G{k$|W3GgO~AH(iRyv;-t'vW9PTY,CSN7/Z~j[d7$H %C\{]f :d1nB 5Q fE!?"mN~R!X88?U}!,gMNwNJ.y|ftZc'wABJan@xQFiK5sdNJdi.TY>l {R]gN`axr{4:;6i" /lzAe8QAV3'E0tPkIy+i'%)K/\22Z9hCec~t998/CzX"-2._jUp 9 T 9t:f:R`xMOKjy1DePH ~p&?/hYbmcC9eb;& 4< g$yw82LwB6JnGpt?Ep1G "<>g $L'B0-qm;VY>m,L=4@<YXZ4 Kv"s_!e}V aie+ %W0 znSdo*swyFi9DkDWxrB@*SKF~RW t `7ui|`Ca ijL_YJQ p~]_0]#:Q9>uQtjz_C/=#-niq/:j((dwG|zI;h h7RKY;~[ BQ ??F8*L4@Xehn1 rB@D2!e,;CP(b*2+3K{(cyyouoYoJ"Nyy+z5D}!(+rE2} "[!.C|!g7h e/{\m "0\1Y{\MOsgcttJDDoD+`?hS7<?Sob S6{ '-> Gnv^'D/D-Xc-'kD83JIhxPr@B13D8B(9[B83WEv9z]hRSK55{K>9v1ToB$p<x@r!ra@!$? *b(0 WOZ-F7{;;P`1 hq8?!D(P7   $#-BIrq(\fMB8OD9o [< PW<lnsi;9niRy*C0L+?xjP6Z@y)K |&iUk)j]g.*b#C[Vko&!.QV?I3=@GYG/_;So$joxZn1*['Jgj![! PJ](F {DXU [])N c O 8cu[5}K?`co(82c'pI GX[ :YA+FR_;$:v"/3M\LPvOa,yB<s<i`,[^HU.I[~>?_L Q{.jg,`uf4g<XXwSX;ZB%{9L*g;'!2[q UtvAQI}dq:'C66YezZI2<^JiHuW6U)<1~jy_31 3[b71L$ ? h C   }0Co H)<,0f9y .Y9RHWI^}iyr7#a"{0II?Y#pvP4S pl|juluYFWH LcJDB 9+XKJTTo1~kBL`voI(1(1IS(?l{5a<y@oprkW3n}zJeeP8[? (81 ^BqkCzg @ZQrabv<B11 1? F<V;Xb!XSI1'C8(z4XC qfYck:8SoYh"=7I AZS-1:jRcZ0f'`-n,cP =H X|GqfPd `g `0 g`V6z; z%) n=gFgy~k^1S488\"HBu{ufVa\ZDyhyv{AH < * $<11-9+!(2?ZiPnOqgVOSPk^`kS4+Z[F0a y8-00C1OP*auXr0R ;x#PA4{R\-\7^RVHA?`gBo??aha{kLK7"^4Vq`;#48xZWoP9 0Qg`L*b @SQ;;!'uW*-' #%9#!?E)vSoh-e{'Tz@E'FMvJA=i1Y;82` ]jg2NRy`.,f+YXx,{/0SuZRSK Tmq<J)$Kw'SKS%}X;(P5|Glx5Wz}?6wOhyu.1~ld=yrz?@Hzq}f#; CWiP2B8/:ZD+0m;UT>LCgPm+,/5_:\= DD$Rq x@f&P['ye;Y U"m)6~e1Vl~ p}o bO?fW}Y c1(O:G ">Kr:>$&el40=jq(PW<,2f]MFR|k$/sjp M{DL@:0ZEZ J#MO,s[sXHNY~C%B$+`9iSp\N<%lmq-nd_m%c ^h@wIqhl$rO ihA9c/2 )[; ]F&]HiOD 8i\5v~YVhFF[-:Mzj* q,C1Hp[5Nc]V%k7nH %2x6 -h"A =O K9fh^17 < Vlu. @ WPUwi) xD>'ZU+zz1g~/IEu>pt$u3+3{r22b1nXrCkZ$ZHK)*uQq kn uirur?#$<gb a{u(S GO)F faRGXG- G2V^ tE{1_N$s V+o7%mcN8UB6$eO5BS,- BC;t(&*iRxq wcpt_UQDp@~"="5RsRss,#;o2as)f=D9%,WzKp995zzx[W\\ZaFiN]xEER[#Q f>Q 7A3;QJ:HUA*YG !#gVt?*!|O_+l/a~9+xN/smzMD;y|}Nru)]T[4E]bEx>T)ZKSrJ7$2<%(6c0'L< !vlgPvoR18 q1X#6q&rP V o0re *'\M\K 26X%"eE]#5-4 Jq* T<WaMa@71u<_ 9[EWm]Qql[6p ial:>Vj{j%Fgz(F^ WG\j,X_x'BF9iDI qx:1oV7 v$8iVKlJ]HN{-ZW+h!{[$<{v+>Ls:J>`9oK#w@T:;|&[K h{ioUm]0 plW}^NoLQz;vi\/z2B=`$KBZz!&zldu1o{_v~B2m#"xj'H~}"L }v{Rp>a"$"J^<jXT;7tg*pz~3~ JQ$)8IsY{9L4b_i=X1pd)Y-RYc60SVCi/}w@RB+Nd 6W+~-|2OG^92V~80:P`fp{>Z2(~M@#C.0k-n>+Y/U72Fwiy&t,%U)o7/x>zPM$]? iiwV^p>hkK- r^/(xV;I='yyqKvD0}4WIz 9 #bOjBg$#xkz"A+$fZo/,iFP^7:X3 rJVK1rv>o!}+K\n,IP-^n hHbh 15StBEOF{C#{a@+h5v5=(ih\^v@L7qC;d'x--4jD,11  ?:D\F^<QPSjzu^bPniSfn^q x(X@ Q#eo vgbe-aZVb?^JirZua^!9<^BV2@r)+Aw =FRpqqhcOS_2c(DA_-PqP 0%11RW^nVYDaPy1 DKOr`cWZHoDcqWvPFq`{n\B:LF"1%A:RLV|\:mqjngtx'V8~vu{HuO{{qB4LHy=VYA ,?F;cc 7-WHHh4^qfuIOgAn4h=YLSZk-{^B4JL9C$iHWZikk1FvkbXZvCu?nxnJh[e^X0P}nv?PCgy;PP k zLo[[n8+*#+ea7WCBX;[$4hZga`ha<eS o;uoO49WhILkZq?oZ<742!!@WWr F aSZe;BF`?[*h'!`?OFSiv+#*1<2HX@uX#`O8$ 7(VZ!i @#O17'`Fr   !< .22DZZp~XSXZ1bBDvzhw=so~hyp{iyzPlG@;C$(KI zrz*Z8 i8rx8v4VC7 <H$ie^^n9X4I<<7!7r{L(-qXV!P7a94-;-'8[#'*  zFX?b8H7O!<92FJ!chKcrL=FI0'HH)LF' %) FK B,34,7 *;; F"Pg:O)IH *R#W \=?~^o0?{-$`FK^quIfSAY4P\v0P0H# ux{r;vh#{koB^RV = 8OZ3afR)"#**:y Y:qV-%#fVPrA:HL#P!1=W 7447$  *-*';0I2-'-<7'* -'$*2 #(FJLOFSk[vuFhnu(i0}Jn8gSyhzez;,(1.(lPC,C8! ; vvy8X?q?99!@?Znab``}BZIqQ;@0 *r 9$-'1 [Bo9P4<1`( #?(zy;--# L( 2Cukr.2yex}vVggaHhV9* {FKy*~\HB=;1`#W'0'=fLY#oDZ*;'PA1`FFAF h {-POWAZx^'FuuI h #814Q<  $$+(!j{c;LkkjP8-HP3S:A1jY*Yx~n,3\*h),YF^S~Ik):Z'#H3;?4)'3I-7K3Hu**W#x(V`V48K;xn '\r*ohZng~cLjYg{ya?#<ZFR+i5$ =@I {i5#fOaZD,uvrZIs^7OB1W$`Q^*C2nFF[ZgV0!4@^2nC ( x-#?B(eC #^1O;@^!-;Z+<Z` * g-knFk(LXaxPZ-q18!O+82`+rH[znIHZ8-gi$8ghe;h9zJyS`H<eI7J# VF b* R+q nqh 'H!!*1(;#4+'-8kOS;PbZ`by qiuqukyxIvJWJvXgCyQh4 L8oPoZrgvB? ynIhL1RL0{gP"=,YPn3,P 07,OK"n)7:8 ^ :%18'VgDh#hg:BL`jnkrHx*79I87# !CC989! HX(I $;8O'[B 2B['V219 !yafR#1Ii\nWn%n` X gf3hz"R# zBJh|A O+h'-z\v ;7{+u^d GQ[mJ^h~\E *|5y%UD+wo=A1CPFE-AC4o P}PDOH70J?(HJyi`O?`` hy$faz(a 1P7q*@0*- a7!}4P$$@ F'-+q'!S -'g<k@o[  P 4$0*1<JhWOeJg94H-LSXQh?;[+S-F`XX;be@-9@`qCe1*'-yk8!0LaO?x{Sj-o\0WLQ;HI?iC$7O@?B72vHbC'zZ^V7'PriP'v7S<(012ZyWIC*PZu$y-XH8SVba-8@94 C*' !F SZ@19$<y7e F(*k8b xx+a*qP+#; 4$@'O*!2[OI(V*( 0( ICI!0QLa (+FC'o!++V$ 2 92#44!(J#rg^grjqx?^nVnungx7nYPgquhy;7r$811 F(`Z B+ -ShSyB~0rY:gL\~1y:f,7r3Pf037 ,##D# 4,0* :7HIL=y3?Dr^y^S8Ar7V ou;y&8** E. &>T928;.0Hd`n9H7PT1]7PM}#}QQP!XeOI'(]?X5; &Hi20.5B0* !*8 cqZHqgkV\qfxY Pa@k}'4OT 8!7-e 1!?!e0OH*M'$&V!5-$d [ o9b[aWk-<Z?E8V7 ' 1*!.5H` !F ry-(   $&Z.C@}<Q #oX]reQl iB8 &OVCHWeP?]M]sXkTxO}Zvhag@99&8SJ[?^1QzJT9h9++   '(#7 H&58 (8 5   $(R`Z{~dr`cgkcVjyt{{fhHgBqV.#!20+ &1#L0!HC<<*@C@F ''+ 880OL> ugwrYEX/+JG[E;f1 D+Osl+W[a ~MaLh!$0@^'9>I}F>  +? 2@7< BEC1$#! 4(  !.0#0 *! +8*.72$;0S17!8 B!85.(< 0+(&0$<21!!!!{jxqk|hgr|guv~v~x~^qj]ahYZY`\fS`jf^jWnuuyymvcok`x||tovm;2rmPvstjeo|~W[qy5; eFE&-+QJ2'52 19#2 #                               pyo/examples/snds/snd_2.aif0000644000175000017500000003272612652732202015143 0ustar tiagotiagoFORM5AIFFCOMM@DSSND52*~GOR4U"synZn]_:R`4!q ~AP>DJG#:N_.UubmHf?(cI[;GD[kWz*$vaB])~yvcP= w0EPzz)Rw\-nTws5F0_RZ-q 'lZ&%oK;?;c@H3BUj/rCB y8RV8Y/nyN=UF  ?= V (9 hQp  '<e@l.0mQEU^v`;B$|b[W{5h dS>Tq~T8BNM^^2 LD.vcnQ9 EOo#4|P xN!4&' Q/yKpA^Qu(QWJZ$|_#[E< rL}88-!& 7@8S3Bct p*W,YC a/{7  5 0-Ou8_8)3px PGR?61DeE<p$[ sLF%*Wvo^b'?,MaTm# 4]/F|, -$ ZU28G2$OHbJX[ +$.ZYD:TLdS;3d, \ELU  6=T\    G1F=y ` + n , ~VoQ'TT4R#\{ nbu4V CTK  }$J / Q9SN j NtHw6FLCBb] T oH% ^o+tkTf  #DBZ 6zR 8 3)C NCd* .|k]X4 w Y+n3 s3 5hC`r^ wMu\jx>H'0 @N+)8R MNj'2 3l  SO f6R WBg` #(} O(3W /ZZBiF  BdwL) ^5\w" c4 d JCQ  u\w|- ; q ) EJ=wFu  ,I& ;/G T < # %K \#3tg uQCx2~ e ;dI1'mnvl m7!ZDK "mH6TT%uX Tc z "zzpT pw[I9 b5K| }Q lO`|pS2Rl7~q#.Vn $R)e\[]YMS^6wuTL l-7jygIT %N ' _%{7Bu%@2^S^oRU oOjz5XI  .B `:RYIykkby1\S*Iv `YM6O.+nS3j&9S"[I{V $.es` 8 9k1<R"zDn B>  K? Z{s0  yHJO2I\X>S$_/K: $ Y  bw8yd ?? V5 }W83%gO %cAaruZgf42 B ~h .ueizH  -yb S?# ~) !CG-J ^+ c ;.2Gd /,W R,8J+ ?DC2 b+@ u ?=].,1Rx ~jwE"7+ |;G R}-@ ror>& s$ V p,n Q xM? k Bi saiu !r'_JcP NXXz?u\ =(Kt,4%E[b?7Pz:Ro+ mxg86:X& I# / ~aq UkV ;I*c J m2_jL | t -VF c"l I kE$ F @u`\m.]>!I %:{aQ g =v2dm &wuJmKiX e " B85U| u 3EJI g*?#  UN |!Q-h g d  Dy) ,A WcpZ, x>$h DM}WY !X3% qH Cg3 he G,,  @A  `Ezx l  q/  X7OJ'dT^E 'bUi|^4u P w]p ET t^WptPDW=j <"AO &Un ,.R 3dj *aR` {J0Nn 3 f'; PMcPw[ nvK R| / BuR $8 'MHG RSd:X# nXjN ? X ';Tf>-E@*w ci`uZ  & \ h ub@i } 7BnT 9 4Y sH;r$D SQ T0-P x 0> u~ + y _=n vrzxL cD~ kG~![ki 'V }, NA= \  o 0 +n=QDuR #s  IQ J'iSw'{ Dx<(c=`fr .t[H*Przft/%P gNS"!*w4LN< M}l#R.  ]D? ;hv  -T6K sV52 n .(T\ pP;%\ l_ (!=&% qY! P"K2n*gp }dgzI~X+Su o6BZa e   ~ko. Cq = xk4 P5A2G; G 6~( |9<]n~]$jp n m\]l: Lw IV@aI2Q8u ^NU "mcZr K).<[v 3Rv n>jNgjX  YKyG| ah{QL ! FSO ]m@u [ >Zo Iu 2S M}>T=o+p t - ZL2=o> N | \Q6  (,aE$} vY%3 ];" d(:<@9[S u l ; C7E}k|` +V"* _;W nR,lf G| |f@^SFB -F(+o /)\ @1e` VviCo(\h ],_8\ 2_lQ/N [!B B 6=]agmd/3#{  j* =, o @I m!h# KJ !,]% $/|LRg78l> )(cV H |+ dnI RC.+ IQTE^ - _Ja5} - 7b ij>GSl,P co{ 1W[% d] b,ZZ vR 7L}+T >@,Am`hai Pp4 ]16d>?4@MlZ@<(-kd` @  ,7<Sx 2gN 9>{|= O];lxc UeK vzI5F{Xf{ < G> ;NS &=d&*O YT'Y #-3sb vT7 dVbn1ew  `d XFP 3`NM f>$M4rXiS[ Mms 1] <1 w-k fsViGZeL^[O pTe2 5AOUU]jiS~5&SxejiGl8jvy9uw~1k(q2)Uy;%1yir1XUo"}EWH) 'T;"4"`WJ Te'F  F?DsF {4x#kA>pnjqnXqsK[LaV!M i+qUo=|L_{f                  pyo/examples/snds/flute.aif0000644000175000017500000165566212652732202015270 0ustar tiagotiagoFORM[AIFFCOMM@DAPPLAMIIprivpbcr?SSND[b              9 M+ol*S;27gcY8Idnkn|~) 8KK33A%%-?aounnraa"@2cl .c}Q <_brlKQ9$\AdK; lp#Q| 0#1Pt?C@MdWL?'C<(#9@rzN/'Jc}z$BaqQoT- q>R''-rLu5dkTBL #;[8`\o$QZJ!m:6?0BN&{_g8Sd~by0X .92 7utDrWW[[t?jAKaR.:dkhtU |SNi>_8IRRZFK|1_sX r"8kO?Ifdhu 7 ![kS5r> SkfK_\=RI n0V ,.6ki'"=h<-&XXJFV]=,(}b<387iTC8Um(XU G2pzIJsoCr4D\KRcsh2Cep}vzja$ 45f,6TtZr :moB.$(.Bp?34ot:d EOPb\ 1e}nH] \c9*5C?<NQP2 us![;.9W5\ 0_vnQ)"]  }^1V\5c'[q^/1MkwZFBIQ^Pp"g+G1>}^*gE,j> J*X dvW<41:1C!f?siKf8s4\ D_.U`RA~MzJR4gz+O(1%h67&  Y@fC'D3(ao X3Sn`NO`P feP6a+IeS<j  /Gi\p 48gW3JYyA-%La{^iaPo'G,Ym{bDm<rO7I !L v8o$9yJ9m71F.'v&f\ k* ( e S .   I)4?;K#n&dPK VEn V- N*z3#p^@o e % W m  R ;~m 7gqh0y3jUg' OS]UA %  $ d w @ 8 h  u [ &hKRMkYsaA0GE Cy*[D F{ph^9:P  # r h 7 6 >  I } k , { d8h+7z; ,!-w%UPICl@G ? h w \ <  $jXx/  U xFz{Vj l8dA[J#cYp3"(!  3  x v t )S %  x =;lL O+c~Rz9H#9lVr NH\6yjlN7M / % &  k ] X389t aR{ {J/(5gR[UU*0ل]׮N1x?Doմ) fJd?y|:sԯݾ\a2*P4S {MHGx G"$&j(d*,.01X233H3k3332U1~0y.,*(E%"t)[ it?x7ܢOϟ˞.޾gXwѱԇݟmn; y HeUk|!$&8(m*,.0$124 555555k432[0.,X)&# )  6za :͇ BQھv< OД#סC^p,? U0!b$Q&)+j-/1~34456789/9b9?8865M31/+(5$1%[ {0+SKm֚Ѻ*M)}~ƻÙZlOӃQۍ)o A! &h!$'`),.V0i2G4 5~68e9:;*?R@D@@E?><951-R($ ao E 2.Vθc^ɲ̳bw?Mk~d98o K Wg P!#0%+'Y),/B247:N:623-{(#1p qS m//KaÈ?豾ʲcb = 8 Ljm{ #'h*-1w5L9F<@/BEGIIJ+JHFCR?;73]/*&!p\ :qg!OΆ <<ݵ5󰳱 Cq}ON .F: U O Rf"'0+/37<0@CCFLHJ'KKZK p8xlд֤H>  O*  !&3+0V5l9>JBSEHJLMNO^OM4JGC>95<08*%M K 'ցI%Ź Ѳ󱜲0Vھ-,*E;l"t5Z! _Q9!9&j+x05;/@0DKGJMUO1PRPPOMJFB>83.)(#z8P&˘ư1Ѻ>KNCv༗ov_ڿN,j8SKf?TW '!'-I28:=BFJWMQ RSSRPMqIEA~ @]#)/5;AqF'J.MPSFThT=SHQOKHMD?}:94].E(!z WA~_[|L˽'"ݶ 溰ؿ!Ăǟ3PEo%1j %,y39!?DLHLTORHSTTRPMIE@;6H0*$t!)سӃuɜcƾT>!f@@ƽɴFtR'>c8@\NV!(/6i82,&)auF $"X9'[4d3˗-݄tQM%LVOq<T O$_&"-j4^; AuG!KP!SuUVVUSPMHD#?.94O.u([!n ZQZغk0Hཉ/ sw9*#Fo>ވ`w%V$|!6}&I@$++29@%F$KiOS*UmVVVTBQNJeE@_:4.X'  0ڧѩͷɒůŸ#8B¼VϺ>){L[j93ia_ 5")07>hD[I|MQTV VViTQNhJF2@;n501)"55>to.YdƤxܽ3rğbQMjG7XJl  (0A7O>D`IMQjTzVWWURO5K FBL=<71+$R D ؀ʗ"&kʾѿ<†rɜІؚރPHoHY='{kQgX'.6?=jCIN|RdU,VWWhVSPLHTC_>8S20+e$e Q](Q8ݑh(/Ub%Ñ2H}gTgev-dz;EA H%-J5sEJNQTWUVW-VTPLHBr<5/](!!j^`JڀS6e77QkƩ8UѴ@- #P<}ߴqOܔ޴]G m%.&5{-02H&נ׼ۉ)GnxdK%-I5^18^2^, %K23 V2,!G͓9űƖ@r 7f*  8 j&޸u'7Ւ;=&Y/ 7 >EKPWT%W.YYWVuT8PGKGC>h872",&dP/Z^ԘLHIJŕƿDf!VMq @ Jz.}Ԅ2bծdpPo%.7|?^FKvOSTUWdXXW#SPJLHfC'> 82+D# ܔң.9OmN2 _ހcz /ZgHn5CҵԀXv }%-6?(F KPeTVXFYYWPSOKGJC>93,M$J YY2Z1=%DʧŶĪz$͖PKe% S q ,c߿ׯ/EN֤ڝQ x- %/8U?FMQ+SVwXYWUSPWKF7AW=h8O1*j#i< =&Raݍty5%sGFȰʍ̸Πq9Z)N x Cge@pSҜүڮJ:B &/8@FLQU!VWWVUR,NKI=E?93E+#?0dR GɗCÙĖǺɭ̄Lcא8(I I X4ݘذҗйT` eH(T1:WB4HN*RcUX6YXVU RO[KHC_=71#)":jH%ʳſA+A˺͡ i^ >l j1Cܶ"үкБҹ,a** c)3<81) /p8B &^:Ȧ!_Ek2_ Riw  cD/|0ӓQ1Ϻpt ط@s # J*4=PDRJPTzWY^YKWUSHQOyLCHGC>m70* ! 6+opҞ̿-kvtTņo͋Пg z)! UzG :Yxݶبԇ͇ͮΚ*Ԅ8ݙ" !_,.6=?FqL%PTWlXXWUSQzP"MKID!>G79/o' d""PưCj˜OĎ5Й*g۱z!! No_ 3ېҞ2HΌhӏ" #-6>EKiOSZUWEXWV;TaRFOKwGzB=q70(B  +9|2Ԅ`|ħ>SUt>4' v*A ] ړ `=˕ˡ"W.VW} $.7c>DIANS)UVWhWWVnT2PLHC=466/4': pr4p˫PlmZyƺR˼ҏ֭m@[vk +7".ޠ-Ѓͤ^ʊXJפ?- $.6>ELPaSUWrXWVUSxP3LCH9C,<6/\'F]ٿpc}FGC!׌dY& b70 Q$``۶oH˦ɮ!HA nsM `#.H7@G+L9PfSVRWWW VVHT/PLGiA<7Q0&'xS݃ԡD=8) ЭԳpޱf $> $!  h(߸Ѓ̴b 6с֟( $.:7 ?XG"MRBU(W>X^XWVUSPMHCC<5~,#Ban_.rĿ2%}6n>GAUV!3"S!-EmLϖ+^Ȍ"F$.7\>ELQUXX%WWWUROTKHB;C4-%Yl]¦ io̠<پޛ!c+1 ~#%/#^[c=k>ǹlɫwкճF><n1%/f8'?FLQ]TW XYXVTQN:JeFA1; 3,%[vC9(RŕŒ2UwŽ!֨ۉ* %Y!S"$"?NlKխБ^y#g͡рq>um ln%/8?FCLQTV\WXXW]U&SPL GB-:3-$~wGOOÁqS÷ū9V|4؝Mr %#$%&"G oH#F;ƶƚTЗFܺ %>.7@GGMSQUWYYY_XUXRNJE8?U:?4 +! )f5ޱJͫSf)ďǕ(ծ2ށi 8!$&%p!s$1 g!μǹńĒlat%2.8%@=G9M(QUWY+YX,82$*) ` :) aMoFÁƤL͵ԗoS%Cw #$o$"6 !KFy^ˬ&¼ÀƨB95*1%O/8@H N5RUWXXXVgSPM@HzC<60([ f6o‚iy(>ʺ΁TcL2&!%'4&# ]4#ϗj5?B_Յ6k>0$~.H7?FLRV&XYYWUSAOKGB<60)", !՝ƞFzw!Δҁִۨ VYe!#%&"0 IW:X}aʮ¼ʺ cb "- 6?:FOMRUXGYYXVSP(LmH~C=A62/0(!S x 3^¡<5}Έ]kP&~5k]$t%%&L#1 ~-x01ϩ}1wbla ",6>FLQVXYYWV%SPaL HKC=k6/( h&ݙԆ8hTϾȄEةWK  "%&_%!? Q3ܷK8ÍĂu=څes 5"),S5>EKPTWY?YWU8&s{!$P% %9"7 d[Lx<ε&) ɠSӑPn"  i)2R;CJPTGWXZX}WURNK9FA<;6/(m b(_& h Gb ;q'іCi!# %&:#$Z g#^ܥDɾjQ48Ғ`m&0:TBIcNSWY8XTVTR8NJFMA<'5.' #+a8Ƥh¡z.mՋٛDi!%G'L((%X%NpHi1|ȻсRMNE%/8AWEL'Q~UWXLW"UROeKEFB <72i,&B-.dE%ɯŵ¡@aVr;k X#')'$; ?^1Ƹà ƛHε.Cvoo*\4;=DKQjUWWWUJRO_KGB=8y3.'2GSL׉ʙM>W'wڴ0r #&{((X%c%A@_^}ǜkqEpӳ1 (2;C!JPKU&WWWIUROLNHDp?93.A( dci}IJWʔ΁֝?޾<%@!%%(*(p& G)Zobo~_(ŗU2:%,/g9AHNxS)VWaW4USQ:MIE ?;/60`)#*|XP{ĂEåƶɵ|gM @[6%(I(&"\M CPZՈPT y= 0"-^6?{GpN$SVWXVTQN#JF9A<;507+$3 CJ<-fMC~D;kO c B %'x('# XZؔ%O , ?}ǘhϯԴ%r eg*4=sELcQU{VWVLTQMJFsB_=Z7B1,&fw}`XLφVy(^˺A6gjv"&#&#''g$  #?$؍pAe0Σ|ؽp)2;CJ5OTVW1V T;QOK_GB=83-& *r$#8P °īΒ9޴$m "&#'r&="c a6,ڧk6X\r;C͓ұ^9;w%/;8AINS-VWWcUxROLH=C>94j0*#J Zh?ɋŻÔÒMy΂шԶ2J4 #[h`#%%#XKNZ 2t&<>cW̢ь]݆jO 8# -:6p>FLQU+WW.USPLID@#:5h0+$, 8AqzÎéʼn}ɋ!Gس9 ;#" |W!$P$~#W /MD^,B'æŅˉЈՠO r)3;DK$PT6VV`UvSoPMJEB >82,&a""KG=FTČ{Ɍ̰fH* #tg"W$B$!?k Zܘ t"Am!ͰҴ<lt8%/9JAHNS$UVVTJQNJFB>}94/n)c" Deņ^0ю9$|!<[!$$#!9a8Δy0$J@}g$ "$-6?NG$MR?TUUT,QNuK+G~Co>94^/W*Z$bE"ЄɮaǦdʢy͠ВԦ}p#LC X!i$%$!2 kżt:Ev{tT!ӓd<{*5>ELPSU^UMT ROK|GC{?{:51,' %>LzEo/̑ɱ_L=Ѹ9*!?E_ _ N!! ,  w<(ˎÍx5ŌW=޵h>ef'1:B5HMQ(RS)RP{N0JFoA=:629-(Z## O >E vӝ zͰϵ ߜ9WbE7c"$$ cx4TŽxM"ãƑʓڷ 4$1.8oA HUMQSSRPN"JFC%?5;J73r/r*$}Ln-?ۨUg|rUΠQO5۵bG3S gI"$$,!` 2ߡnЁ>/Dt OBȟ[]?U  !+5o>FEKOQRRYPaMjIF$BW>i:?6W2s-($11y\$سԎwF#uϺ2iIt2  #@#!D osoҙs/(|#l.׽y"p(-2,;BI7MOPPNNLIFBB?G;62. *6&!.mۉ"ҤϷϳО!ٳ` q9 "!V)+ߐU=_.%m¾f'ۗx;- 0:#E-6?eFL?OQQPNL HDA>':j61 +'#&.c=Jل,҄ ԃ ׸Sےy*^v v!V"3 ~ kیR\Ɏc*s3i*\@K[  +5;=zD]INPaQPOLM"JJFB>:j6^3X0y,&! 4kFѣa|j7ѕZQjVdF  ##!&I"g,'Sdļд}\ |'1:BIMXOPPOJLIEB[?;Y7c30h,X'  -':m{c&јo&[ Lw5k "?#g!6vއׅѷ̈^ćþwr2uցVOx ]#|-7p?FK9MO&OIMKoHEuA=:!6s2.:)%g Mkub%AY#[9نܵ!nB"#"qyy^-i+Kńx Ǜ@͠ѳܩ=6 ah *48<BGKM3MLJHbEB>;%73/,&(#h 2A 'Uorѓq ִ؉ٻ^tDW lPO{"$$  AWbˍ_ƓŮ8|ɋ̕4Ԋ!t &08@>FJ'LMBLKIGTDnA?=96Q2/*$- 5Ll]bz.؍s޴\N#&n&=##H-ݰ SƊİL˷u$~|$%.i7b>DHKMBMULJ>HEB?C;[73/*x%!%w*9("ТD7̞! כٞܔ{j? "{&&k#8*ߦѮ!ŒŻΗҵ." ",S5. -WK~_Q(ǹKѤּܵ x(E19@@QFJ0LN-NMLIFCa?p:62.)v$ABr }7d ܂քjɄ+ȻA:$,5 <85$1,'!. DN2Pɏ62)ʽ̍ώF 8O$&{&#^\ a ms cȧ!Дզ۱xy  )2:AG@KeN8OPNMJsG C@=$9553//*%&Cd[ٛPʂȈȠWtP׮ۻߚ+\T$%#m=&yOǾ~)"A^Κybk'>08?EILN4NN0LJEHFCR?<9632O-)# !cl׌̏ȬQǂ*0˹Ӊ#n Z WP"#[  H&\ȳ u-S 7C",4<)ByGKvMOO&NL0IGEBp?s<9e6,2n-i& E6Ԩ9!ɷɁg˃дgբ;Nb% r-!E {߉ͫXuŐdd&͸%&/o7>E"IMgOPPfNLzJ#GD@= :9!6@1b+7%& kPΖV_ȟțd̥ рӨض;[Rg? ,D f!ASŸnŴȻ}?;s r!+5JNPPPOoML$JkGDAF=951$,[&N8Ԣ(˛*y\_jp^%B9+ R pna~7ɲ$Wg$L  *3;BHLOPQPhOOMKHEBn>;7,3.Y)$ {cڝ_;/61-)M"3 2] UBjϡѱ8C\  ZwYs؄Ӷɉ>eϚ ٧"O$.7>DIqLO OOOMkKMHEB?<85V0+&c Q= h|X<+ MKH2EA>;J84/h*~%Dj4\%N ˕ _μϹJQU G> ]cm؇IήHn*҉In #-63>DI,LNPCPAO!MKIGEC,@Q<473%.'! Bdʡ8pniքإVH`q  8' ݬ؂-tj˛ˑ2Nϛgv &y/8@EJMOP(ONML:JHEnA>/9590,'i1ڭЪ6iʺ4Asϯѝdiڋnp0 - v2 m-ОN P+԰ٷ"(2:_A3FKZNPOPPjO4MiKIG5DSA>C9Q3.)#7WH'c؊ cʮ}+p~ьԊLٔ`(kSb sL~ <w)}`RΫ˨ˤk Ձې`# ",9563-t'S  i+K&1Mr_˫2Ώ2z`~r' b6K lMI-w)ҭ`VMuҗBu*& /8v?E1IMmOPP{POO@MIFBZ=Y9 51,&:u\=3̷`f̻,|Zlg? \y 2U6 ~l(: M(25:DA.GП˽yLˉQtױT#'F0B8{?F JNQORSeSIR_PcMfIFSB>v:o62,'$$+vLqu֮:ΠV&{0&NfΆ+d]6= c QK^ܨcx8͏ˬʳʁʽ , h]dB)2:AGbLOdQRS`RQOLJGC >N95/(!  ZDՀ'Έ̯G8#ʹ ""ٕݙkI "-cOν˴T^ȒɁFdl@ #!,5=DJ]NQS.SS?R1PNoKI EB =82p,%j|tڴՏ%&BB˦̶Άӑ؆یްJ B!t :ޟԜpʊ=YCО+P2 ,'a09v@FKO.RSSRQROZLIF1B>950*$} w4f5%w,_̘D.љԔ`~Jo~ l< Yg۝֡4O \Ү5ߣ  *3;B8GLOQjRkRR-PN|LjIF(A>!:14/8("  jw߆-̍$(̇wάQEu"qwy>p #er+ wBߙoib̈ ; 1} -#$-G6>EKsOR*SeSS|R0P) T.{ [eabqrݥ:H )j2ݢGpU(~2;iBH{M4PS TBT_ShRPN*JFB> 84E/)" gYrI`ͅp[luϰԂpڧ~>; e&E cQA`PH$ AQζDإߞ- f"N,p5l=`D~JOR1TTTSLPMJ*FC?;772.|(!9 ^p.aУ7fV̆z4Rn. iZ'la wp$dϓZȃaɐ2>,S%/07?MEJO5RSvSRQsO^LIVFB? ;973.%' @t01\ۂ֮>ʨˆR`ЙҦr)*F l)`&R`o$j9ժzʁIƢǀɜB֫ݍ)2;4BIMQTUBuݰ. L axg=џ;KǛ:Jk̛ьיD( s #.8AHQMQTUUTtRPMJGD@#;7\2.)"%12ʍwɜʂWJҚiٯ T zn4   h-R#3iNzDrۏw~a'2;D#JPDT6VVUSPNJG5DB>:50}*r# e]/ݶؤӝRvʗɈ5O̳eٞ8U= U#W#9 /c  (uđ{ȘFכ& #P.8AHtNTRU:UTRPN^KQHUE|Bk? ;6{1+%ExGzuo+ٜ;ϯˉʂ˭7О֋ٿݕ#7d $Z%#o9~MnՍШʼn#Ëj-^'*;5<>FLQSTMSRmPNL+IGDB =8550*#28 #\L+8R3ɉɤ\>'z p۲P3 c %='I&V" Oܖ\ϽTǕ1ZğǴ˘_T%b0v:CJOSTTeSRZPN$KlHEBe>;8I3.p(!"g9+pб?4ʏˉ̺ίEf@qu#'(& 1U<8N^Ą ĎȾ͵hWN!;-M81AIO|RTU9U.T QOM0JGDi@=84/* #*oiʸ[˔1ւپ66'"L% 'u'$ g̻ L`)K4d>yFM7QTUU(SQOzM=JoGDA\=a9940*#oIϖ(ˆk̾ͼL"n q{- s$C&'$"5 OJEfhπǒaq\Z3wI ;%K0:C!INR|TSRQ`ON KHEBa>:61b,'?hT}p^ [˘Z̭fiԷ\ۉ|a dL$(='%x .Uv2!ÑrNٿ/P ҞFCH~+y6D@0GM~QSU"USqPNhL/IFCh@=9p4e/y*"hat|1SԐv;Ēzε4ѷ_rvY >t$''('h# w+ Rr¨ʿV֐ '2x=E`KP%RT'TNSbQPMJGDf@=95h1},Q% ;l]O8ˡW%ΗOnYޔix#7'W)()m&F9WdP/gṖS!-8RAIN-QSSSuRPNL.HEB?W;7]3-.' @Vּ݄Em̰ʲ>E̷jոٶWZ4 "R&(*,(<";vB@ˊkʿhĿ:ς\Z c)@4T> F*LJPSTT2R_P^N'KIBFqCK@=E8{3j.*O$Gl 2[|vZf_G˺A2AucNuWP"yjA]%)+Y*0%x 4JMكQG Y2}KAL ]($0k:CJNPQnSLSvRFPNMJGDUA =951,'e mV=!w ˃-Q ~fP^In&+,+K'!9ہͦxпH@'لzK!l-8BvIRNaQSrSJRUQ OaMJH:EB?M;Y7u2-N'"LѩΈ;r]}gϗ"/Ւ92$*L-<,)#5X>5KGuΛH{9m΅\i)9)5L?MG9MPRRRKQ-O(LJYGEFB?;J7>3.(}!! yACӯ.̧˲`H͒ Auקڟ+ G"n(P+-*%% b~gzy$Ùپ׼:S+ӹA A$1,;CINoQ[RLR#QPbN'KTHEB?:6v3E.)?#it [/ ̷˼*͎AWԋy~-_#S*//*,s(?!, =q2ώeħ߿ڽ05Ǟqa &1;YCJO>QRNRQ>OMXJHEFB?B:6N2.d(?!(aќ\ʠɫɮʼ1͓Б/؄a/ 8" )7-D/.)#%B!ӂ\NѾ̽OUv&ę75$6*"5?RFL3OQR4QLPNLMIFC@><>84 0A+$ 9L)˶RXʖfʢAb۹; ~_'-/U/-}'Z= g{ "c@hھArǕ̕Ey` g&1=:7O3/*#1cګԽHg,ɗl̃И{2 $,/0O/, $_Y"g؎ö|y)g"-8{AHMPRS;RPMLIFDAW><:50.*%܊՛pʚȰG"PuS"߆Y4 )\./.+'%&tFͣ@ïms=ۼTÞ~R)4>uFL9OQ:QQJPMNTKIGECA>p:7]3,&o VW+ҋ3x_ǡȕ ˛Ϋ/ԕ[(w%*.0.-(# - ?@Hű~A_!ԉܵ &2:<D6JINQcRFRQ@OwLKI:FDB@6<8404)"T]b ȣțppP`ȄRJнoS*#s)/1.)$Bڋ̢Ƣοy׼Yađй| 5N%1;CJNQRRRQO9LJIGDBM?0;6D1+7$_Q 9+ݬ֏ljƏ4C>I)ux'L-/.b+&~ V`f3Meȼej`Ϸ׍ +lUC*q5(>FPKOQRRQsOMKmHECpA?v<*8{3.)O! 5vwh#*o>[ǭhkފ; -$*]./-[(I! ֡6EXѼؽzqƔ̥HxV K&2<~DsJ[NcPQRDQPCN4L\JIFDAc>95 /)#b 9F֡G͉GǶnEǟǶaf "R(.b0/\+ $$TrKYƼ²轹<׼Ź ٠@a8"A.A8AhHYMQ!RSRKPNLJI/GbEKB@<84 .'rp &}q.8rŠǩɴˆQҗ?t Q&d,040-9'& >yۡӂǹM"S \2Ëwz߉0 *5*>SF KOR RRQ)OgMKIGTEKCA=:F62U,}$k8lgԷ`ǑǦLƯ22ȟɲo1& S#*/y0-)#!yI* ,-yy&.Ҧ^n &q1=93-T&_b/-/͎ |7-5ȭs˴KЪӅ׮m*q&-22-P&p+ctٔ:̴Ǘ/)Լ$GcVF5@![-8AHMQS SRSPNLKIFCA?<84v/`)c"lt# ƿǀǑǘəu\Ֆ۹& #T+ 0r1/W*" ^ݷ97Ȧտ5&Qpq˲ZN;)+4>sFL!P6RSxS>RBPNKIGDBo@>:Z6?1m+,$~~NߙfgeƫƼťƽȭ(W2ٺ e*!(-21,%dm=d^dAOlwg? $S1 <"DJOST6SuQPMKBHGEZCBe?<]8~3-'^Q PbBy'a]ƹdɅrω׹ު ($ 7y&-1320*{! AI_*|'ÿ; Cd`%ݨL,7AVHNQSTUSPQOM/JHFDfA?> :50d*$G#5O-y7]3kƔǢ=̱ϤԂڒVJ#+033%-%Km^wΛQ QS-UϤHoW X&2=YFLXP}RSS#QONL?J0H:FWCAD?H<83:-^&M_[ tŅ4ķ2ƫ(^׆WEd*=0u4041*!i aS,Ѥ G#Ő@#ߝ").:DdK|PJSkUU SQOM#JHXF8DSB!?<95'.(h!i l;$pƗ/3̔4ـc[k (/*3H42,$#r eoi{?g\ !{_\zT)5@|HN\RTU=SQOMK+HGQ;61f,4%mQ׊(˺ȩǀr7nǩɪͰ^R$-36%6 1*D I 4|N,︿i;*K<?#0y;E?KPT8UUwSQOMKfHF+CA?,<93.'A2Y X<2[XƺøWC@hGͦѿu *2X6~6m3V-%  |E#YCncVlfĻ' :7ܚeX+8BJPSUlUTRPNL2IqFDB?F<84/I(!lR) dգn:ǯħF}bƅ̾cRY */486R0;(be8]2VL n?}A r5$2g=FlLQTV7USQO[LzIFDYA?<9/5n0*Q"BvΪƧ=ó%ŻƼ2М߾-2<$.b5G884,# [Qʧ^Iȹ@vc߻(o߾G<"/\;DKPTKUUxTR OM(JSGEB@p>,:61,%{ )j ܮ˞/F#7v'9ɋ̏=9 X+&26760'-D݁L% ݹȷܶθ,I(ڙeV)O4?2GNLRDTUMThRPmNKkHECYA><:,6}0*m#(Q{aљ̖ɱĠ3ļNYL y'06873,# ؐϵð2뷼)KKMP* $M0I:CL)QTwTTSR"OLJGDA>;85w1h+$9 <aBǑdt9F7ΤؽY-*17d96G0(l$Ӑ̧[շYCғܡ3RO*5@IOSU:UU SWPMK8H]EC@-=^;c84.,'E 1ޔ׉.ˌǦĴŭ[ՃڱjOR )115u88F4,G" +ؾSɧ uն4tzſ5{C \$0;E4LMQ>ToV)V)TXQNLKIFDA5>\;85d04)#V\jYѮ̱jP]ą[~ǰо(]+j"x,>2{7 85/&4*p5@gI,OkSUUTRPNaKpHUEqB?:At~anĀ."oη<῭ı7Ӟv?;!f-9C.KPT UUTRPMJxGzDA>y;t850*$J;BR?o˔)cO 6`@xD"-48:%72()ju{pޢ5͵MѽӷbCЛڒ G(k4v?GNR]TUU SQNKHTEdB?<:F7k2-K&f '"zYs.ǭLF/&NǬRx׸, =,49;:4+")\بuw+f1|/Z-k5#d0;XDLQTUfTSVQ:NL I0FhCQ@/=];j84&/V*"XXޣւό)ǡĄ¯ãZ=xəc-(28;;70'F" $Pҏݻ.Qݺ̾J°ȿ)@ Z+T6AIOSoUDUTbRoPMJH$ENBF?<9u6@1,& ;פ ͹<›aBĀňɤNݶ9{,%18,& ] dԷɤƗÛyVš<ǀKr5 9+"4;$>Q=93*<O\Őt깘0C+U (L4?bH+NS9UV0UTQO]LJMGDw@>;8 3.' 0 TkED]?eB1GǷ6ͅiަW%x07=81(ZwAs48Yֶ9Ç wdL+S6@pHNRATmUGTSQ9OLJ GQD4@=:8 41.(r 1)֮ZyX”S"_obj+a$07<1>;5S,u!~F^ƺ~%' 7Ps % 1\^FMR"TU"TJSQYNKIYFC@=C:8O5 0u)"cM@fѪ0mAeAk<ĦYU% a * 28;;T6/h&' )5ҵݵܷڻo_Ĉ!&.9CJP~TJUUT,R*OLIFD|A><925+0]+%6x 8עô^: ĚFȒl؊cT$/66:<=:3* JR~bNtnI (4?GNRoTUVTRPcMJGDA? Qc(U3"9S<=:4M+ 񿷻6!a7Jڀs)5@INRkT<9Z52/ )#@uڏGj/Ž5¼7"ĝ k"u".>6;=<7.%% 7`>cѶP˴# aA/%-2!>:%3q*";c۵Ar2^lӹPVG-1b? ,7AINR4SSRPNxKHEC6@>~;963/*$KHӢ̄ȪFbq06˹EMW^$/7|GyMRTTBSQOM%JGDBp82) qجvE4 wռdc**wRd.!K/:CJP;9 51,i'!R*xmaM^ µrǃm϶թ$1 8<~=;6."cbުԊXŖ̵Kn}ƃοx )C5Z?GMnQRRQPtNKJHECA3><%962/\+&? &tfפ89`3_¬{8cWU!-i5<@>82w)b0rX ؚ€gUt+ɸlH# ݭfR#X0?;[DKWOlQRRmQUOgLJGEC@w><96j1,'"R^g9V|6ł^YJ•$xˀϳe`r $08u9 1(U "(׿\|q<)Դ\Ä){u$F1r< DgJ[N`PQnPOeMzJHHECA?=q:8L53%/*#-S 3FU7 (iY.GC7(p4;?N?=6,!ܚq({ƲͲD/,Rفv+8AHMJPQbQ@P N5KIwFDJA?.<:86'2.+'$+s5YŽ6^ܩ?"#/38)>@??91'e :}͇Ʃ»T#x}#l}| t&3@=rEKoNPQKPO8MJG2DB@d=;: 7~40-) #-, %uδ|}r¢x9ԽۜRD'278=?<5-R"cѢ(*.)e!Fz'% b-8AHMOPPOMKTHmEC@@>2;:$862/,Z'h o4%:S ‡cğMe. ]+5[;?>:3)(l W'\Έǂζ6 tBˤSdAP &2= EVKOQRQcOLJG,DB?x<;9*7@41o-*% om6`p|Hjū/37]+ ) 3:>>p;+5-!/ \Æ˶g3:)+jCP .: BHMQRQsP8NK[HFZD0A?=o;u974n0-j(!gygE6—[7 3U .791D&{9 &=FlInZT0. N'Y4?FL?ORRwQHOFMJWGDB@?=;97E408+]$5 5WӀehD%Ҍؔ&u* 4:>><4+&sܞҙʡ_ۺ]s-\|^lB$ -9GC?JOQRRQNLJGE&C2A?=n:80511,,F& /: noއ՛ Té›P^·xzm"-6WL<6/% LI3ǐ+>JZ{}Zծj $J(4?GLOQR QP2N)KIFDBp@G=;863E.)$(0vuŒKRM]FŐȭ͑:۔%p'07<9630,'j!!<=гaKd-dwHˎ`ۍ B+<4:<\:T5W-#$g\*򹫷64;̩թ D&3=EKOQ{R"QP=NKHFDBy?=};3*A!_,U2ڷK a,Lږ'-9/BINQS0RQPs@<7b0l%Lߦ~{<ǵԯFh U(5.?GMQ:RRRRPNLJG;DB@? <:y8'51!+$U@x޾ַ˦Z ‡ŌWe؉"( ,6U=|@k? :3)xW g+ض괶 u$#1KO '4>~GM~QST=TS5QNLJWGEUC(A@*=:73,&*EֵƲrTǽU] úDŽslw" )\42:4+8#ګlɉ2u q׵1}Ɲϵel6 )-9yC"JORTU[TRPPMKmIGGCECAZ?$<7\3y.' 4 ˜Ĝ^ξW];ɿ"ke9&08V> ?!;:5!-e"d2ԲƘ<ϳbн,å3 )6i@HNWRTUToSLQKNL2JlHED7C;e7i1*i"P GS 0ֽ;z͉`ܫ.( h-v6;>=81' ZY}>B 1oT3(D#0GkN,RUVVUSQ&NLJGEDB?z:50 )G!#C]љ©ҿy߿ èdѫ0ܤJbl k*_2"8O<;6/`' &dP _9?n`Dڜ-:DOKQ-TVWVUUSqPNLJMGECT?;61+#, 4F́dlJX˜=#֋fk'd1 6:N:7b1z)y)V<ƺA충¸?Tţʹ "'u3?MHNRBTV`VUTTRPlMKIGFDA>69}3p-%nO!9F1Y*93+#L YLeH|âmĒa\ӂؘߏ8# $.{36_63%+K! )gpƒ<hx;kȒژe,)5?HPwU"WnXsXbWvUS|QcO^L(I6GC@#<06~.%uN.H]7“YEhi_]ϑ:\\m) /232 -M$ xxwڹܸ~úv&'nP9#r0?;F#N$SV WX~WVwT^R OMK4GC?<709' -ޏȽƔF¥³Ģņǎ ֧۽3 g):.1r0-G'$B@ 9}G_N$SWXXXVTkQObMIFC@n;5[/ &/h i#VOmĈ>N ́А#4%W}/ARp',.. *#N6''ӹ A{!Էޒ o-X9 BKGRV WX WVUSQO+L=HEqA<609'q w %Ѹ94IJ&jXqpӈ֣wsVz Nl#o)j,a-,&cQ hLu#h{G(DѸWU\ &2=YG NTrWYUY)WVTNRZOLJLGD ?e:4-h$k2 ړӛ,ſEpFLJA#=هݹ.XF%)+?*q'T!|۠^ͷkğYݼGָG*!g-8CRKQV0XYY^WUSPNKHDA820*"LclCZζ̻Thd͉WHߠ)#> _u E >BےHʮ,'Ǧϑ?7 !-17@HNoSWYZuYWUGRO2JF1A:;5?-& M ~06ݷ|θv́!RupKj/݊n4`M x _Cnң+TzOӯ5T/ z%1:BJP)TXLZb[YWTQlMpI Dc?!82*!{תzzTsѧӊ~()YF43, B [xahNҤgʡțbҚo(!b*X4=EjL0QVXZZ"XV;SePTKFA;5-% YE۲bο͠ %n^ֵ+kIww*3u  52ʯ(pܓ  #B-7/@GMRUX6Y@XWVRNJE@%92+ "?9`Nۄ%ш~;іkՀB7A`GF181FCވq &{o[t"]{&098@GXLQ)TVWWVSPLHnC=6h.& ")PP;rDѸѷ.լjyޭ||bB wiUkun^]֎Ԧ:j[=DZaX%C-5o>T=rJ :w]g6 QvV&%3Gt`vy=  #']*7,.d/0]005/Z-,9*'}$!LS, Z *@e]ytJ[{qjG_ \.qZ?(x& 0v z #%'S()i)))[(m'?%#!t9q q P8~[5VhL@ _+a>q^dN  )f"#%"&#&&&%$#v!- D ={5D~>>qGkD06 b,.w'>ZLpE 2G-l R!"j"#""7!O O > xa,LCHee$ V ? `8.q"X  cq-ChB / V vs0 &{4|#w;~xU?mQ ]h,e vJORwWi W &'Eh.:C[ 3ez \yJU\w7V>U4l_ l78!tHt-H d 3  ~ |]EiJkD3",yX1g=T(;sP'T + E Nzk+` ! j   C  F"/FaM|\>sz/+@b'Pw8*vOFT[P ";@S / 1,`w /53' x R s B5Y < h b  lV{aidD6nb5t]!IUL<&"t]}kXn m gX)*3H)Y\,i&.| e Vq'F2M7~s?QOQw [d.!Z  b A63 t8rUWUYK Y!lbFWCH0rKY(i10 d_  % !"$#@!""!!Y!"x" -[\ 7 S [k0n-يhߒx+J(^wQ0Cs35  `O!(#$%'a)*R++d+**))''*,-'S!@ S :)jqi"޸݉ ߈AݘܡBy^FDp?W; \y U ; r?Zlz#(F+/g293q4455453556!5454C1J,')"sL(\k8ڣ؂Cl%>)W\ >J?bF4}S0js ,I!j&U*/369;=s?K@A>@?>?><963B/6*{#GIZ:Rvٙiԛѣί^eH̒-ϥѿՠٸkf}x&L^I[; |_c KS!X'.94'8<)@/ChEHIJJJHFDfA>;8{50)< 3 JݘV'jm34ƏƮ#Ǒʡ ѢyE67FLdCTbTbޘX8G/U(M_N #$W+3U9?RD!GK M-NSO-OON)KI@GD@ 9-4.&=" x%H"i 8Dʹ͇яb^ < "_}NR٪׼׍]X|Mv '0O7> CILOkPQ|RQP}NLJEHlFC? :5-%@ gӺ /W w<+ոe(  9 Y > Q}U#ד,Վkcؚ۴߯11i!*29@EJxMPPRASSSEQO_MKIFB[>94,#/d]*pPfgÕD4q8Dٯ\t )z<|Jnݨ9#2*ӝB׳;ߒu"+4 ;jAFKNOPQRkRQP(MJG?DA=60*"F[  ZpGƊČFyMzƌ+oһ՝U2sV 9 ; T#$wَWҵ\Ҥ֖Pޠa($-6=CHAL,OPRRRRKQ+ONmLNIGEA<7U1*t". (-݇c`:[_BjŠš+f]ݙQ6 r z (86HVVi:Ҷյ(q%.7R>E"J^N>PRT TlSRQPRARRRR)P_N{LFJGD0@g;5/ ( D"H~ ȬYĭ|\ljF^7S%oTO$-  W<@ݒ֭Yѻֵڕn[ )2:@FKOQVRSzSARNQ)PJO LIFC?D:Q5/(E i&O$țƐŌYŁŁ#ˊ϶|&7:}$ kfX*f%" ְоyr۪fIW  X)2:@A)FKdNQmRS0RRwQPNLJRGJC8>93-5%:Q` ږ*xRȘ ,ţm;Sթ6ݛ6kPRL+qj@0 >%7:1U+#]U_٠QTdzƘVƗɁ*ѕڂ޾eV/elb3׳Ԏ>;^~m H7*r#e,5=ZDNIN8QYS5TTGSR P/N?LJGC?;M6,0*S"fUֲљ͸+:O^h,ʵ9C׸ڭ݀i*=gvOAe]CАI gܫUt I$Q-6^>#DJeNQ4RSJS!RZQwPOBM)K HEAt<71)! .cmud=RȸƯh7ȋ ̜aԫ"ڣݴ |3ypIfyW7z).jРИѩץ4=e&/8@NFL[PWSToU UT\ShQOaM-K#HC?;60(X :+ܰe ~#ǷWknChكl*N@K(5"ݗMЋ1܍J?D^+(1f9AkGM0QTJU}VVU+SQOM J&FCh>93,#?)uV̆zʁ-Иl yk7%zMBl[2Jׅ(b2Ek9+)X3/;CTINRTUV UUXT'R#PMtJ8FBv=60*;",Fm&ڦ(@ʯɟȵIW6܎(c`}62s*SVآZϑM ԩ؛3z !s+a5 =EJORU}VW8VUSQ6O_MI3D@D:4-&_~ |It%wVИʮɵɴL3кӶ;*IfC/|[RKe%8'1&ТٻߐeZ #-6W>QELQTW?WWVUTRNKZGC6>48a1*"gD݉؊MʮɟcɱH>̍uџm۽$$::~z[dPІϡ$4֦%Q%0?9uAHN0RVSX=XXuWBUYSQNJFBe=6/|&"M}BιUeʩ5Lkt)߉4+wR+a WGrUݴf}  *x3ݴԽ̇ˎSʝˢEdһՁ#.Ut-Z _iiޢQҦdmN(ښx1 #|-6>EKPTWYGYXVTROKFAT;D4-%X .slӍ7w˼˔ΞЁջؗ۔0]FflfY+uܖ3ЇЈz1%Zy'J09WAKHzNSW Y"YYYW#T6PM4I3D>826*"w2q ؾePW }f҄$Hۂ o_SmNThu )߂ې}ӉљРдѺ|֐#0k x!(+F4=ME1KQcUXYYYoXsVROSKF@:4. &  XTnBQc͙/$AБjԺJߚhJ-xq (]s8ҖLDԃH^0&"/8@GMRVrY3ZEYXWBTQRMIE?q9 2T*D  H ЛΠ͉e͸74Пj՘S)>22}M'H3ZՠpѕTJ68ߧE L + 4}'dC?nVҵМdΙ0\ Ѡ]G׹ڣoU{B tSXkEwLޅԕZbf;U<*%i/8@RGMOQUXZZY WVTQ LHD>=70)_!p RܟؾgA(U1T)G;/Okr420-Սӏ6b~VBc !+4=^E#KvPTWZZYXkVT*PKF@92!*"1j=vDBӆQk$ӏ$%׌߿=lw-VLFD?C<ַٜrҗt\M!ڧ4'C11:JBlIO;SWEYeZ#YXUS[P(LOGBP<6e/F'0?` 8y:TЛPc>шWng/PT-eTݢ(A-(ݦ KTB#-6>FMJR3VIY[,[YWUQMUH!B=7N0e)6!cf#t|;ӅаЇcDjԆժ>zsNUF&UB2_܇֋ԣ _ؐ| '*33;CJP?TXJZ]ZZX_UR NJ""0,p6(>F(LR;V(XvYYY+WMTQMIC>88D1(Py 2JM5Ӎu[T׫'}Y(?; $]d}.U֗~6; Zi  %)37;C5IPTXZZYWURNxJ E6@ :P3k+L"d'6~W2JQxHП_҄ӲԾׁږ7J~'0zub(y3V{b$ vH ?&0:T70Q( 8^ bmۈؼ^MA {Zg\KIHE=ۉhA?C._fEE׶Wڂ}\_EKfPUXYZJYWUzRNJuD=6c.&V #Gٿcw&7ӤԘ}c׉sݞRY$<AH Eݍ{H^߶UL }$=-@5p=CJ4OTWYYYWUQRANJYE;>5-R&I2 i&>[-$զ!)t0XEօׯ}LWy4gxR۸7_J!U L8{/V"+4Y<CmINS>VXYsY WTQgMILDU>l70) \( T3<`إ_ӉuCҒӺvm[AB؞t4iތ^W:l)lzإs6.n'0 u%H>8VN:җxԉh s"נP^aVSfٰڝݢU*I$.J (1/9APGMQnUWYYXEURO1JE?!70}'H <+L\U]ܵي1/ӸҸӆeՔJ֫mM܀L [g&|غ7w5y ' 'r078=?FLQUXZ&ZVXV SIOKF?70u)R!-/g "mKz*݀G2# ӮladՁpnېߕXX6j0X5t U &4/76>ELQtUXZZDY9VS[OKEE>6,.&Z ZC$?=ޔ۽ZBձԞӠӡӝӞԺ.,yK=/N+֏Pӊ n8ӫӍUI,B(. mhgߋyRTYk5L#M+4TԄ;ڄaVOG\=3܌NXf# 3#%Q-5=]DuJP1TWYZ"YRVSOK6E>70-'? zG+p0az]֋պ8vSm=IҙԶL[V dS,O ݘݷQ E4#+470)"P<D O ?LCuAOQzզZӮ]pCw͎c[ԛ #x6iN޵+2hC=l0(m19@jG6MS5VxXYYXUmQLGAR:!0(!+ iVkw$%S/!ך}weaҞѻЎy{͸$eicJ]ݰݱe (X19rA$GMVRmV]XYjXWjTPL}GB<4+# akNpT9-H_IrҧѾБϼSδ k`06 1I]޼݁?tKeT ^Z'/7?,FILPwTWWeYUYXVrSYNIC=7B/&k YRGKݽIw [Ϊjϔ 7P+L2 ߓ65ܥ4? %.>6,=sDKPpTWYZ Y3W`T OK#F?8j0)_!  ;'F^L;ۍ^פA/jWsшβϞU6@ Gds܆{ݑ9\d""*3;(BhHNSiVXYYVSOKeFA1:3X+}$aV Cj:5P&؟ՎԔpһфMcё*ѣyCYR|)J)r z G(Z08@GM~R-UXYXWUJQN5HB;60)  VL@s|Ӟq`% ҈ ӮԚ$ަJrgCLR>E4ڻHm%G ms}%e.<6=DnJPTUWoYYWX-UROKE?H93,G$y g#mNזҨҧViY]HU%][rڜ'Wd$ LuI#?,v4e;BINVRV\XYXVYS;OLGB=}7B/(@! 'hlK$wԬӬ ҸҦmb=pn*A`ڴ 2BB]}blb~\gݯۋ=Vci '|/7?)FLQKUfWYYWTQNFJFA:2+y$  ![| 1n֤ӳҮ<44J҅җҠ#Ԋs#~_1JydS׏ؓڑg2<-s$M-R6=DJOSVYYXVSP"LoH"C,=70( G CQmڸ՛+Ѱ=Ґԭ%ԍԎ+89jy4b۠8f`ޣ0U l  i)2 9AIGMrRVXYfXaW&USOKCFA;%3+$< l:@ް׌<ӿҨ,EiAҋԚHD]S.@ h UhnaxPXܥZ$-6c>}EL/QUXYYXVRS5OL^HD6>9W3c,# a\_Kס*w^Ѱ҈ ӫԒ֨" ؕ%xJ**ښ6 ԕԷ؇a H:# !*g2;BPHNySVjXYYUWU}ROLHC%<5.'a=fפ]V}@ѫnYԔ׃ةٟ4+M6ޤ'ӯҦز]co$%/8e@GGMSVY"ZYXUSQNJE@/92+# YAl߮ۉTmУrҵfnշؗړۅt޼pq "@tR zӗ p ` l"+4&2*)y5RϐLԷP`6 w"A,4&ۼL1ѕBHҋJ۔&TL0 p!+4rIE@:4O.A&" }1>m ˔o Aұ Շ۶߫TS'_K  6dѢϺ͸' ΅gفwC|i 8@",o5=EKKQ=UXYYXWaURnOKGA.;61 *"[R_݃c.kͲ?˚4W?͟бҝԋֹrC: > u; 6uAQHR޼^^ν˚'pozw%T'x1,9AYHNSVXYY9WV%SQNJFAo< 5-%N} NbO?2ʸ)˛̬΍зXv߆f'kR  Hn֓iϬͩʤz ]߄8 #|- 6>F;LQUXSYYYAX6V)S[OKFB=d8;1N) b.%g`ӑLC˦˕̥V? g.݋"4}_] a FFݽLЀͱ5S;&pܝlP6(51G9AHNSbVXYY@WU}SPGNJE@;5?,$*J U%FٛՇ^Xˑ,Dk i1#U*W>?h ' o;(ڕ"zGVC-l$ `#5-/6q>F`LRUX_YlY"XVU"RPNJGC>8;2R+e"$LPWܘք|;ʐ˛0ύaiy:pRx njܨwϟ&CɁcOѝ۲LCX@d(2~;6C3J&OTyWYZYqXV SlPLIF>@:4n-%nF o߄ؤ\J˛g̎ά!>Tj܆$Oo N ul٦-.`HɕȳYөހKn #-6?$FMcRVmXYYXW"TQOK?G+C =70)D F VnNѺI:ʉ*3ОӃqyLyR r _EuۖяΡ̸ʶɭдmVG Tq&)3n=9z3H,%vJb0;unйmpP^Zd=3   <25?}М͉4[ȻhmEIK&%0:BJLPmUCXZ\ZZiXVTNQgMIqEAQi=` j}Y ^XS6;c7ǎ[Ⱥ~nG>'o1;2CKyQVZ[[yZ(XV)RO*KGC.>:4-Z%cWW](.!x@V3ק ާBgwM xFL 7zlLJD/ыֹܧ/M #s-7@HOTXBZ2ZYY'WU,Q\MIEA^ցgZU pV>#i5Ԙ>]ƚ&ȸ˹϶W5|w *5T>GGNoT2X5Zj[ZYXUSBPaLHC>81k)! Ns-K˓ɟȦx7ՑvCRy P PLS%CɼǢRƂ1ʚih>| '1;bD=LR4VY[[ZuY[WkTQN|JE@:3+#+e.\gѷA"dzȋE_ܧ;+ OV`A Q1NۥQйɯr.ņŴ.Z`ս܇,n 1m#/Z9BJQKVZ\*\p[ZWTQNKJGA;4-% ZҜ*$6ǯǜ>iΡյoV $^? eCi;ǕĖOT8rB !,z7AIOUnY\z\\k[#Y2VnROLFA<6/&G-+#`\ѠiǐB8;Шӵֱَ(KF  x wDU(ߏحү_ħĄ7&ؘ|w)4>GtNTY\[\Z\e[YVSPNFJ&C=70]'fjnaј͒AƨǞ[Σоh֐MT5@`%^ ]ٍ]Yv:rIJр׊ގddA( 2ƟˇO$Wn5c4H/ {9!ɜƓıĺƶOӤ2 !- 7U@IEPVZ]]].[YWHSPMIRB;3*J a d+jYɹhmJ4H{UԀصivGOUY\^Y^V]ZWTQMHmA:3a+7!s5 Uh;,7.}MʮͲԡ}'x O v6@j.jؐғ`>A\JF7٧RO)4>FMTY\Q]p]\[0XUR)MHnBZ:2) R}̒LŞ%bñgsէ:w>mrc+Z:#uUˬ*ōĴŗq wM?'q2<DL:RXP[]F]]j[VXURMHC<>4R*  #,T6rćʁͿMݦ]CP~,G]y{ڋ˩l Έ}߉''`1:D9L+RcW4[]^][YVS)NHB;4c+P!G I[aUE }CË+ŋǽgzJ2݉mSD7 HNںԛ*=ſhOΤWز߾ E'o1;D!KRaWZ\]Z\[`Y0W:TPcJMC<4+!z 5tE,ޢJˆdzķÐ$IͱGIޱftF ?u9?*Mkl6-&Yئ߱>'1;:DKR-WZ[] ]\pYVSOuJC?;4{+! <{Ϭ9N+9ŠIv$Rb ] zw nq:L `,{? ^ԩ {#kU$T ~۔лw<#Ɗeϵ 7&/s&1;+CKRVYTZ[[ZuXVSgNI B;:2( W1JߕTnŚآv`ՙ̀^0Qg[GN*SWZL[[ZXURtNIRB;V4q,("   @97%ǐP˛IL=]{'7MYp-#7 >Dw_1Ia?Ǘ&˔`E #-74?G(M#RUVY[R[ZXVORO2KEY=5-#7 SA! %ɖǟƤlʯ7ӝ֚ !s_=cq6'o5 '0-G7yƏȢkRٞ;<t#W,5>oFMgRVY[\1[ZWSNID>%5,O" }"DfbǥQ0͚ЃӰޕ@{/0 j; 7ivޣصӬ@ǽId ",6(?FLRV*XZZZ>XVTP2KF?7-$I Ce3d|A A}8ͧF8֚ ݐkLrf5 l:E tm~iF$MKo[k*I uw-aq -!+5>sELRUXMYZZY$VSP KE>7U/L&'. ϊz/I7Uٔ5SR! KE1T4=Ё/;@>s׈ݻ5  9*3ۆޕBmnS c  J܇֚ʓFhWɭ̛ЍՍۂ*&0 9 A>HTN"RVtXYYXWPU/R*NJD=<5e-#Q"=ׅӿλAQ\Ԃ=Nݍ4[WwK  S![S ̺9lǺj Ӡ`\H_m]#*,5>FeMRVYPZ3YXWTQNJEc?Q80'%-6wٰvgj9Y3ӳHۖ&H >G @ zFSLгh"#TO2 ,l *4j=DuJPlTWXYWXW1UGROyKf6-v$'&yרv Eύ;EKPTWBXXXURP+MI)C>81i) JO ;2*ދٸ?jϷ+*ҹԲgzg% = p ^[`TV̾`ȁ ϛ*5  b*;3R;CIOT5W-XXX_VTQ NMJE?:G4.%?E\{ncCЇoZҼԚ֙ؔ>߱L [A[ R > T i Mxљ˘#|s˛Xћ0v;:%/:8@GLQUXWuXWVTQN{KG\C/>28c1*u"rM4R۔BИОшW8!qݙvrDT31^C[@%ԘЕ8wCQNeΚV t [*3;CPJOS}VZWWyV0TtROdLJ5FA;5.d&8 3%ޱ׆G$ұפs=ݟ5"L,77 (kW^ʮɾ)g9մی 9<$S-6>EKPT}VWWUMSPzM-IEEB>D83.c'P jޭHX3\R٧ۼݢߧ4%Jr4RJk*YړՍM˟N֣])2l;BInNRUWWVfTXQNKGDAx<8d3_-$k o܌P}WѰ%s[jԡCٻ4;8DK7y$ R@(xסҭW̷:ȱȔ.SPϥ+.&= "P,o5>+EHKPTVWVU^S P LIFHA=}:60*3#P'iV=XQ ZH].^g9HP%R'aARZwլѺ%˨pɋ+ɷ[azsSfa%g/8@_GDM`RTViVUSPMJGiC@=}9S47.)^" 2ۮ DϖM!ӓPؕR7-/ty4?-;Jz*>ͫgcLϓ6׏܇8[v6&0:AHNRcU=VV~UROLI)EB>>;n840*#>U 88څ{GВag@bbדڴL%&j  j o6rmץҫ̙}|!W8'1T9AH5MRTV&VTRdOL[IEB>:7i3/q)$ )6 ΐ΁΅0o,U؀'h޼ku@  lΆ6̣9ھ{&7/H7?oF@LPTTVdWV8T(QOMJFB ><*8q3.*L$ ]ч̿Q2h z׶ڈM| a xSұ3ˢʲ̒)A9V}$- X&/`7?9EJOFRTTSR?PM!IEC @;85 1,[%.IN}ˡˍ˗p2iҦ;֋C޵ M  F v_ڈRy, ́gԢ=g11 d&/u8?EJOuRTTJSREOLIFD-A=:7B2,5$ EI <̊ʔ˔̦~|KEܽ,[$  < ` KD>,]K AVq9Kvn Z(1k9s@FKO#QpRRQPNZLFIGMDBl?<84r.'!Q 5'IB՝oαfiMȕ+ʂPC҆SA` y "^?%El̈ʆɖqˎC>E 3 X(2:3AFKpNQQQQbPyNLJH~FC0@U=94/&)"f- /?ځҏ 6?+Ɂ˂,1Ԛ>J K S,׈ pcȟ7Z̥dU`o< "8 ,)229@IEIM&OyPQbQPNLJHFDA=9451+# Jn27{#DE) Qʸ̈́Z { }lLMϡ1ɓǑƓWf@\x n(40u8;?$D{HLzOP3P@OONMKIH7EA=:(60b*%Ex6Fޤϳ̑lƶ/ĴĎŻ& :?50*$j^ء}ʚǍ̊d2Eיhj$%O ) π˺zŨ'ɓ8ҫٳ HM'.52:?2BEGtH{HHHHG3EDBA\?F<9590,(" P) ߜu_XOi|w]YOT(/P /s ȧh~4ϲl#YA (#.38= @NBZCDEELDD0CYA@ >z<:T863x/+( #,w_x,΅z뿟+`։mw ~g ;>/޾n#AMȜ;}2Eߎ +$[).15;8:o<8=[>>>>>.=<;]98:5300-+M)(E&&$ !7A ?LͰ~-Ǣ͓֌l2G w O<7+کՁ[Q̄kzdKM < $f $(,w/246w78k888O765W4.3212,2 112c0-c*'Z"- Dڠ*_Ǿ()2L?w7 W  * .ݍ.Gגۯ|lS<. 3L"6'+/U2i4:5 56655445256Y7`8q:+;T=Y:73-($ -W/ſjIȿeC\׼s $%0!: v(qtA83(S݆Jal`^ d/#).26C9 ;<=>?R???????@@@z@,@?$<77_1+S#? *F٥T^` S BņHQu6~ "%'v).'s#zZ p3Lt+gChʨs:iS$8r \p!+(^/w6;?CFhHnIJ J:J[IHFDCB ?=:G@F5JN0P@Q POlLJG/DA><;9652/*% - L4`9OJL ѻ Lxū7z)_.Ipw$*/L/+%* <)(8;νɭ3QŪ05;OVaI!)T07|=CzHKCMSNdNYM4K1HFDnA><98642m0-a(m#W 5ǽCȹLlvþuSF_4m#(,-*$onіżĽfշb>5&-39s>CwG$IKbLhLjKJ1HEC?<96310!/B.+*';#2vuӬg PđԉٟQO!r  N&((4% . 1 T 2ǽٿѼ×k֣:C#-*A0L5:N>BFJ LLLKIGhDBI?=:$754P31.+)%!a8 m3ʾg~!ܻv{b|Fv%w !%#5#0 U ]y:$΋ȁ1S9ezG )G'}.56:?DYHQK9MONO.NaM;KIFDB@B=M;K98&63 /,7'"{ <þ;xԻw ĩ ͤڸ'vN S 8m m,:qړaTJ d|l*!sog""*D18?DJHeKMOOONMLK HFEmDA>v;97|3/+'%58Oүnx&>I$bhLڄ h Qz ,];ҝ;y:j|Sz [;&.=5(;:@EFHKwMO2OONN]M JHG EC@U=;840,(/"HS"A@*~I Ȫ"ѪS:Rt,Av  DrIU*&;Y<ǥY:uw) #+18=5AEIUL@N*:75B2/D+|'C!+ Y J2ĤΊQű(ekݬ_9y&+iR X o_G :ɤ:ܝ ('.49=ADGIKJKKK IGDA>:731,.,*;'%p" (h_ޔUђ̕ƽŲgšAǘɣVa ܉]mf*  JQJtwZh63KX"M  F")q/5-8;<=R<_^&$M@ gj!!j!"H!AyP+} ` ~ .h+{W.#I`Q~rg^: u5 d,)vS=0] O }ycA&{Jmq#BF , m`( 8!f)/ 8s~l 8".###! ]Hi&AjcݱܳLޛv?rXUZ7:k  !A'hK 0o_ 8@;0^P+3X9Ly7C,fp{t < 7JB"% &'(2(a('P%$!e<Y A~H +a5eΞxH|ݡpM 'xuw h:u` 5u<svM& r4dJr| U1<1cxL 3>lDk Ag"B& ),./02!2210l-*'q#r l AkZxT$`KՃӨӌԦTE9f)/Sx P w = ,3Jg gl$).Y1467=6}41.U)$X3 @OL=*k֖ CУ#oEyܤE A  O L a X{ ; #'*+,(,S+*'v$I pS A 9/qxK,cr93=P.FNKFHd3*x2 #8#(,035665 3 0x,(I"$M"T.޺='|Q;y͌l< h5Ul]=, /^U1gXkeW9 #&)+-.--z,s*'#Os2:ܩسFC̠˗"$s ͈҅U#GtM*X!=c4:7 BA &+$/4e8<=?oACE^EECA#=B82,%X Pֱ4$ńm Ǣm1<ӧ֕"lG6#0G\^  PS|e#).38U;>u@BBBB$@/=83.'BbQI? ѳ̬^ `\ƿɅ˨nҭס2 :  H U 4m"'+0}48:6(02)  M{Ш@ABPB@>< 8n3-&X =* ,T˹ʓ`-r-ҏ׽ډݣ9--  D\~ P$N(d,04W7:i<>f>>=;8>3-' h ,4+ӅІ(+ʈ\ȵf^ȣD,ΫЍuԯtwlr`1 (@J "$'),G/147:p=?@|A@?=:7:2-("yg A)lBާ$ͦȠňœ-#FɅynZX׶YC)}$h "YI}zr"&6)-159g;72M,M%C k\ Jϵyh}8WbѢԺ׃ڤ@ YU vPK 9"%(+.14c68::;D:9852/+&!\Bv|RSB$ڱh4Fβ\̰'ͮΈv^ыjsk?=sC &$ #`&S),/258;:<=>%>N=;9|630+&k iN &T%sE؀*nbǎƨNjQKʔ.хrՁ׼ڒ?pZ- sj( #g&(,C/258:a<<=<;97;3/t*%Cswۯ/0ϵʛǷƲƳ-rȴJҁbجܐJ Q R^"!#%(6*-/14169:<<=<;A9i7 4 0,(*" ]_Z?O_9΋̜QǥkLl&PΥӔڲ!"  j}G!m$r'Z*-025a7:~<>??c@!@t@N?<951++M$rY 6܀1 ɭƶN puVCw[^ ?_? !N$&)-<0i3\6 8;\=V>?z?>=;96[2-/' Ok }[թΌ˛D|-&ċ.ālƑǪ͟Ћӹ׆+-'lZ ]`|=!K#&)++.1369<=?e@,@><:D62-K'Y   %!X:6'0*# /۴"ewUŶ;f7H1+$  h%gӵϮ[ɏ&+v@R:SxB C `|%I~< 2"r% '+.w2 59=E@CEuEEWDA>y93,% OcRpW۶Q͏ʝCE5ºu4F¼^p*s^PuK@ @L!G$(+/3n7R;?^BJD[EF>FDB@B.EGT81)Q = u صDι+šgM-[.İʡe<$=<  ) | JZ~r3!2%)^-27=AyEIKLDKJGC>r81)!@zng~#9ł'VW+3o5Տڋ߿M* $-}_!U%*n/5/:@*DOG~IKGKJ}HD@:3+#-149SM ˦yŪÊ~ tĵd|wrߨ=Iw / ` > q=6KsS"',17=!BXFIuK#KKJ0GC?99z2*"B@ ! a?ck_i=aؿ9Dþ-Tujo[`9B5G# 4   >.8"'-+28K=]AEILjMfM"KaHADR?92*  t~HٞӿΌVĕƒ翱 ۾*ORR13j* d |  T df7$z){.4:5?"CGJLNMK|H5D)>81F)n2x3)R؃6ƯöUn4Ùƽɹ̢϶ڕޙ"<dls 2 P_~B##)06G;AEI_LvNONcKHeDV?G9#2 ) = ɧ'øb}[ǴZ2ފ-KnL"8 YX> > (k#(/_5;A&F JMMOO2ONLHC> 6.t%G(]xG%S4d0Lɨ͑Ѵ Yh9!&4r#Om+V lg %,+28m=BsFILOONeKGCT=6x.z%T tM}NbdbćVIgHCȌ"ҵia(U:&[[6tq ;=y &,3E9?.DYI#LNOOlMJuF'A*;4,"V !f&٧1ýSZٿg3ؔ?߮Hs9iROOvy PT!(_.5|;A{FJMO#ONLI"D?92*K r yX{ɐ&L6ȾؾTY#~&Cʡ΂z)|ܮD `;Of #q)07i=[BGKNMO OONVL0I"E7@{:3+!,bt2x݆ѱȰ3j3tdΉG֓v݇HA%uXOG: -jl?$W*1=7=CHeLFO4PPOMIE@Y91(wOw υ.*-mv|>?jcmr^P{ @/lX@H &##%M+208c>UCHLOQQOLI%D?&8F/%j _8 5ӆ6ʼnʿ=j>otŖ̰к<٥^ -'Y ?LR <&-4u:AFrKNQ0RQO@LI Dz>6-%!`F=}ѿ̪ȁ-šǽEi`*'*ʹӖ#YQ LmT9pm3G _ A'O.s5f<*BfGL^OQ~QQmOLHC=14* uplr_ϳ*Q"ᾗҽ徾/}Ť@=f ~.PcVS !(0O7D>%D\IXM9P)QRPNKIFk@X91'E \aInƹz߽оRrKǬoώԇٞݹ`^X^~aAWuK[aG!tg b$,+38:?@F`KPO^QRRQNJF@E8.#.O B*+n[_1VGۖu?P+':\LpLLm{ 8TC&.(5C7!)%07>EJO/RTSQOIKGtAR9/t$ ^1uΛdIŸ2^}3>:%KJ8 {7Pil De~#+3`:}AFKORSkS-Q-MJ*E>5,!X 2/PF_bwKGo¢{̬:۹yx}SA2mJc R&-5ZE8JObRTJTSQ,MHA90e%7 x/?X͉7pJ˿ Ͽc˦-0p߭uY!rzxpb!A{) $,h3;AGLPSU&TROKF>6W-5# BD=ϡȁŁ'Ty^%n[%s6׆|sN v9e+sx% <`0'4/ 6=DJO2R~TUTyS>PLGA:2((s1?ʸDŽ/(]F^˺klBr^C@x%$HLD Q3Y 'F"*19@BFLPSUUnSPLG@n8.#\<) t^C) {vۤUQj9? b] sJ%Y,41;lBJHQMuQUV\U}RNIC<2(+}'9#l^J; 9P_ǘ/y݆%U> cD78 XA m( /7>E3JOSlUfUTmQMH-AZ90%\ B')@~)ŋÍ&Q kOú5էh!9f8-IoL<J 706@Y a")1h9]@GMRqTUUT,PLQF?6,!0&wݘwGơɅ|ݑ=%)W}lT~]|&r$,5I=ZD_JOSHU@UUR#MG@7.(#l/^?ȳDj,$¬÷!+р\aD+G #g)gD\NLa fc!*2:?A>GyLQTVxVUeQL,Ev=4{*/$VDݰ>UǀC5bwķǘWٛq>y #,_4b7+S!_qJ M:#,V4}οҠ׹vI%8]QW)N $#(+\3;CJYPRUWWVTPJC[;R2Y'*ԇÞ«.˜Ƭ͉c܃`A*|*]#a W+'/8F?FMQU,WWV*RNkIEB:1/#40Tݨz/ƢĈDS|˶xw=}W".]S!IHu #,;4s<:CJOOT3W&X#W-x9La9cԴ%dlx $9;Ce(1:C3JLP$TXY2XSUR&M#F>h4*Z$ۧյp"1#þAǭӓطݒVUQ-h0)PCM;-ca(f08M?zFLRUXX+V/RNrzƇb͎ұ܊1kBgA_lK|.mn &/7@mHxO_TWXX$VRMG@7-b 9݃qOc˯b2%P-ĩɐ̴bX lpzw5I?3ht_kTIy.$-5=EL}RVUY)YXUQ=KyD`;1D$ y(zҒ@8ãËs^ˤgg׵&`ssX&1yN!n 7 "+t3;BJPXTX YYXVRnLF?"5)K4?Fl̾-NƔ Êr5Ō&<̈٪NqKN%oX7$ V5w- =;'0#8t@NGN RV7XlXVSOwIA7,a ho`<͟ʨiƛ)JVIȇd!!sWCA~ DZ3 %.O7?G3MSXlZ[8YVRKD:0#''IWh<0Ŷ[ñJM(Y׈߯>*4 IYpKTz KK!* 2:BIPIUDXZRZ"WSNHW$šC6?ܥ?Y  dltoqgsA%  )U1:CKQUXZY}WS4MF@=3Y'R \4/PϷ̰7h «Qľƿ~8Ѱց۝;+"4u&wS uZ (1Z9BJ2PCTX[U[mYU/OH[?4M' Hg1nWʆȄ6&ŏʼΞcTܲ%>_!78B$?"1 %.7N@I8PQUY[[YV#Q3&& Iޭ҉ήŅē#ȰB8n<  );Ln)nQ '09@AlHO/TZXnZZXUUP\IA*7z, {"1#6̙ɣǐcmLlGѭmF p fNZ<<  z%G.R7J?GeMSaWYZYxWYS5MD:/y!+ں԰Њ+ ĊÁ«,`=Ѵ{]$TO'n cFhJA 6S#V-6R>FMSX=Z[[ XU NF<1#;}Zݐ־nŚĤV·Fc̠Йހ2- S w MUvVIc ,(p09AIZOU{YR[#[MYUP=H@6* SߒD%qȊfâ¤>@gY}Pܐߵ9vu \Rt_)}3 #&0H9 AHO2TDX ZZYW$R0KCP9`- Uc֎rʳ;> $+EUdȑMۗZg %~ T"4OjTQ #,6/?+GrOU[]^\YU9NoF</!m] ةz"ȪƬãŽr2K$ծЈx'.kyL+O i0 P@g[)X^y L(*1D:@CMKR_W[\\YU{OH_? 3 %\ R$$І ) uňaj'4b s9 Zt+&Jz2]z` 9F$K-<6@gI1PVZ\]z\9X~RJ@4(i=ߠͮFMSX\`]\XlS2LzD[;/ ,I;VET&0!|ą?~Q  i@4f# !u+R4=F>M`S^XP[\\ZVcP1Hq>2$cqYTޟ-pǦō‚4<&)4 1W{6gW ]t'1 ;DKRrX[j]+][WPH>3 & f ֲ̏ɒ ÄSgL5ƅά^~I uh]& QZVf~zh 7/ %/8@HO4T|X[\-ZKVwQ)J@w5)pji[ ҉qMș?[-šdĴI7k qbR DcZz/>xj g"+4=EMSMXp\]'[XTPNE&:/ ! `Cٔ=Vţ@sHzƵ6ϨDځmp I@  o9 U,/ '[1:FBKR*W[^^\[WPPHc>1$ <'ܖ08ougG. I bDf9e/q  U$.[7@H}O-TX['\y[tWRqKA5)_ؾDəĊxioğbK[ӺلJ^_ D T:Am ]/e-߫HGL7Oj!+T4=FnN:TX[[?Z9WS'L)C:.!as0ԛΗR{ͩwj b!G* DC%w]Mog \ +*3> GFNT^X[\[nX8SME;/#7 v g+7;lSc¼m` cM  e0 fUߝzk -&0^9AhI`PVY_ZZYVR'K8B8 +>іp\U<+4J0ʃ]nz\C  |{߂<ުX8 /VK##I,[5i>}FMSJWZ[[ZKUO5GGYPTsN:Fo3w&. [F,̳ȏUh{m˚ϨENSC^ j! q&#G vq ' *4e=FMT Y\\Z`WS;LC9.!+҅ʹUjodk4ĤqΞGkC:$1 )e3 XdZ߫ߡl/$~ ~y'1J:cBJRQVSYZZ,XhTO/GI=2& A>'It¶ÐĸͅbCۜB ] >TA&z߮ް0\hg<$-7@ GNSX[\?ZWRKC83+Lrcޟ̢($8c|Ǿ?]vmPE ~Yjhr?>_S  =) 1:DUKQVZV[ZWsR{LoE;0r#X 4$y G~n2C>Ŗ|sDݨ9_ Q y`$i8rZ0_x* %A.8BIP^UYvZZ]WSSN$G>T2s&pנн yYLǰ[~& Qp suu:޼ވy<![+T4>FlMSLWZ[ZwWcRLYC9,}dSIX{Œ{ƒU&&ڌW Z?{@$t9߫I}C 7'0u92AI:OuTWXXVSeNFq=!2U&w5 c_vȴƩ|©¨1KȘ̔iךKT vu + ߌxN0#-6@0HOT=WYYWTaOI;@6+#'S sʨ1gÃGs"A#ځ$eC'BM* ~YR2-%)CX fk'1!:CJPTWY"YVRMAE<1o$ tEzĚ*HŒ+Ƙe[ߞ@& Y.\?HS4D8$-6?GUMROUWWVfSOEH@*6.+&*Hujxmǹ|Pj#H{?$2gl  eBB߲aބ-ehZ. Q)3;C}JPTW-WWUR#M FL=3'2N9BЦarrBOƤ"ҭxkNZ Y Y. b [zA\~*=#ye$2,5f>(F.LQUXBXVSeOI,A?84-!M }"lR?8ğb\ǚNٟiX ' X^s 'B>߁E{ 8g/{ ('1:C0JOTKWqXWUDQ`KD;0%88*W%wÙ8o= OL w )9z MJ?>A"+.3-F!k mد8/FĝP˜Ê ŵ ͎߂<X_b Fe AF.n]8 =(08A"HTMQuTQUUsSPKD=3)Oj6։>sDJ%ȟϝ;73)I 4 um=6|G( z#e,T4=DjJ]ORTUiTR8NBHBn:I0.%%~ WC:Kԡy'Ę( }ɚrKWEKQTV VLUSNIC;1F&? OuCɭƽd`qĠ+1dlbD F 3sZ%NXqt+,I%U.7g?FLQNTVwVUS9NH]@=7!, ٧61téǜ̜4*)jzٱ t\JBnCͲ-cZHCWWDaj@&"Vzߋ=D Ai)i2;DlKޙk3qf'2 ;D{KTPTQVZW0VTNP1JC:0&9"aܨ&#J%:ĸ β;BzMx0g<cLT>eFޱSTj0 tx +n5>F8LQUWWVSiO9IZA7,! ^v~AŠ_m_҈"OtO:  .x`{x|5 nR&0:CJPsTW4WUSPK$Dp=v4(eSyHЎx=…鼫-1!9̄.9vM!-!% VmW*,/<R0r)4Y=FaMRPVWXpWHThOIxAV7-#X ?`5 ԩ=Ē/o*iɗאߴ3~Q hH! "?!U{Xsܚ$ڿgd <#$-6@HNRUWPVTQLEu<3 (wW$ҚzȱĊBF%yԍHwxG!! I`Z-D;;4׹׬_)'02K<{E%L/Q~UWWEUS-OIB}9./ %)g$ aoŌл׼տžAՕݞ( y ![## H xْך5=kg<')4q=F>MR7UWOWUsRNeH@H5+"{ l8ޑȀU~/»v׽mʉ{k /!%'% AYՄէ֒9=@ w"-p8@uGMRUWW#UgQLE<2(O'4lPqi!ۺ!Ǫ' SzO#%&8#dl)hA5 <')*]*K%@ @6yذԋZϡCF 0,i7ADHNSVXGXVR4LD:0'B Azvb  Zƚ _a@ V#())'"Z/ >֓ϼ)?>O &/2,+\' uD$՛ј,=ϔ ((k3='ELR,UWXVSMF]=4K*Q 5:coT̕2$K^Ȣϯٻ=M"*--*%%5 6q ܢ%Ӟ*Δjպ|,57@HOZT2VWVTsPK$Dp<3_)X(gr N@ T'`nqfz]xY'$+-,)#$ y e)̭_ow j$0;eDLDQU)WeWURMH?6M-_$e,s? ŜU^Ϻudťѣًuu M$*.O.,( !bn^ Ѽ]l˞469*5k>F2LR>UWVUARRM!F4=3)G &zW€P NjC-&,/]/V+%)4 9[wժQg̎eΠd 1O"g.9BJ$OSVVUSOCIB:2 %EޤXqʲϾ A!Q)./,g'">cPTW0WjVSFO!IaA9g12'F,3ɣ¾b[+bx,H!- !).0.)#%B?Bk }.sۏ$F %%1FMShWXX9V-RME;1N&/&YّzVӾ^ø0uWνߡ0$,z02(0d+$}m0..?{.˚\~SחxK!"V/ 9CLRSVuXYXFTOpH@6t,^"@94O|~ðMOܧ&-/0Y0.J( O%ץes ^fNml 3&2=FMSVXXFUQLjE~=o51,!@ ECǩDùߺ<ȏ+ )".6//-,%L +Pu̕ɸ(mߴk-9CWJPUW$+/1..X("|#=v֗@$Әgm Ds%2F q*5?HsO[TWYYxWRM|Fn=02(A գ͂q߸4ȁg0j! %-010+#~ NT#}3Ώ{p0`ًJz!6.]:\DKQVNXYWTPK B97.#VC5!BWxپ] 總4Ƣ͖ ]{(.1Z1/(!/{=JϮGBʆα԰R&-K j(5?bGOTX;YYWT N'F=2( )' Jȹqcſ 7]%l,/1e1$,%] ihT&ʵmй"f24 .9VCKRW8YZYYVQK1C9.$} )/}e@ɂO ⷵ?AԔK|*B023-0I) %qО}}ɫ̩ҍڀF '54q?HOUY[ ZXvTNPF>B4)? tޛ_Aż4>&E,^/21,k% Pci\QʑZKA,8CQKRWZ_[ZWhRKC:Q/$ ACړҠ=GpO8UCYN[ZXTO G?5,o" aGM ^FdjOuI9 )/q10- '. ;f:{!$MIdz`Ձw5 ,7AIPXUmXYY5V7QK(CU;>1& vَk&  ˭hG %b- 0v0.*"Z+"F2iʏȑǰȩNsm }%2=F8MYSFW5Y)YXTPJPB8.i# w+hEܩ]5q$X=֚;8 o)O/11.c( Q-FX~RːȷOS2r+'6@HOTX/Z/ZVXU$OIO@U5*qY' MNҖ@?׵NWKr< "^+P020+%,n @-j݇ҞʫȒǐȌ4;Jb!.:DMcSWZ[YVQJRAP7.s#ImF x\Ӹ@7O"m΋i "(9-0A0-s'/ 5C& Ⱥdʼ^՜<1)'6@HOUXXYlXrVRM F+=4+   ڄɨ'·ݷIh ғٔACS | (-132 +#}~ X#C {)ƼȜ˫M!.9C+L5SWhZD[WZ{WSLDC:1&@z!r|ٺζWŜ'.L22.u(i!1gZGqJ Ζn {&3=FnMiRWCZZXTNG?5+!  -jM\q˯Ů5f ]_o%6' %-130+h$ #GyW6\$KئHW-69[jobYB6¼_٩ |T m(-00,y&= Xu]iU*rui֟~bx+6@zHO?TfWXXWUQ>KC\:0&"iܢ|atɼl txūjloEr 2%,/u07.N(!1yֻ_ n4 t%2=FMRS-W1XXWSNG?5;+" 5 B7=ޤϗbݽaa͟#E& l*J021w-'^{K C^*ۣoșɗkǘ6۫ C)4? H-OTX!ZZ7WS7LEL;1m'G -lݨswS͹y#ɎW #b*/0-(Z! +o/Ԙ _ɕw̘ѝ 3  ~-N8BJ2PJTWXWTP+JA7\,! ۗxмH[սՑPG&G+R.z/y,/%aa9zU>da"y΍Ӭn} |&p2=F;NSW1XwXIVyRMXF>4{)O jIpej:"Ly¶5yy (,/".@)$8h c*б;Ph  )O5@RHOnTzWWVTrPlJB>900&8p :u0׮θǂ+$poF4LzPIRFSMSPLG @7.%W[7{F9  ! '+u,*]& Y  @Ժϛ7ɹERF*u~!>-_7@#GvMjQTTSQ,LE=V3*!, _kɎ(y~kJ˽p5c#*),,r)$V<`߆ne̴K66` #*& h r")݁،ӈ˞SΠԴ1Gj d'2\;CjI4MPRQPLFM?6-$.VOG}cķi ÑCCcٻI>~#L(+o*%" D}~Tѻ͖ʝ.XrϝޅTwv+5>F?KOPPQPMHBu;73*!#_T.QAÐm=5DI  %*Y+0'#B ..6#*Ѝ̘,ǾdֻCvl!c-6>EHJNOP6POLGA\:2) b^w!Ҝc!E~b3R|zA !7&=)v)')!tYW/٪Ԏȩ*ѻٶb Z $/9F@G9KO PPP@OLF?77//'dt BV3֎ɪ&MƉ֟KC jK#z'**&p!/ h+UqZѩ̳EqVc5% '2;]CIVMPeQlQ\ObKE?7_.% ;`ɏħɿ!(9/(GtQʃQޭS?Lg"u-7&?FKO*QRQcNIB;&2 (1 T)4UؚɖH\ǨoӼ5I, g"A'+,* %<;ȣ֡x iM%!1e;AGLPQTQ]PNI{C<;3I*  71ޤGʙČ[yJ+7 %!&8*b+(w#h =u I5ŭLЀW$ 6&1:wAHLfNOPJOeLGP@d80& A$'`\$j•5;J֒VMa#(++'h!@v\ #`Όƥ=x&.-*4=SD~J4NQRROKE=5-D$J s .}y DšAS%wMa!@Y,!%N)`,<*% b HBӍ*`FĝI6w=\,n,e6?GGM PRRQNIC!;3Y*  Wr۞ԨhŐ żȦd֎V޸G2 c1 b%)%*)% 6R: sٗLnǢƔnΫN"-7?@EOIM@OVONYKG @9x1N(|J?83 3+d¹ʧ[8%o!q&*)*($ &q]ݔAe̺%t,GC V&2J;C+I;MP@QQPMGW@j80M'] *p̻ħFzGSvhS2K#(,o,}($ + EWԚ[Áǹθzv (3P7.$ ? bc(ʵ#=6$W8ұhD`^\ z'+,*&"X i'݁ʓ%u, ˲|ܶi%F#&/,9AkH]MQRTU0SOJyD=<5,"A3"[l'~ !ybn I $)/-2/B-6(#85  uwk $x%ee#%"0;CJSORTU"S-OlJED0=a5-K$[ fOǛ 6yMU "(1-/Y,['" mYhSj,țB (4=rEJNRT TWSOJsD+<3Y*#5F]PØۿLּ$=Ȍ29߾F\).,//- '!K-5φɻfHǛΝL6-W 9-7AKI NS- l%{*-0/P+D%C>4 BMD^p'F#! k'53V=OELRUW-VU)QLF>4) 0CeӃ̈G̾ǽ¦H.ӏ `yb&X+/w1 /E*j$ vsيѠyƼ(éK:[ %)5;>FMnSPVWVTQ]LbF>5* b {{4D Ώ+ļlxl͑[ڎT|n(|.00T-K(;"8<aa)UkèV~y^ +6@HNSVHWnWRURLUC:^1'OE:t;êmuW d$I+13c0,I&F j*̽ǦľTN< "0;D KR%WYZ9XUHOHA8.# )&ւŞ\R,Я֝܅A!L*/22m/V){" 8ڮҍLW522g\$r1=aFM*S^WYiXV7RNAG?[5+!: kwV,1|+6ߠV |% ,120-2(U!YGbVאQvƉßDsK/r+7AAJxQVaY^ZuY%VQKC:1(WZjϩ"D"<Ό9L !t*#1G5 3/*,$k6 ~Ox۬̀PwmPݳ9$1=4G_OUYzZZY3V4PI=A9/#'}p#ƍۼEyw5n"+1T32J.("AEz2؊ѷk8ļɈ F -).6%@GHPRUXYY^WaSM4F >6+n  R+| kz*޸#պbB<''2,13c0+% H6{au][P)(ݟ"/;EEUMToY"[B[dYVPJ;B;1&)i (ҚXпռEn`­ɾѸC!!*/2>2/u)#}C 9:Z<̞DzÈΐ; (~4?HPV#ZB\\$ZgV@P)I~A8.# wtBֈϚ+ܼغyĻ2ƨ,Y y"+P01/,*' [Vf,CϷccdMq̖ӧEy+6@JQVXYf[>[MYGUMO9F=44*EJGmaܑӈxN|cg϶֗vcU(.23#0b+&x V5f@ǻU<'ș>88 $(1=}FNUZ4\-[ZVRNLD;1,&> +Eϑf"׺Zf|V"Imy#,02J2j.(!'j߶gТ˃DŽ$AѤt` M(5;@I4PrVZX\\ZRVPXIj@6+ ܬ.3Ľf9͵ޙro&-1e20+K$ mdh/xODR,uΠ/P @-:hDLhRW[=\[WX8TMD;@0$- _<1wйٿ{o'`6"c*042.z("j*O/1)߫؟2|Ô\ ѻ L p&3>H5PWVpZ#[\z[mX$RJA8-a  QX- ͭYԽum`gH?S a#Z,p010x,&* 1CRʼNj2MŤ̈́ԞD%:,_7AJRDW5Z\\Z2TNF=I1'/ѼXTrÍaP '-0q0'-f(I!MS' ͫɟƧTn@Iu$0<'FOUY[\u[WR8JBo99.!& |]O(¤5LVBՋݷCk"+/130,%d  'DŠqȣ?by(5P@IQVZ\\+YUPH%>5+ "orӯ!.Ϻ¿-ыط3VY Z%!,/:/-)0"W TF Kf4"8.49CKQVZi[[XU NE;1k&, 4$kсEvM[^4?/N)M.\0k/,G&C 40w ҂zg7͹n F&3>(GNhTY\][W)QJ'@7#./"OṢŜRGh!? Nbs4 "k*/"/.#)# 6 ;3QKܯ(3ǣPfˉ ؄#L+7[AJQVZ\1[#XT@NOFu<3O):ISЈ[M0c˘NB>:',2./ ,'Ov1,٠[hʺΞԄNb '$X0y:D/LS0W[\[WRKC9[.#$ %j#ʿ_1&MI',.U-*U#|X xm&tCOitޔ{(4>GNTaX[j[YV)PIX?5-*z5$_ܑԫ~㾟@i ť ыلrW y ?&*,+7' Vۮup()bj{.P,V8AJaQWZZYW{SM,D;1&D؉HuG=,!sanp7 l")++)$w 0IiԊϷ̶gVг/P RP#/:DLSoX=[[YVdQK#A6," 7N4ȇ]ѽUļɋn& "(*N*'!C/ O{5؝ӏϼ̶XzFIb'3>FzMSqWZ[YV\PH?5( K ۓӑͷȇÜP.hC !#(Z)s(I%q}%5̆Zܯ$'+A6i@IgPCUGXZZWSMQE<1U&V..f/؀(xF.W2)E[D&9 n %_))'"u #vdՄlbBh( ߆iH ".9CzKTQ`V-Y+Z YVRKC9T.">P +0l=fS"ϤZl <9#o'+'7$ WCHEڄiUΡ8 л9#[h ^&41/;}DKQV XXWS'N$G@#6+CUiFMSWY_XVRMgE;1 %v=bTպNZ ] &3 m"c$a# 9 ?9KҕϢПӽ:JGH+6@DHOSyUW WUPjJB8.K# v2ʊ1!1>YŨڂI&`W!C"!S r,Zb8߆ڙ֙ӉmiҪէN" !-7A HNKRUVtUVSOvIcAY8"-"r ,5kɣǀŮ&9ƶ8ϩA '!!FZ cpoߧ_GuEmےN $_/9BXIOSUxUTRMG+?w6*) iu(!+E LI%TǚF%u/" IOw siҦ%ЦqK݆rR@[& 0:CPJNR]T\T1QNK!Ex='3t)t:dr&[*/ʉn7Ds N&b Zi(׆ԥOxٸ޺<<[l%0?9AH)MPPQQP$LGA9'0[&*wJԳ[v/̴΂bո<i K .L+cn޴1VՖ\؟Ig P$.7@XFK!NLP$OMnIIC<4<* Q '.PAЊ7;)σѳGގ  =v T|Az''b%SG n+)M2.9?DG?HI"GD@;%4,$"  b=FFUrAJFKdҁպ@p 4GD0z&lS?Qn@nvY8,BX! S$*059X;<<;962.:("0ezkآl٘ۉGUD@0,;L3w~u jE!s.NQ#2(],/1373{21m/ ,($ (] _ZH}߮^l+M^F* `np,MCgs !9$')+1++*)&$ S mU"@:e7Vo,*t 5h5O-B[p +M ~"#$h$a#"!,)b 0OC7K DhbNa=ah q3] [Sv F  s  i?j~aFnZH&o[(ma9 T 1 _FiiU88{}8 )(fy)   Jn^",01_DI`s?()  |Ke?:  \ 1@CB:=\J"*d^+)ZHDz*Dq"|q V R < bO.f ` {{s2w>LqoT@}cj.< o3 . w@b S B e Xk"-s= ,uh65W;_9+ u > ] Q A  &_3 q5AuaR# 'G(nL AOVfQ(J#c  Ad>8|F:':w mtARz j}mm?KY a^Xyc&$[ ,M?a58 jU1 75/L?yzF "j?$&xZf  KP` zIqFy(K ~m n5 \\> I|%H  G,Ul? &S}e)c,X9_ Ar"zHE\ KR!x"g"""! + LvQ3;lDGYEs GW%ZP =U4 !""c""!fj4 NJ#.0$'E0$p^;V=n(md)"X~{6g0(tk kV A!#%&&%#!c ) owyu\ ?D=:R50+`$O?YXٙΝΠ=|rrZz9  >Y)CI D#+2.8<@DFF4EYC@,;8B4^-% r1Dڎ]ǯʢmII"*q  W1n2y^}E; #+3 9L? CGHgHTFDB?;6/(L!bTA=͘ʹ[ƆK1Acv C ={?'߹Jo9z8A0'J I='؟UȈxQ߉ݰ`߯ #,5ʡ||=1 pd F.$܌^H;#a,5=zDINPQcQ OrLYHtB< 4,"M txQ֠Ƴ^ºÖUp[ Kj \B.I+ݕ۲ښږyu2 !,#4<CJVO-QRQQsOJEa?7.(#f/&+H>_dǷй|$-^ ++)Z d Y(jd t-;kUޤ܃nݒߖ[@I / M*3;CIPMPRRPMIE=>~5,#H?P$ҿ6b ]̀l:0b U HlcܨںޟKcw #.K7?FKORdTbTeROO_KfEc=5f,#*\ +_HT˲amĤ1$3ZHb|e .H1=p߂܇ڱzށ< ",5z>sFLPSUUpSPKF?7N-#H(ey+@ @F éYּݍbm g'- !</ pۗzRmw Q"-h7@qGwM\QTUUT^PKE>r5+$! .k܀oȕA‰ƍ{.}= `dUߒ@ ۨ߆z `$.7@]HHMQTV_VQTQLG@6+!KQ 9&!\ɹuD'KـR&MMs Dڏj9ܗAOS%/8AHtNYRUfV7UTRgN'H@6*fLlw';ʐE$¥Tɧ؝Na _ xIt*يL9'߈Q4it'24E(.,_L*֨Mr>ãI̭-c{=8?f:`ڪ,='9PR'2UG@NTXwZZXUQL5C8.j# ]nJN؄~ƑĚ*Kc l$.^X&W"  ^?nB3ي87G `"W-D7AJPVYx[E[,XTPI?5+q=s4 թby{¤T$<-ޣ1$bRU +cwh}4GںbPT$$1/:CKRWvZp[OYWSMFX=2&'ۉeØif¾ğ fٶ}9% 3rP3x#-,IzٜzvR#^&1<E>LSyX4Z[vZWSMED;!0#* & f¼) {V9*I0ZV Z ,wvݍ04S:h{.l:*5?HpPUVcZ/\a\oZWRrJA7,.x' տɿ¨3ʿϩݪ I  lvs ښج׏Yڈݰ$ f".+99C%KS$X\ \[XTNG(=l2l'. vF7=hs5_K-.~ \|wtIr&3ׁ׊EocW&1<EMT+X[\[tX.SKC 8-" kGָѺ8MpQк׸<  ? * /*(Jݕf؇7~,Mu`a < "+7KAIIPVZ\\Z[UNGJ?5)5B+N@A̿s|PƇuD.P $s$"IO/:]|ܝ&֜S8 L#0;D~LTCY\V\[Y@TME:/#>F Vȃ"]U[PC7)u~XuU!$$$!K d\gc"B حz֦o"T 0u(4?GOVQ[]a\ZWQI_@g6K*4Hݯ֌ &}pM?~ a &!D"$P"l %4 ܰ*խؕ|/ !-9C K~R{W[Y\\sZGUNE;1$4 2euC)̽|šd Bڒ_[ /,",%%!KCY>߻էTf"߸r{H n&f1=YGOV1Z\\ZVQJB(8-9!z!7vؑsƨ.mlt|vZ՟(_P !$&&" Q;}~L2ԷCNدl*6z@JTRW[q\\CYUUOG>83' rjNmkdZMٸt /$'r'% C .ZYjҶӠئ*/ $0;nENFU Y]]\/XaSKB29/# f4{Ưq|68ȸC_~y #(*)%LQW GfkQ~l(4|?CHPVZ\\PYUOH@46+)ݗ֗Η1ċ25ԼӿvcжY\W!='*;*(#M+ 1p+фXUֈO/ ".:$DM"SY{\]\Y(TND:J0&"c ʉ׿̻ ~l`̊-NS!)- .z,' =E%_>cy'Y c*:63@JRX\G^:][IWRNJs@p4)7}~V4$fmȊ8N*ā02]* $*./,a&tz y@џϳ%oz߄:m|R!3.:DQLTY\h]\uY;00E%(I 2֝QƟeµH71^ՕރAt *2/6'64:/j(P! 8&Z֌!C=a!Пւ{n$*6ByLU[_ ``^]=XSQ-H?=4n)E5qtJߵ}",yAE&(047612)"SdtRΔbȘZkԛۼM-"/;{ENU[^_^pZSL!DH;1!$ d'@ķrԸOe|ļ![̈́(5"-s4886M0(  t۞$WL(l#+7CM\TZ]__:\ WPH@6)}OGȵNƵ0нɚRE$ +2t7:,72g+$lBW{FcAAYS- QZ'v3?JS!X]`z`^ZVjND8-"-I&4³> džhngo(1Q7:j:s6m/ &rX#1}604ǂ|Ⱥ%ќap{y .d:*E%NV#[R^`I_a\VNE;0% =mk̢d˺F+ܲ.7cd˶܎l#;-o5::'61*|!. DmiȿƺkE (i4@fK6SZB^b`$_\WOQ"I?5+*oix-QT6ȳ toڀ 3*3q9v;943.'5yW#xZȌ^"0&=8 !Ȳueln&3ߐ^$%A0B6:;81)! X}led4ixՖݨv >+E7BLT~ZS^w``x]WgPH>3N(N^;9 龷Q߳Cvgx<ʊһ۵>1!-5i:D<:4-a%zg|ަk˄ǟ,pƖʵרxhz$1=HR YY^ab&_ZSJA*6o+{", xWFYmϷ ޲BͶ_ڟ@N ,*K39E;l:71F(Q E[ o7@oņPCs&ފ .:ENV\J_ao`!\|VNE;b1&n_˰ʼ̵<@Cժn%/6;=94Y-$w eZp~ΉEjǂ/ pW'5IBLTY^``h^+ZSZJA6* mHŁҺĵ2״ 8 Ӊ%/6+45::<;[6 .&J6ߤнh~ʉ1<iK!0>NHP=WO]a[ar_\VMEC!8/%& ҡtڻƷ*H.IЗ(2Q8~<J#SY^a `^YqSL{B72-N"P_5J'TUzӻz?|a *388;;70`']M̙oŸñ.GɲrR%QW -:eEOV7[_)`x_7[WdPH <1S%h .ʐoePǛ\$/5:3;9V3+#(ԳμF;ĵ6w۞, :1(5AnKmSZ0^``^ZTSKA6*'քTC+׹ԊoI9,75$: F޲͵߿ 4@[5#-a39<9k2,$n.h!&.p_Āǽ̛<ٔcwF'5?IuR:Xl\S^`#^YSLC8+ 8ڻLūҺ wqp =)17H;2;79/'8g߼љw6$ Ż ~XG! @-:fEO Vt[^`b_:\VND9/x$l [Zʠ0иHųAC4AǯyY!#P-49$;&82)! X+ԕ%Iĕ/e.U #)H6AKSZ^3__G\WQCH>4h)5OwƉF/)83(.( 5)Y126979 4-%>1]+2HAyH=ưȣ="ُG"/;ENV [^_^-Z(TmMDl8-,"I 5JSKKXbøɴ@ڷ½pɡ9aA [,389+61)t  B h6uŵƺ}N%. (6@J&R:X}\^^]XFPG>u3A'))Q#ƶR\ܶzRߗa )0599'4 ,$ bءɾsѮnKY"/;FOV[^_^>ZOTKB<7,5  cZܫE@?۹; aӈۆP) +268h6H0)6  v`֤Р!PɕεՋz>| )6:APJvQW\^)][VtOGF<1&: Ai ~u𵎸RNEB  Q&/3y652,Z#PWlShW4>ǞUȌ >v{C"*/;F$NUZx\]z\YS'KB7+ N 22ݺϵo†nѩ"0G*15a7950#( p 6 tݣM ~R?R '5$@"I|QX(\ ]][UNFڼ+%w7;'ڼ=M) 4/"(+-,,!'< 9ZW!ZVό[=`by#P/:UCKQUXIXW}T%NG>4)n,!ڲӠ%_R]Ix $)@+-A+4%g| zZ'Uj̈ʓ*մ݄ %1Ĝ% ;C!Rk!%x'^&# .:uּHR*e] $m/9BINoQSaSMQNIBW9|/D$4 r+ĸI—6̪&؂-c8lujG"%&j&##gl s՟2n͏5ΙޕVp ?%E0;CWIwNQdSRPMBH@7O-1#q yV2ׯbž'ű Ҥٴg!--h"$3$!uUS#R۲Vpz">y߶4D? H%w0:BfHMjPfQgPNKF(>5,V"c }#o YRAoNɒ͏0XI \#]$# IxH։gϚC\ S v'P2(;C HMP QHPNK4Ey=5#+! %G4_ܖ֗ѩͦQǰse3HgRN"#" (?[/5nԞ!<>Y{'2R;xBHMOQ"PN^J^D=J4+c  m`G6؃}HΌԛ5RG "#H"r; 8^iѰ>(|ЀԄږ#L)4ACC-  c! ?w KNT?QΧ͸Dn&"*4=DIMBO(ONhKzF@91( 2[xׂӏlͲ^ucw?G$PC] QX]ӂЈΒϝ4ּ|4g !S,V6j>EZJ:MOOSMK+GA;90&N)W8<=ׯz_mh:ޱ:w2_ B !>! 'VrbW +5>FDIMOVONK%G A:2T(P^ dBBϼrMȇʠG۴X  Y]q V$K5u{Ѝ҆=ݯ8/ !,6>lDItLMMLfInEZ@9T13(=] sc+.3lɭPɈOѱ:T K\V p$!ܫHΪOeP Y#.8V@gFJMObOZMiJ"E@90'  Ԇ|C*>϶Өܬl'3T F!9#uxϯσжӽuޅ\ .!, 5d=DKI6LzNO MJG[B;~2( .x wJ3˚z̘VD= GX K "M /m^%عШQӮؤ2( !,V5=TCHJKfMMZLhJF*AD:37*b  be77޾ٺљ"ˆ̸ҹpWF8 ? ݁ Ӯаv؂ z#Z-79?lEJLOPNLHB;2)  i\پԶАi̋w:ՠprG7{P!7"!lR=ݦӸE,}=޷>3 I!,!5F=ZCI"LOFONKH3C=4,$J\_\qpUʩȿ .Ȫʿev%3V` n"$$X! tܬsI^ՠ=A ,25=DlIMPPP2NJgE>6-j" {q (ӊ.Wu cD i "~"!W 3WnKb[!-67c@G'LPFRS8QOJD=x4*  8s{5BZ6b"q=m9ˇϾ 5bO^t 4^!!2$# [ϓήkӂB g >#/8@qG!LcOQRPN)IDR=5+e  >Z ݟz$&˴ƫl$ aW+/"$#u *$~`}͕t"!-7@GM*PRSRPDKE>6z,|!OZ (+h޷aA0İ:ȑvdԥ,w9S Z!##'? Q5ۥ)9(j΋фb7+!-37@7FLORRuQO;KE,=4*9Q %pFiomaȅGќkrU RaW"!X =;/%1gϹc][NDa &1~:B;HMPQQQRNIC<3** @ )l%j͠wǀ2$fҝׯ'A "$[#S ; 4Vճ;cKΓ0}M" 4$0u:AIO$S9UUSEPJD=6-#@|W¡5M+#u У-÷—#ćΚkj=[ "$F$ Yl3 }-؛r%ҡ؝Ep(X3,5+  [,Ŕّr'jΆ$ߖ; JT$%C#  \)Xұ1:͹ ;q'j)+4=EL(Q+TUVVUQKEq>6-="v Q&5qͫ3LĪy#{}|v' Z'*#(%! s,-ωͱ͋ϦGT>N)4y>1FMXR?UWWURhMG>4*3E,֣3kƮ Ms)3ԍٯuj# %'&#xr# ۻ2[#:j +y6@HNTWYYXVuQKC:b02%@0@%D΃<0~͌҆LUpbT "%$"@b RyڕϳGޖ8GU"r.G8BKQLUtWXW[TO IB8.#J ;omzӅ΍QgSdZŒ թݎB p-!&&G#| .s٥ZO ԽR &2A(v':#EblW؂#:NB*-5?HtOUOXYXVpRIL4* ZuHLyӾRZ~'-*л!B$E #8&'%x!+ -wϢ~,ΡK֋#2!f-8AIP(TWeXCWUQKD/;$1K':%NGЯ˥Ǖe?ogj#zq j$+'j'B$ da߮ѷϟk\'߱ %1\;DKQUX6XWTPIA 7-#A (*Q񽫽>[‘8gϗֻ"/&!().'$#TUHDOUYZYzWSCNHj?5+8 -yٰү̷DŽh-ZƖoߵ (%`()c' "Y D8PΚ]j.܃VAj ,8"BKdQVdY(YXVkRwLF?5(H.afN= zϽ~KE 0Y,$(m*)A%m8h&yߙٞyЯḙҿT $$0<*EMTY\#[YTUQ7JB90}$ }b@Ӕͦڽ'.Kס6  #(*f'" Yy;֨ҋIXВ @+w(4?$HOUXZZWSM(Fi>L4})8)ǼѼ =­n@l_ba#(6)C(&! UѼx'".9CKQ_VNZx[ZgW)RLD"9`/&Y*n*hۧQV˻\Χծg (%+-*x$<gxק*2Y 0Bl ;(4}>wGTOuUY,ZZYPVRJB#9O."3y 4'3!kô(\Al3ғf 2 y#)*g*(~" 1e2'ѭε̩кm !,L8ZBK-QW ZG[dZXSME=5) ;-˂Żiɿ է] a&+S+)&6 $Gݔ׹OΪ+ חޜWA b% 1C<)E~M{T'Y[\TZUPIKDH9.A#? |^Qhoc?!ʮχ}*E$r*J-6-)$"!L 7ADR͉T *6@DIPoUXZZXUOXH?6+JoEӔ ػUպBdƹ) #T&|+-,&'!s&_kTӝ1%W~ΐy֨p"e#r/Y:EMTY[\`ZWR~LD;1%}  }*߆ʑ[3E ֜ގOw=LH#+^.u.+' X%\_k`fR]m(4O>H+OUY\P\ZVPI@7-!.(,91޹ԹwsEү((-z/f.*#A /!a#V*8Wئ ˆ˥BՍ6 =, ,#85CKS?X\E]\sYJTME<3'G"/нŧԼ tS07c m|&-@/0 .V)"XO ג/pj~~ 2%2z= F4N TKY'\ \b[X!RJA8 -\!={Z ݯ־›ef?U¬BBn1ym!+h010H,&88  i_g ʹJڴ2O'+8BKRX\]M\FXT+N'F=}2&)W"`1ɼѺʸV̹K$u5VۖIB_'y-13k0*>"WkZ4 ܧ׌}̦ mޟ }#0<|FO@V6Z]'\ZVQJJB7-!! ig؎ϳǭh!6byǍS#a,<1'21k,&_o XڸZ=K̩5 ԯڭ130*6q@JoSX[\o[XSLE>@4k(wc0595_qàN(Þ/(_Xl)j/2 2 /E*#"A.a%OΞ8 ^/֐aL9 *$1+`޼̹#KF9>>ֱ m&W%v.u4s64/ ( 3( edfխ[ͼ)ZV-D=z)6AJRW[]Q\YTrMdD:1'CwGuƼ-qh`Ġѻ6+ 9}*/w3441+<#oIED?ZRӞϽ̄;hԷ&".:tDMSXJ[4[ZRVQAI@96"* - Sd 3ĤӷJG<ߕ"]*/21-r&@ 3x۲f͉K{֭ dv)5@`IPVrZA[ZXXSM`D:0E%1 iSϢ]߽+(ۄ; &. 242-&h s&Ӻ0{ب[I_ -9nCM SXZ[~Z VuQGJ`A6,["t S܃ą2#Ե𸅻O.S)!,2"431?+#z2} }SFɻgʿOItyG &3>SGOhUY[ZXUO1GM=3%(m\'%ؽٺ-swϼY?!Q %-2540a)!f" g~%٭˚~o ϑf7[;,9@DYLRWZ[ZWRKC@9s.#Lw r M^…¶$3dc̢ԘF&]`-*0q4.5=2,%~ z݄0yǬً̊ [$1Uo4(W9 ۞;@+ŷT=-‰T =%Y.f36}50)^!%UsړPVǽdʚ΅Ծ@d D* 6fAuJR6WEZ=[8YVfQ JBL7-# P"$3ъMǻev\xcq [*D2N5w6Y4.&g eޮaӍȭ'ʼϤם76%" .:DLSWYYX%TOhH ?4*L ; 6Zh1Fu귑ntL79"o,1Z3V30*_"c1D3̭_,tҏm@ +&3i>GOSTXzYXVYRNL C:01%MJ?J!Mư6`r,d2 .'Z-v022"-X&na {N(EπǾYԣP/,8CpKR*VY5Y,WcT*OG?$58*9 woG˄ĵ"-6U&cq-(/&2380+%C z5bΙ?ǃʳϺ g\%2 =GN1S+VyWWTTPJC:0%YR`֨L5ŠVJ*ʯЄ89$5+131,z&1 d&&\2;CXI MAOOONVKQGA:2)u |GrNA Ødž֓ M!&)*B'#ڀ@ˌh1n?S)04<=EEJMONkLXI Dw>66.%\l",)=>@ŵaӝbP0j %&Z%(# W5`؎͏̽"cكJc"`-7@FIKKJH=Dw?93+"QKc#?͒r>!Ų2xj 6qg(=;84/* # 2+۱pe#ݹANt  26gj Oi/ڈ׈ՔLևح#r +$+j1h58:h:9'7d4[/*$"ck&o!֠B_@ӗ?X=wv -;c pn<!yٯGKy&G+K.00r0/k.<+B(%$w? FKaL={ܵڤ٢+ڦߕ :p"YXہۯ߄;%[B)!x&a) ))x(F&r#  `;LE$giڤV(),c Lb&<)Z] 2 wR "޾T* I;(5< .7# Lzws:- VTSkTSrkSY $8p !  BCamJ&v}3  ("e  M }! ( P0XAXKt=h  P\ |KWF.B%5PY2pl i }U ,:9Gr:w9%\ / SRL}: -b  l hi{(,_Rv1|g{B 8 l F ?,yvSb0JnVr F gy'=[kDv?rTt y Tvm`hGEyXQU%MaB7Wv)-4*A p`_}E:=\"Je,:J!T3U5yt5c1@*Nq~FX5  G R * y8x I !$*[R~*_SK0"mL_Y*"s $ F ] )&6r:Q0 [ N S{%;$pwNvXeU_l ~vn*> 1+=!'; O  iyxr{ B_+(x< WxmR7UtuhJGR :p|g)dx KHlYVk8XuoEKJNO`4J h & b 6F(>4'A|Y%.Z7P/!q|C2ch< ~8b}88SkL:Aaag^hF,pR}S CzEYiD<cv.2M@p?b &)|[wPp}=}!fu:YPNZYummR2#?@]%z^|LYJIu [P{AW7^ CgQ>O^^}<WT/4cps 2tXO RYMQ^7*Y| q2mBzmNI&o;C`!txC^+}GG5ER{P|z=Xk41@^ ^&,e]Zq4Zt tN~fe qLsn?mR4SS*1Zg1} :$q+Pf6+=bxz'a0*0\MPz W~p7;XgD4ux"y>`LS\wQ2-A\4Bw& }$TZZs{XciK(}]H|Im3$>EG[`+S 9}8Od%eXf"32 *1(-f  `*vU"2Y\eXDm0(soLR -| NsXU:\a{u)v37C{ m/2j`;b5m<\O.I&=fa?LmXU&[Mu\x2Qt{-y3 vX 4 / % { q J aYf(>23-Zu5EuJgC'O|(C}nVݡܑfWٯ!دgMڅܶAC>])\n62 ? = 'Xa:PK+!j#%'h()7)w)?((( 'M&X%)#": (;n9 vm8/-To7 O؍,aь Gь ҹhEՑpܿPD965HxI{6tc  ; 5"%q'*2,-.{//x////~.-,d*(W%"kFv c!j:ɯʚGs JHlt9]ja;8)H-^7j k~M"S%z(@*-}/2:468'95998752/,)\%"?_ ',*.D޵dCн͌ Ǭh3!(3µǗΤYH[g  6W#'+}/m3_7:#????>=<:841,(%!%Pe *(E8x!ײӧϦȧń¨))4vdʮІr Xik9/]\@a _*S"',*0x48q;>@B@C)CCCBAl?^= :161,'"@4& k!aC=l_jãηX也JqsK˺n#   ^YLwF-tmbu -r#E(,1G5:=AKD9FHxIJJIGEUA=83._)^$ Gl L d G[֕aUֽɻ?﷝ᶕ*$)%Gy ]  Z f  2P WaI Y3"R'Z,21(6A;?GCFyI8KKL9LK?ImFC@=?9 4d/+L&!b6 _?^ ַѵ Y]Iڴ '~8nqo F}q a\wrlEQ 67!g'l-v3"8Z= ABEHKMO1OONmLJFC+>:25p0,B'!{ 0QWQ?~̷3Ă\^tϴAIJ޳~Ιc~J gKT RIAM B G&,2\8=}BFJN'PWQ]Q|PNLHEB?;H7{3/L*A$x| s_B6ؔUʳƲºWx c*;ȰٱijҸmАٯD v%p: * *3 =[| Y &-)3]98>CXG{KWNPQQQ4OMJH0E)A=95p0+&A  K(+' F%۶_KJg}u Ӷ7ɼѵ۵]U 'at @Mf r>&-3]9?^DYHLNPQQQDOMKHEB>:/50+&q!iI 7_kZг DŽ'eqҷ ߯`\^*ZwVSތ, 3}e I&Ie~DB |%7+28>D HLOQR`RuQPrNHKyHQE#A>s:61,'"s>' 6rG)82P$-3) X֬Ҭĭ2=/6 |(9KeLUo- (#d*18>D{IkMOQTR1RPO LJ'GND/@=951-* %"?&0 Ks֧l"ٹﶷa>ѬܬM*gL+))68 !Z Kh $ A /f]dA ,x!w)0B6=*BGSKNOPPPcOLJJG{DB?;73/+,'`# VP %ܺό Kճά>ͫc NatؘP^ !) yS "}E#vzK 'Z&=-5u<3BGKmNP}QgQQOMK2HEB?<*85f1.,*u&"(Bx ^08oۣ#5h{ \V{Azu@!#"!s+ y ZjMh |+ l#++4;B4GLOPQQP NLJvH!EB@=; 74s1.%)%!0q {|O \I氼0ޫ˰-`JzݴA_ o##v#". jXe:kd!*2:MA)FKMOPPOMKpIwGF-DuB@p=:7!3u/,(# kcp،҅̈́Ȋ|ǺʷX*aHkbX嬊ޱ ~Ɏi 1!A$*$$r# Yzw ca!6aI^W k^(1C9?EJ%:742 /_,)0$t.$ީ)VsҾ`CBgҬSGrlEʤަQE <"`%{%%Q$!!R[ N?]|kޅ8j:2# h-,$.&6?=AC\H\KMO(OObML(JWHGEDDB@=:62^-)_$@ BrY{mб;Vˬ?I$ȳvŒ~ bE#%&&%! |H,. Q  ! *f2:*A FJM,NOONPLKhJ)IHFECA?O<841-) #/ kwyXռ"jƲ4u M:-5?Y"TV "O&-''R%"- 7l뮑T˭4 RǐtX5 o a$8%&$!k 7PmhIgR7jga+"#*29?DHJBKCKKKIJ}IJK|JIHFDXA>;8"4 /*$ 2  2Îb=l>'/ºUֵ A"% %%# sn #HWڦ5, 0W[<$-5w;ADGIJJJJJJKNKKKXJIHFC@=.950.) ^ ܼe~ǂ1ʶjlo]a8|t ת54 o"y%E&%g#9 a#uBjُ1ױ٘A߭s (60q7=]B*EGI'IJJKLiLqLmL^KJIGEB@4=r:5N/ & 0ӹ8Iԯrˮh]ŻC˄ұ; "%&$#J 7 S2߲*'&ֿٟU03Jfk '}$,39>BLERG5GHcIKZLMNONMJHECB@u A`DFGHJL3LMMiLKlIpGG+FJD/B?<7g0'y/ȕf㮵gF^ k&F>ժ$ %E))o'%"1a h+sDOu԰5֠؛ۉTs| ;h!C(/5:R=ACEFHQIJrKKKK^J*HGFxEDB@<5 ,M"00 Ӭʚ|츹 .﫬3ܴԺ߾vdz͂*۶- &**)<%" e^8׬ovԍձiPLH K/#+2 7tаǮZMpް$hc˂Ҩg4  o(Q-//,,'!h +uܮՕӏҝҜև٪1ZGM 3]!w(/5@:=@KBCeDEZF9G8GHfHeH-HGFFEEYCM@=81/# rQ,(s>ݰﳦϿ,˫x !(#-A/k.|+(" 4ArX;qАЕ7ԔׁK)lp} &G,2F6:G=??sA;BD"DEDEEFXFFEFEEE7DDwCA+=$6-F 0c>О'ڰ񭟫%ڪ0𯫲չȸؐ!)o.X12/*%Vt&S*׆р#Ҷե5 b")0/44+7;=?"?@A:ABCCD:DEF2FF9EEZDqB?:91b&k v5"˲@QaWɼ{ǹ?ٞ? D(^.2A2/0[-)("Fi X4׬ӢЊϵ'ӌ 4߿`4  N&,048:<=>?p?@YABBC3ClCDEZF&FFE#CD? 69*mٱPkʹ9֬_۬y»i'cԡ:K(_05641W,&V 0ugύ͵%ͼY?zݻtb  %0*/4"7w9:;m>?2@ZAtAB#CfDEF FDB@Y;2&o WjԂ#Ha?m@\AAAABDFG\FD@;61#2DyC4ȧ#رxv+V X&_.59973:. 'Y 4vHҜΗ8[?]5 %*.t14 56788h9:(;_+?U@A>BlDdFFFEACP?:32)+PdѹQ@ڨ*ǫǴ=Ej{=yN*4)2(68;7440o)"=0G~zʡf6\T D!&E*D.Y134W560667 79 ::;=?>@@BCCDCA=s7m."E Iݬ4b)gZ֨$ܮɲշDx9&Y/ 4B775a1,%S,`Rt>LB˽Dђ~XgA -%*-0y2U34s445}65667N8g9;G<]=?@BCBA@;4)&]$;泱iŨ ~~Ȳ ̕ ()t26i7Q64B/)R!Rg.L̎ʙtΧ׬~x Al"&*-/012l223B445[68A9:

    =@CCDDLA>o:2j'" RԻ8ܱ:ZX8̬ذ{*/8ڋ`Su'058862-?&) ~$lHքѠ͉PыQ$(6+-./01.1d12=3)4?5 57w9<4>'@1ACDDnBJ?3587G9@BDuEjDB=`5-$%j"gHoæs_oٿ?411&0<79:T96N0( a {os `TxLvɜR͈Qk߫" !|%7(d*H+3+,-,,-%-.l/1f3N469<>@B@DE0C@ҕG&*  b%& %%v%&-&|'(-)+-/m15L8;>uBEGGFC6?o7+o|͸^ϵTdvO$ם}2 %07;=9BG IOIH+E]@8. "1Qھ϶½6#dR~Ŭհi'\mz %0Y7:<<83G+" 4$јȖ@6ˢϖ8W߆aBR;p <3Y "#>""t"""""$ %i')0+.#1'48<@jDEGHHFB< 5, 5̥ؕ|ngr0|ϲ^r!7ٔT#):29e==;g71I) \?F;7|3ai C h] fB v!"#.#"!!7 !"f#y$&)T+.159=AEGIuIUF.A<{4) +2Ի+Գﮜg*DܪOѷf4C p$/F76<>>5=:5/D'#6%K*Q\МȄq̿ &"bs :!C"#J#"":!! !"$&0(+.|16:N>B[EHfHHFBA79k0L% S1Pҝo,筊<#6ж ĖEsgQ ]%09g>w?>y;/5-z#4 ڭήʠǣƃaDp{#FMK!""~"%"E"O!!( !"#.$&H),0H377.m r|S+ũeg>qVLF2݀5xK(3)9=Z>N<9G2)  i`ئc AO[G ВA  zLk "S###s""^"O"!w!3"#s%')-R048Z=E:5-$2AaGqϊoȬ>˓ώn8 z!#r##r""""U!!"#%9')-K04B7<@dD]FHIJHAA8._">ڇd'R/ЧYf'QЁګ;'*19F=>=<8)2* | ٪үfkEk Fυԫڀ+ ])!#E##y#B##"!!c"=#$&(^+H.[1o48=AE\GIOJPIrD= 4V)_Tfb>ɯæ̩*VreW%)3g9S<=<;)6 .&KkЬȻƘ+ѮQݗ>_' !""!!;! y "#%{( +n.2<59>CWGJKIGB:1'1 z(MHײMͨ WņΛA;l*/4:Z;4:9u5.:$VTvZ#ܘBϵȮƶƚʑtLo'Y]- FM "A""""Z!!#!Q!""$&(+/427;c?CG"HIHFAy:l0% ctнas,ЭH1ڨc_Ǟ7  $.6p:;:7*1P)3 @ $ ;RԳG!ŮŠ0:Hj٬d /,pB!z"q"K!".""!!"r#x$D%(?+.1549O=AEGIDHG/D=4*!XFͩwh墳LToԑFa?X ]$W.N4k79y85.' W{7җB%PDzl̦ 91A}' d!#$$#Z#^#@""#r$v%x&)c,/26;C?CEGII"GFH)GGDD=3O(\"]ha20 ǂQ]I+F%c- 3i6641k+#9( =ܵ˓dgpM".:  +$1'o)*++**|))M)9)*+-0376:[=@CEG F C@-;5){C _́ċX5Z֪$Ǯ'ɷѫV;  (w/48L85M/)!& MHՍPk7$ӳ/M>:xX ].c!%')**+**\))))*,.04 7:y=$@YCFJFEC!@]:1,% (rkrɬQ6N6g)ҫYebv&c.4+554T/~(  {0"ϊ srǒȺyϨԆ/xy  !%(*+,++K**4))*q+-/147:=@BfE&FF8Ce?&92c( o+IMikἄ`UE>du&.47i63.(r 7BEڇΥZƳL$mo G!%(+4,-,,,X+**X*+-/A148;}>GAFCEZEF0D#?68j0O%P! ``(ƒ2Ѯ={[ѭdu9܆ %-K26T62. ' @ۜ|˾>ǨDŽ.loړag+ k#?'*,.@..-J-,,v,O,-/13N57:e=]@!BEtGFC>57/R$:J6Ƕ+@U.ӯF8~"S+1C4542.N'' +g .U4?[bi3~ISFC 1*#'*-:.//O.--Z,,z,-/1358;>@CFqG;ECa>7-!_KeʛcEbN۵ĹCk^A#+244A2-'n YV rՍC̴yLi߮"5 Md#'+-K.///U.--[-X-.U/2N47A9<>>A.BDDCA=7u.q"u;ۓs4o߱'ȫﬢCHEҿ;/+eK1 #Z+1k441d,&c u_ ж[SԦ &h S#2'+.b/000+/L.@--./"/1369a<>AeCE-DBa@<6,,,m#^ߵ7w@qB Һ [{L(@CEnFDA=7-"}Э+Y']&Ʋ1v̠ӠbN(#-2442%-y&X 3i^.ѧmɣ1͝aJ߂(QO s-#B(-20712H2{2O10//A/02,358a:ADDFFF$B!7:,Q ģCNޭy'Į+Gɻ~aܔdtt'/#47O63H-)&Zj l hqˇ ɫbϺ46O@ !9&r+/234M473U210u0v112469;>X@BE'FFDA<4*,'/ח͝ )t&߻sƃԳ]u@z4&/F5|6J4h2\.K& bӰnr ǭl'ӵ[q LM$!,',/%1333V211X00$013468;T=?BCE)E C?x:3*὞6̭)u*n+ɻ;ƨ͕8 SL&.N354"0+n$=ڲȏ#M˫Ӏ-x^ ws!''+/.13Y3322"11W1,151347-9+;[=@{BDEEC@`:4Z) WѸ(T孔e.+(ͤ8j*k?'V/5Z6K41T,k$lts .Uv˥|ԇٗGq D"(9, /24d443Q210012358v;-=B?QACEFPED!@:.0%x +<)LvDh >o )A͏Mݱ "Y, 2)57Y50*#EM/Iߚد3.ȩd5/JߐzH "q(E-?13555I4322@12>3/4691;u>@CbDFGGDD?:2Q$AǽH{{Mj tDM$,27p840I*-"'x >lPߠ?tX4!b+Ԟٴ|c 2#g).p14|56.6 5y43333f3457: <>@BEH)H{FC?_8j- +KV*ECưǬ%Dg]{ =lH `$-4476450)! `Zݗ}Ѓ"^21#9W %$+5/3G56660543g2345d68:<:>W@CRExFF@E%B=;4*?9yvQē~uhѬϬx^βٵ͸̽ɯдLm $.V3553/y(! Eж̟mdzNjdk͘m՝ڝi;^&t,F04I6v7j7u66%554r33u35E7*8:K;=@DBDEFE%B4>27[+ J֟Γ8*Dp5a^Dʼoofm[ B%.47i74/)6  -6R܃l/ǺǐZ&?Gժڢ9&,]14[667=7[6{4333334u57:;=@pC}EFFEC?7*jw9mVQ,'!@^QFEYBDm*168S8V507(!9 i3~˟;>fʍͩя"= f* -m!'-2v5u67]7|65u4q4)4W4}45768:=@BEG+GEB|=j4'Aܓ6}7خ«hgʿ !"-48974[.n& w.q'ҨO`'ưLʞbܛ. G#)t.[2/46T666433334347,9:5"ʰCʪ:_=Vz+r͑Ժj$X%0689C73-%Rɯǚ{ƞT>ίҶקe@_>+ 3g$"){.%14j5W5w55F4H3K23034$46[8:<>ADFG FD>7|/.#|E{ژΧƩ&\X.ʮҲ48ɤ*ov9bRA'1e8=:9P62+"x'>$nެU1ɏ99ڷI G%*G.1s3p33Q3B3y2112$2346 8:w= ?ACEEC@=8. l ;yQŧ QbΫKFmc;ҝJ/0x1246P9s;=q?BDEED{A`;3)+ N4-֙ĕJtroK̻2 N&/47862-&Ui]ws1&bVp؄%-srYk  %*\-/1111100000124 57:/@BDFGSEC?7)+?J7ڢ#`iYxF6 # f&0T69:95.' ~ UF?[]S]u#),-/&01 110///:/U0}23f469<@ BLDG GvFlC<1% 0}SDzI<4Z*s!L,49;:83-$0ypؕ:ʹʓf`$>OH# I!'+-./u///6..|.G.s/B013587;!>ZACQEGFD@:0"\{Թr±J&ɹȎv4D$/ 5:2;:82*J! +# ~Gɤȁ˘Ή҆=;s|5)"&*-l.Q...C--,-./15357 8;=>BExGHGEqAF8, J,4( ** z=Cv6@| H˰wO74Ջߴ ".x5w9;;]8V3;,d$"tҸʂGǺhձ #z H K$(b*Z+L+,[,s,C,E,-./02$469pBF0HJKJIF4@6v*i ZJ""`P[pV!,49<<~94.&&h`AGaǴɓF]FKBFJ KK~IGD<0#e^Җ roЩ#vk崳m<\Ρֹ W&18P<<;7k1m*"qy{Cj& ɚǀXʝծ!q18| O!&*-2..n..--.>./0247D9L;X=ADGJgK JG8A8,-P|׼;_3sǫhSһJAo``*N39;;:/6(/' w>ưBp0֚+(JC(#S'+R--.&.s.t.b.m./0n1b2469;>MAFIKKJdF=1$fH$VZ (Ǭ֪H^AB-u,V}I$.d7=`=;/8R4-h#c4Y"ə%5Vٍ1[Fz 8!=&#* ,...q.C.".&.L./f0I1N25 7-9C;?CFHJJG_A8?- j k^[@OD$ިTL o s#HZ P*4:==; 72*3!6 l p!BȺoʥX֐.---./k024}68;>BDFI]JIE>4`' Oj]ʞܼl!ৢOī:#qa#.m7<>'=!94.]&L&9&_͒e*]؇ݟ 8 | o%))Y,--l--p-- -. ./013D58;>AEIHwJ+JHCj:}/""?ȇ"y>ۨnɬKuϡ׿R)q4$:=>=^92+# ax8tEֻȟ4uɗЄj;+s"O&*4+,T,E,+++,$,-.0246:=ADcGIIJIF1@6X) p(۷\ p𦯦ߪ.ݗ 'J2V9<>=J94Y-&UD)IvjsȜ SyԐF#' #')****n**c+R,-.02469Z@LCAG_JeJBGD@H7( ${2߸DϧO@߰յRfӊu &1m8k<>=}::4.V&37ԭ:ˌɌGx̀ ގl5d! "&()*_****D*Q+7,v-.0358;)=AuFIK6JIGB8-i"6oKѰKبo׹4 [": &)4:(;l<<]80)+! Qnrw=ʈ&ȑȬʝdqd8Z H#&(.)J*+**+L++,./14;7Y:>IAEvHJKHD>6z* idgh[ enRpޑ/rh%07:;;8Y3 ,#CPԂD0 + C b #&''T([)T)**E*, -h.013658<1?CHKLRIEBu;-!(ܑҵŵ;㨀H"ϺƒUٗ}T",4:=Y=+:61G( ,Lkҡs ʬ]{ͤЈW$h!$&8''((),)*,-Q.025|8;?(CFCINLiMK@EP=5_+O >'GĴ+#Z-[ۧ7%ڽ~T*B39<=4;72O+^"GZ ښԜ̎ ˌ;}c) s "$&B&' '"'()*O,.0v247s:>=ADHMDNL\HC=0brفzB쳐ȧڧLkjm]N++t b&18 ;>#=93w,%b0"#֫3[|S;'߉@3&$o"$%&&&~&'V(N)m+M-z/?03699<@0DGJ)KLKBG@ 5&pcMˊֻDqަߪoҲō]KRd+5;>e><-82z*u  {CطI!ʈɿ]̢5:E< wtXY #C$%m%%U%=%'(G)+0,.+0259I=BnFIKlLKHC(:-ZHυ!c_Ǩ󴓺^ʼ M '29<==:4-%`n۽FϹ̇4-۴OO ^ C#-$%@%%%%&'*')W+ ,.K037p:>sC0G^IJK]IF?4% (պ̦Çұ{%K_ʪGgYQ+TV׽Hr +4;>>2&H A|QzD֧kߨdq4ǃqwy9+4:U;;U96/u' R W\tcVn3 ΧڟRbuc Cl| <">""{"#T###$&(k)l+-1/4$6:?CG=IIGF!Cl;l."h UұșfKn6çZЯƵjnʠJ s&07;<:72*!dSS܎)yzf;̑&Ҟ܍8*z }!!!!""*"""$&=')+-1;48;;?D/GIPI8IGA9P,w g͹Ŵo=1̧/'?N8 ͋g_!,5M:W<=l;7>0(#8 fvٔ wpbՒڑ y! y[HI \ q  m!u""o#%'(?*k-2F6;X@DHKKCJ'IFC=0I#a[+9!~ TLʮ#7Ҷ)279i=+=x==;7=0' EF8gס҈΍5̑7֐a,f hL2<8`4 _!$3&;(*.b2{6q; @FIjLN OLD\:4E,o"E bQtԉE \ ׹W6@| =v}dr "k$t&)-c149>CGKhMuMLMHA7+.OZ?::άd'ЎہM' '19>@?J;G66/&Y58IU6_ͫɟ\Λ)֐ eb{ v !\! 98? ~!#%x(+.i15:R?EjJMN)MkID>+3x##=>х=׸N09$,{]mxÈQ֐C+35<>?>^93E+" 8U$ߦ4ӨWʖT4%SH 9Z !U!) / !N#W%E')J,L/4 8D<@FdIKQLxL7GK??7.#!g%ˎڼڵŬ"R5EsG-ی $%(/9>@k?:ID HJKLJIE=2&=4uMrҫs9S<Ʀ\n|qīqP>*{4:t=>?<9#3\+"u 0JߎӺ`2ʳjzԊlhD?>'a` !#F%b(J+/q37<0@EfIKLYKGW@6*L_vAŸI.kȦc X~mۯ".~7CFLHK_K]HDϑ̄ʤR5@AGqO L !"*! fr !K"$1&(,-/37k;@!EmJkLMKF$=4+859bXā>бkV!ѿUۤ Ee's2:>@?<70(or 3*/s "m+YAa U!"!  l!"$i&)M,s0o48=FBHK_LK$G C,@@?<5 ,|#C0i:*Ɂ ɭғFNAjT  , !!!! ip "#s%'#*-2<6; @DHK$LJE@B8,F q1ĘҬ.``歷~/m m&*19>o@@x>92!)  )uՇВ̩02bhՖڿS ZBd ! 2*l y!Q!#n&x)A+.27k;@_EJ{M_LI D~=M1#~҂J9Vqǧ۱]línr:z?*5;=&@`@!>5; 5@,#r=ߠyλ=<˥E5j[% f6 W 'Pw  !"$&)h,1659>bD%InKKIG?A}5("λŏٲ祐x^Mgу/X"#1o:m>A:A>8?1s)) ݔʹ2dɟhsbI3wF i{!E"H")!J +nM2 !#5%'+:4,#'_/: J5˫n)) !!3 Yud {!i#'%-'^)-05?9>BGQJ:KXJG B&9!,p~Ȩ.Ǩ/< r۵X!4,6ey 5( Z'8ϩƧԩӬ{BipˀEr e'19?@>;!60 &:Q/ՇЭKM`f  c!U" "!A !t![!_"4#%'^)-05h:5?9CGKsMQK6GXA8.?=83O,# 9w{wde1ݒm Xh ">"""K!!!#!!E!"$s&(+/-3N74'C' jNm̥l˭ΨةŴ$՟@PV9$i/%7=?`>r;7(0(U SUL7ɕʸTeձ] pdQ "K####<"!!!!"$2%'*w-159>NBFHJ)JTGhA:/] _hо۹%Ӱ;䨥J[ήk4 4*2K9?A>:z5/7%i<.4ٜ{˭QIK˓b,ܞ&  "c#%Q&R& $##z""t"#%@'T),/387D;p?CGHIIF=3*jK 1æ`ױYߨΪgڳlKYАk -6t<@S@>k9o2*! ݎַjȭN@ӝ؞ޝ We a#s%%& %$####$a%' )"+.148=VBF0H{I"IRH~D);0 "=2KOʺ+%9ڬٰ9̻w /"c.68=)>>=8/&iQ6sȧ ZW'@r} .D #y%&3%%%%5$y$%'(@)`*-f0W3Y6:>PBFGHI_EY>7- Ui #ɲүl&SԩbMmٷ$i'2>:.=>>|:4,M#1}%)MXջUn m*6p!$&&&&&&j&p&'"'(*g,@.15W9<@;CGHIHUDD;1&%H}K'.PnĀ̾՜>D})22c9V<=o;96e/(# W|Hݻ-}ʞȢɹ4;ٗ=9ie"%&'y'''.&&'(?)*R,1.q036e9=AyEIK4IE`>7,l_tz6ѸY խ;VtƝn־P N8">-48;(:7D2!+5#V. @I(̙>pʽѷՍG   $&r'(-(G(N(?(5(G()*,P-0 25h8=ADJF>GSGEB;3)' "E v͝6׸\ ߫ ԫ ¤;4ژ,a #.5X8:96b0)9 6 x/@w:ΐ`ɭɈʑatӂ)&dUu \N !$&(B))K((()O*(+,E-/1437q:>1AeDFGHFAl91 $(kEҗ ҲY6!j>Jގ[+%G.59v:85/=' ^",\%)*jɌ)6TވkC'oQ#8%')[*(*7*A*j*))*,}.,/14^7;z>kAqE,GF.ED@S8~.% ZmۆzC\Ϭf#'Ɵx1%.58753E.Q%u8 4B-h/pȽ ʉ0aڏdltv #&)x**+F++V**+,-/136J9;?3BiEFEDgD>2(;{xyĵ+t _Lps̻iDmلov;'0688&6Y1*"Yh$e~Ԙϳ#Ȥ! M&eZ P!%w(Q*Q+c+,C,v+++,-e.V/2@469=@BDGcIcGB4<2$ tֵ͵ὐƴ зݼԯ܉` R(1~68;751m*u!C~x8 eNg;Qңa(} VQ"&)++,G,r,1++,(,-v.0247V9=)@CD(EFEAr:*0Z%S87q/$y Шxz93asbbϛ׬%55&/ 4541D,%zbrȌɈGѷIj8= S $y'[*,,,,++e+E+a+,.[0`23358FB+DE8DD Ah;1%g 'WcB,]yRDlYܑ x K'-1m21.Y)l"q^@S;ʤD̻p3Q ID q| #&;(;)**n* ))))*+I,].0S25d8*;C>5AEEDDB=H4A&,j Qdq[<ǭ-ZͳgDb Uy ']-121a-(!R ":?`˷ˆԊ42E'<! p5#v&@'()[)q)=(''([)Q*\+-0n3I68<?MBNDEYDB@-;3)T AMvخ:ծiƳڸ{(سC* Q' -00l/.D) K] B(VϰQˢdҿւ-\M ^ ,"%-'q(?('(6('s'C'()+I-3/~2+5(8i}j׽mo<# @C"%&'(J(''Z'n''(),.|03S6: =A;CEYHJID;E1D' { m8pe®îT гؚx/ (4-00k-)#L9 i/ޒE:MӰ\82\Bh "V$$%U&8&&&R&@&~''(*7,w/1476:=ACE`FFD?:6,-i *5˨hOwʯ6q=_ nѭ]_u#)-.*&"gVpT$uVͪr҉էݪ@J !c"$$$$$%6%&')+.-03m6:l>A CDEEyDB=5,L`l[iADOF]GEA=M8k0H#>R ԰;|L{<) b!'V+<-<+'"x 3]N mΒΓIխ'ݪ1g ^ Y!{"U"x"-""D""#+$^&g(*-04M7S:=ADEEaDC@]91y(%}ؘƀS Q?3ຳMİ˞ӵ^ ',P.-J)$Oo HKf(wҡχ6 П҉XْvD2T$ "C :!!J!K! p !z!"$G&)c,s/25:>+ADlFHGEC?6)  ѭȵݹ6뱰 ᶣ\3#$+0/c*% )LQ"EOB!^k1V I !"!! t !x"$&(+/E268<@-CFHHNF[CP=5* ?XԷL;y2Ƽ6P9ܺ."*--U*Y&!Q&jݞԒY{ @S.ro Bu " "4!# ! !2"j$B&0(X+<.148L<?C\EGUGWEC>8%.z#q 0fVċ>P|`u/غ, ':+,z*u'A" A7CEmF DA>:47)KSEQ},xٱeC 4YrDEc %0+d.U,(# SUR4;:"H C = !b!!{ v  D t!C"%E'*0,/3,69<@xCEOEE?C6?;5v, h!~Dі8yCOײ/)+?#?'o)s)'Y"qLۖflюώnІ7ת۞LfI Ow !  T!#v%(+.2i6F98:[V !"6"#ws@~ۻez!ҶPNAxhEH? &V]2D<D4 "$&)H,d/3857:=E>a>\=;;73.9'* EbDՏ@|¼t1(S$wډ&za <VjHD {vPڪ8֣֗I ށ'nb a^ #jiEuH!{#%(**-034567641-)K#vlS l ZѮ̣ȷÛƸ͟I\N ojV$ޑܛ:s'< ^?6z$oS}q!#%')H+D,.E/1/|/'.E,*3&!}/އٛՇ6ϐ̦ͦ_̱͹σ u~ AuW N`8UqާdܽLw(vcYj)0 pRa^Y?.?!#F$&()A)))o(]&$k!EL< Y޴N؊ց5ԥԴT{BڑXXVTI  a: YD1 yMgSq}WNM; lIBp6 Q`VR!3"#$$$$#"W  kN'Q T)@c(1d*i 8 o9N|FJYy!w'<v N E)N@PLo J ! FPR1s NXaIS-oTEV%8 v { a=`24^&b$bQ{  -H[KSnp\ij N|"KF1: f3H ?y{S# w!"KxIPH8hs|Zc ~ Y >#-j0]Rr?$  D2sBPsLNJ=/+4ak{61W>_YZbFo; m 5\r[4c}U q?]O-Ci+ov @h|MO{buMFThB_ c E C3c|  k]H:CrO5$%4eAjh f})T Dv eX`K88%d`  g ) 1 X8R  ?4owD '/p7>K\`\ Q 9 [ <;  * " VI!+KR^ Ca`8ou=V0.~5#[6v>:cd=-B v D z b _f*NP'8"])@c# ]Vx,p^-ohI*iN \-P^t  X z z SQqI++' l 8PT8;.&ai {@ !FoD-e/x?%(wLc{Zw$(~-58_L:io?L;*M.,c4}Ao!RKn]k#\1-`> h7D)IPUs;3vn-#d9q/xO2!?U}zbUQWk<g)wHZvqnO1|rdrLp ApJN~AVU?Jt#T.~D9JmN6"?WGK{{pr+kNzAbx`:R<^- #Z K0gQL]JFphU3 sVF>CCZkD5{'38Njj'D)jHl}:wq]OY`4=)!Yv2RJd+ aB1%#,K*N(i6p);O>]m\\9 <[socchxFFnktufF7r}W<K',~;pb:){-G"ZwU#74U~E75lOVl;4LAP @zxZ>PnA!(S X1]cy/M,Zt|zZ,v9t'Odd(Alo6.w`Ndzo>qzYpxp'mL~Y ipktuWS9`^ '@/J y\SJYH=Lb@&73Jr'yS:M` W   i <S7}ou.r;0~7}uFi4H* #- t4KA}(5B<t{nE{# *wnM6<]zU+KKE!dbNW{)?pB{<HU$E={R#.l.&}@t2wQ.KTUBf1WV%ddp=J[:AKdqP;OAggy22i'Y"o({wr| ; 1!   G z w"=*t?Fs+nz8M5`e`pz-O'G  0+MpM[M\f_D24 " k     ?W Br.JF/pd,{oy.UW3x>w ^;ZF pWq ^8>n!W,  JN S |o ~+}8?qGN ^ ! ]   b A ` L  J  ; ) ~ 4`DD {-c| b U K l ^t#6lpjf J ' F%_KtpTaCZB"# Pl0l(>=xs8%  Tc?NT==Wt~Hx.U c 2.7&GV"(^zt=aDU]4xD\# n}Y d 6 }1]H_AI+fY j~HF74Jcmޘ$ݞݘޅVLD(@8<_SsmY#<rohqOs`hC> #c%S7 W!{"#W#$"! /= B|7FjzQL{{6?د#էz!&Jܬmg:G) + 4"/<YM)< D0 Ak!$P&r( ))*#)(Q&%,# lbbiW:  `']{hcث{1-M̃ &М([= ` Z \G v15HQ~2 rH")%](%*,.01+1Q0/-*&# 5{Onm Foekڲ;4Ƣ0bÊĭǃɄ/ϽHّ߭U 5kkw zj?J&wl 0b($),036s8-9'9 8e7,5X2/+'5#/7ip  ffR#"@Œ,ZH/ؿ4Lnՠ8) K  + ^1A "4/ >!',5059@iA @t><96j2w.+)%K!2{Bv 3 % z@/ӿLs XϹ:Ƹ|𼲿M#!ٙd Smv=> rV[pC Q %*05:^>}BDF*FzEC@=y951-w)A% r # ^) (ׯҌM qRZ.[r{|qe̛ Gi % 'f_Ky < &_,272@ AQZ> /%,&2 7kKC69 O/yC aXKDT# [ m$*16<@DdGIKdKK I)FHB?);+72.i*4%! ) Q&c[z{Hi5Av*D_^fğȌ̢ [%?zZ!"rf DwrHH&"` ")/5V:?C FLHJKKUJGEA=951i-($ W2  cAY1տшͰ:þݽ~+j8KSÇul`2q hSi~5( K ''-Q38E=ABDGvIJK$JyHFC@N_ADGDHItIqHFDA>;&7d3q/+'# Z N[c~ƶ$EHÛƹ1qӫvJ.]Ch` 0cl !=MMu9]t* !'-Z2e6;>ADHFSGHHGFC@=9y52 .9*'&#  @ CQ'AyײΧʝ926y{]R?ahT`~=` }S & ]d:5dW mEj$v*//4e8C;74I0-*D&#vFcY- A:aܡ׹B.ˆCgl.Bw뽗VJÐƢOΣx:U7O~8} }In)   71e_  &,16:>LA5CEFGGF-DB^?<9>52/,)&# Hw %:>Jv٠oBȈqɼHRݽ/*wkew<8@ 3p: A U69:>8YICN ;-$;)/748E<?WB@DgEFFFDB@>C;e8530<-=*O'r$^ n XN5e!'óȾy̼U&OֽxTy΃DDݍ Z 7 o < Em>C S &j+05e9e<@BDFlGGF;DB@Y=:75;20-w*'$ 7X QfnׯίǑ\cƼx\齗Zl^Gѧ^n \5d & I?1'\&,5 #)/38.;?2ACExFnFFLEHCA?=H:75L2/,l)K%!q <3c!yHNñX[%j̼]WRJƸ4Ώ׼\" Q"^ a yRHC 6<. <!',2V7 ;2>BDFVGpGGFrDB@Y=:75h20 -K*'$  q4lQܡפΔʱFPdwݺ 5/;qfn1ܖz 0B NC3j W#e%~+16:Z>8AeCEGGGKFE=C?@>< 97@420.-*'#U {JoYeӈǃr@;^.Z w Į!Gбfڂ s ]ADFH7HHjGF4DA?M=:86i4 1.+(%  YzpF8{ѻw[ù.T[rϰh I[ P t OJ-D1DR,6d 'o-3&8=hAaDG'HIII7H F4CA?F=:8O5370l-f)&!c I6$3w8oí⾟Ի{ι۾{³~֚۲R 0|x w%c06| r)$}*066;0?CTFvHJJoIHFDB@><::752//*+(2$ wV>lĴ [#\Ը6IB=łΝ5ߗf' rS )8 1'f Ri=!'.V4]9>CvFI|JKK/IH F CA?=;974<1.*&r!D t?wݦM!ofk<7޸&UU,C=ـ߼U Y0y* Q?+#]  '.4:@DqGJLJLLJHFDB]@>>!<":75Q20*,(@#H p64ݟ׿7vĘ2M4طܶh6@!xJ7"%n3 I\Ek +E`X_ &-/39?CsG!IKLKJaHFDBe@\><;9I64K1X-)$VAD@ +dLbsȅQ%Vϵ}jӸSx08$G?^B/h k)E!j/%6+28=BF]I1JKyK.J-HG+EdCJA3?_=CGJL_LLiKIGEVCAF?>. nI/Jw"2s? C%-D4:@_EIKMNONMM]KIFDB@><:86C2/*&@!9 rsݡ˕'7Ƽ麦mq>˽S#y 5IRm-%L+4sMk 9%<,4V:@EILN:NNMOK[IBGtE&BM?==<:8740-($ :9̩ó+O[Q^彞Zwں,AAk)|  a8rDަ #1 0%.5P:G(!/6FCGJ&K|LKK_JJnII*HH7GeFEE)CY?9:y6G1,%J m$ybȋ×bT_߶ue*u5E4Yn =k3&To XR'D-څ.iڷܿ). jy(y07s>aCGJ+KLMDLKJJVJ :61_+T$+iͭhԺkf8Jȷ麞næ)ͤ_p5QoNp(  xRA߼.ٞ0ج\[B#-B"+h3B:K@dEHwKLMMM`LLM%LKJrHFDSBA >:~6,1+#;DiTrŒԺsԹǼ;'ǀ҆ՃٔV `(KI Uf]zaNFٟd٬ \ L%-5CFIKL}LqL\L/KKKKGJHFD4B@?6=L:72+# 2|ұ#$C޴`նĽRdω٭""U=% E4_ޔڤi}~ *{iz )18>CF7HjIJJJJJ-II>IH}G EDCpBMA7>;83)+<"\ IFK%EQh3 mw~(ٽ;#S׆$( 7f p KPrOձZ.ޭmv"+39?%CFHzIJ0J-IHHI\IIIGIH(FErDBT@6=J82l* 3r xiݵֱLʲz&Hľ!й'ON Ygm vOS[ܿ؍ t!պ':,zA \;' .5;@D]FH~IJJIIIISHHHHRGGGF1CA|=7n0& ٘ВɅ+NV2A޵AXWžǐpzY/Z~'*E_ g7n#݁gս uӐSآ5+[Q= {)O07/II]HHHHHHHFD@;4* 3"ԶzʼnSP3B1W5wGŋqϓ[iߤ 4 ckxښEVҨI݇UO /$-39>sADGFGH}HHII:IxII HHIIGEDpCQ@:3:) T7бâxεݰͰ OµBwi~  !x Y (L_ۗׯlVҤӚՏ܂K {-'/6q;@C%DFQG2GpGMGiH$HHHHHHGfFFG{FD@491(|B _eeƺﻎihïذлoā`6ׁ߹Q 2w ""? :*g *q!fԇQ7s mH! z"+28=@BDEF|FqF]FGH0HbHH}HMHmIJrJI%G!DV?x6,!{jTPVa ݴʮȮЯ汜:ʸ|= 0"$$"{7  d~ܘBфVЙӛA1hxKq W'/49y=@aB C\DqEAEEEFGNGHnHXHqHIIISIhH$D2>r5)c ZaƔȲyJz ?"9؆g(cc#&'&#i k K _XJ#ѱ&σMe\@AA\ABIBC=D:EEFOGMHHxH{HI'IJMJIFCP;T/$<f >ݢZi,rgޭ(x@׻Pߜ !&'&$ ` +,߼ ϩѳR-hފ@L 'S.38#;=9>@!AAB!CCEFyGGGHIgIgJKJHD>6R)%HYŜkӮer.ҹO cEԎݴK_5 %,(L([&y#'LQ ouܲKyή҆ys-,p -or")A/m4l8:<>.>?/?@ABCE`FxG!GI=JKzLM6JFA:/!EZ*ҫ&C ଌbEWܴﷰ*wKv5 #!')T*%)%Tmb&-ذeIvCѓT4ߋw@{P &,W26\8e9;<= =9>p@A#BCiEFFG H+IKMVMLIDS;2:'=H}0?,:q(@L̖]?W('++a*:'$ Y \,h_%Ϣ"$ѳӳڦ[.[/ $*@/Z37=89:<<<>%?@B-CDEfFI>K KKKZI D>7/-#Iy|Ÿ~1ЭƪGծdДa^R%_),,*&!s= ީ1ԨvϮ)ϗ1;V'J?+ A8 &L+/25 6789:ABD6EG}IJLKJHE@6b*Rl ?֓ҽ) 0r2pk:^$*-.-+A%)6<۽UӏПA?Ѫe{ao }!$^)-0T2Q445^6l8 9;=?AuCPDFH+JLMLKHB]9@- 5mV5Ɠ@72 ͮi˻PӤp5$e+//_.,' w= .ЇιrםwswvI 8#Z(,/1 24-45798:r<)>?ACiEZGJJK/MMBIE>2$G{3ܯKz%o G7ݾG=/6 X!|).>//,G'!Q P:DuUZ tб]ڋ  %i*9-".1234688'9;z=|?ACEGJ.KLfLLJE>i3' \"zʳŠ09#V+0> \oجx'- /.-@)c" Q<e҄?HЃmNmgl m#'+>-p/02!35+68L:K<>AOCEFHK!MONLHA5)J+8َŠ$I,`&< ȝ@ J',./]-)#9|(*#Zю!ҐؾLv. d"E&)+-/1Z2[357:'< >@C$DFhHJnKLNrMJhD-;E0A#4H>f򯵬c.⩑/״zd_̕ړV ${,0<0/.)p" F.f9IILѢ ڪ~u!(%)x+-/r0124;6$8;=?ACFbI*KPLMO]OLAF@"6(*n[zM6LI%w󩆬.tʼ.wٗ/#,b021<.*N#m L4dI0"Ϥ-ҿַmHm1W !|#'L*%+-[.02C35[79;=@CF@HKLN^PPMMIIB!7){$ ՙd—ȶ$34t"G;O߱CV p"+022p/+%3`+_v+ kf qH!ՙ܍. ?6e"'O)+-/>0F0246@8o:=y?ADLFHK(LNNLH@6U,#!/bA k=`kԮXơ;}(j (/33%13-)#W` a܍uӵz3;kU /4" %(+c,.4/g0z13569><>@C EZGIKL[MAMrKH$@30c4ڈ8{G۫ĩթS a%*,./01234698;=?@AKDGIKMNNLG>5@(f~JT;S²q8}h"0})1565X1-(T!Dd*MjՄC[ͱ4sWGD D %)T,././11247k9;=?AhCeEyGIK/LLGKIC9J* GձBK=CܨبIQS6s̈́@W &/V4e66p41/)!]clL{Go̿؇ ds:H T$ '*\,b."/0]12v468U:o=?@BDG ILWM6MMJC9.!V סͭʼng>dħXq˿Kh7> ;!-46540*"k uK܌׏09dfyrz K}"~'*q,-/#0P1y24"579;>M@BDG IJLMLhJLFF>?1$!T-{7p,:zGķH܎) 156X5I2,$O B(U͎͒9?ӖRےtj + DY!4%)9+,-./d02N4q68;=@BB/CEHJoLNNJFr?l4(i`f†ŵw?_ãeQ(s04541-p&a 18ߕCՄMζͅR]зt۸L#Z'd)+, -./135_7:<>ACKEaGJRL0M&M LHA5)) U ;|Ͻ"9DzƩ%O1*> "r-Q3N4n43/L(!c(a_4AӛV^ϑϞ| 5ޢxR w!c%)'+4,.=/"/1Z3"527~:"m@OBdDGlJ"L}NqOTNEL%F;.t!r~x3+#δ6ņ|ݟ.*!14o43:/*f#oU ]xHP"ցӍM(ЄӤ:y Y]E$8'*+./0g13|579<\>@BDGJyLiMbNNSK}Fa>p2%byq?ȖZF1ީ1n4Uýʢ3/1 jG&R-P2541P-6'.T ^ёF;$l6ڷ޵A'@~BpCEGIKL~LKGTA+8=,Ibp@BDFHJ+KaL)KIdE4=1r"Yx&8 4Mh$׿eūpӚۥoQ'05 54.1,% ,ٱ[O\jφѤԦD7gpC0 %@)X,_.)/1.224T6)79;=@B/CEG/IIJK.K9JF@5& 9_*TIuDFҮAQ J!_+254e20F*! aLCHУwζkf ~0)' c#(+-/02v235C7_9:<>@xB+CEGwI1JKJFB:9-h V4ή #ͬ e8jqsB U' /454$0,% Q s-p߈!ՁѮ6x4\!T!&*-D.0 123D3579;0=?@B_DYFH}@QACE&F*FH(I6HE@90^#3'𿅹q`JU,Ԭ3!cil6z6#+15481<-( oARUk*ՃҚCk)eхn)r-"\&+*.s0o12m3~4|526F8 :;=?fABDFvGsHInIGDq>14'A Oanɇ"rXbH~@Ng\S"*0g4742/*$3R Z3'RZd$ ?(xN~,v R %)-}0W2 2345689;p=W?@ACADFH0IIHjFA:6/N!l V"U̪l*TQ.7 Y%.@3552.(!T!Y_Ԙ`͈ 6ͧ69Ii-;L#^( +.12{345S6J78:B;p<>b@A{BDHEGXHHHCFC=4) Ue"/;> þʛ. u2 *2,5~641z,%E*D !?3[$Պkoy t< %s),.02$234568k: ;`<>=@ACEGCHzIIGB<=0XELٰQQ(贛=j=h{5ܵպ!L*?; $T-%24533.' <>ZйP#RϢ"z!_#g#+([,V/1234C45798o9:<6=? @DACEGH GFgCP=4R(L m8kλ2%! «ihF !?A^BCDFGZFD;@:1#Fp'MBŮ~\ɬȮܱߵ`1Ō̆& _H=(0<3X3t26.)Q"O /y;6Ո2eUPU  )"*'o+.02445Z5689?:C;w<>@A1BICDF GFC[??8-.AOoh=G𪻪6(0ǪMrx g-!7*t1331-' sH{:2߆wOА= ͙ n׿d/cQ ew$,)-w02Y345!5p66789:?@AC^DFF7DJ@:y0#X,(@CܲҬDު*oš˾҈ڕU_8!t*/w342.X)'" )\:`')n%ںBBm["',-/W13D45W56}7789:<>$?@BC~DEECA$=6-vX,|(׿%ԴR2d|jɭ!sзz~gߐLl Y){/ 24W3n/*># X!P4շ%2̸vӿ׸hxpAMg=%s*.g133B45}6Q67Y789:;=7>?@X@AC)D6DCA<5,^>'a͜xWC!ӫ*:ҷKUFa B!*04523`/*=#$u n\]z)˥$ϡ&f%8K !`',p0246)77878n89:U;;<=[>d@ ACDDDcB?:[2@' Y˔LSHڰH]ɭؚ,O r&-254^1p,& AitQF8˾ͩЀ`?D?@@]AlBfBA@%=8K/$zw(z-ݮݬQʮϱ:ϿŽVӝNRHq}'.3-430+% ~ [5Y}ڱ ͻ }*jQ C%+/=2n46 7778K89:;2<=>?D@(A`B^C=CD9CA<75Z,Z RZ̍KU&Ų@9Zׁ H+"^*0!3t4 2m.)#iL;3ޏآӖj́h8GB:` cv D&+P/E2467w8I9.9:9:;Q;<=>??@BfCDUDCA<:4) x|Ӊ(H{ŮL- Ī% $=+A04e42(-'!Qc*i΂̃rHv[؎OR{ i!('-)036978#889k9:X;;<=L>.>?@B?C@C:BB@> 81S& $L.ͫ>J0ܼgo @#+./33u0o*$ rܰ-#vQQڄ 6!sh b#8)i.14l6M7b789/99:_;;>>?ABBB?;Y5-9!9[ƫcj+(׬h[td8cP$+0`2C1.*# 4m4̾''rҗֿۗ<0 &y%w+/257*889a9:9:/:;U<)<=>a>@AHB+BBAx>92)8D{kUFK@뭽kTǻζ=޴(u;N$J*/10.)2" >F\~/s̸ -ܞc^C G.!s'-91N4K68:89;9:'::;<`=C>>l>>?A8AAA?<6/%~ KN ʸ²Rij}=mb/?bCt~[_G;&,}/0.*&I!)gX;Jwp͸Ԏع9X& 4"x).%25W8: :;,;p;<)<;<=*=>Z>f>?>?@@@@i>:\5<-#1uіhdwWԫN^ňu _g?*'`,r/16/+`%}pٱPZ@vͦ*$ hiz <$*/{3158'9:;;};< B>m>>?@nA.@@/>%93+!ϊY°?3 QR̍C #C)-01M.Y)# &2tءPv͡(͠ώ )߼)~2\L2&X,1~47`9o:;{;<o>?)?>>>a>>?>.;71)h93̩r;~usG!¦ȑ՛  %*|.11Q-<(r$  4&FXΐ`'ӈ>۲M'/ j:Y!'-2D5C7:U;;T>?O?Y?j?<><;60S'V hռ0|?L%c d4)&, /1=/+v& R.;ژ'>)/Ή?GO @<"f)T.258:G:;;< < <6<=M===>>8>?@n@?><6.$/ܢ_Nu$xE]ͮˉҐٯ1!)-00-)% ثc'~Ϣ֏کDY5T%+036w8:":;N;;;x;e??\@-A>BGBAk>;75w,u9c\"Hp ث嬡Y8;3ӫۮ !(. 0-/r-).#k bJ#ݨ8оwӵדR p',1|5%79:;N;;;;s>>v>?AcBB @=9|3O*-HսZ/ǫ{3(ΐ#6 $*._007,'}! 0G?^ܫ-tHΓV&0zS@ '!(-2Q58&9:;;;<<<=*=^=>C>>>?5?@@n>;m60'? dknF𬑫Ь[R}_éɁׁy =H #H).[0P/Y,4'!=FՋTδ̀͟ѣ<لf&A "#(.258Y9::;;Q;l;;<1<<==>$>^>k>?2>=.:55/q&9 ' T ֯ʭѬgOÔV2׳e [P;&+/0/)*% Rpr^ٛZ ͌:EUڋ(wP$*+L$y*/3689:p:;(;+;;M;<6????w=;6w."Eeۨw/DzSAm#s]OܺlfџذQm  ").00.*d$iZ M`ӓ*͖ϥҦNڄArRR :&,14`68::;;;;\;u;<'<<=A=>?A*BNBQ@>:r4{,' kk#,dǮ8~YS7qX?%>!.qm %+/11=.C)c#O \D@ճћε6yӶץE>~ @*!(4-2567\9:.:::::;=;~;@ABBB<@=82( f>pŬϫLH״GSqަ7fy'j.K2`2{0!,(! Go9߿ٔԟK'ό<'lhI r#).2A5a799::::;;H;<<=>U>?A.AA@?;6/h$,k< с*_Ty<ƫ䱩gii &T $v+010.{*&d+|+&ךKͱ7ֱQ]*Z@ 1/% *A.2O587R89:;&;;;t<@A5BuCDpC.@>;5s,!O͓ Dx֪ͫx́[ۈ6 )e.13n2^.)#i_ Bzbm-]pX 8Fv1 ^!d',d0Z3678929::::;A;P?@ABCCPA?F;4.(ie =޾%S5Ĵᩔ!۬L@_ټK!дP-&-.2_44*1=-2' vݪ-O*:}X&s#b(-)03R5678 89O9:,:t;;<=7=>@iABCC@<|6.t#9ٷ%q8ɭqp̬5ol ۈ%"+T045 3/*3#9 p-eKӶ׌۱P=A )M 0&6*.1l345678.8c89C9:p:;<=>@ACCWB@j;4I*K ?=֙̑Ċ׸YW۬跕{i!~6 $6,+2553=.("8)KbݣץҖμVːS΁mًގY/C BM"',//2V4+5G6 67&7k778?99:':;=B>@AC,CB6>991'H zp+˼;2ū⪒,QDQk)'RYS *,05%651-y' ' y-uL*̔[OK3 26(%x*#-03r5556<6667V8\9o:<:;l<=*?^ACCDDEB?,8/4#^٪ƑܹB|mf8xr.|D( N&X.s377c41.,'$ p45qαEː~CӬ-P +!0'`+/:1445 55 5I556789:;N<>A]CDDDBM<5^+/PRԻ]WȮKt!+1i6R8{7&3/)x"0eNZʯΌѭ+F!<D$)$,/o13&344y5#56'67=8H9a:R;R<>W@CEhFzFhEA;Q1$/7C/$ԩ׬ǰdVĭܰ|$g'F/*4W7b75;0,'% s޴S7̩nˆSf1J( %)- /23*34;445456789;]<>@BF(HG1EOBb<3'| ^ ϱzY詺Xz Rٔ`#P-3676R2-X&@u _w֕%ͻ̙kP$٪ާ"b "0'Y+.0293 344e45Q679:<*=?~A BDFFJEC>*6,"N)Ŝ *?%R߭Ƶ$bO dK#(05y7!64/c(!(o'H~Ϲ̽GxEܲL]A G_T$(,#.0122345l6\79(:<>@?t@BfCEFFEjBQ=#4V'm /pFeǪWQ Ʋ_C©)3,_Q E#,b2K543O0*$= HP ۸6ђ]̟56ѤՊ|"= ke${(,B.1234P5<6W789:<>d?ATBDnEFFEBZ=7/g"?3׍[WL)i+d/kuׂ4!b) /o466@2.)"nE޿ؔZϹtL̈ЛӳrۯoPs##(+.023 45 56c79I:p;G6@)ABE FGG EoA :F2&(0 /߮9Bح.b!-Gqy㼴J۽ >V$<,267`52j-%)` hrڑ՝Q ̷̒Q6i9~z8 p&+$C(d,.01 1234579k:;=>@C0DpEG6HFC>r6q-"0rR#Ӿ#%1RߨdGgHߐL !,92565B1m,^&  rMפ̽e%WhFM lO~!&6),+./w0Q1!248568o:W< =&>_@BDsEGGGDA=5f(| +xH"U0?4+ D8xOj'0$5775N1,O$ ` ޭ: _+RLh )S#'*- .0151235p689;=?@BDF}GHsGD-?3951 %H"Qίݸ";we1!Hc4xX",4e9y:850+P" i &jz܂֜ѝ).Ї:Jtl'I [rE!%(+T-/.=/001J1235f68S:"<]>l?ADEFG.EB>B7.l b 9ټG4ܭ*Puũa ɗѾ*d+o27::72-c&P @zJMަjQ˓ʡNѾխ+G`Z&$N'*;,*-~. ./)/013Y5!68d:e@BEFGGGGD?:73+ Wހ_Ӻݴΰ'h窕յû¦ ޟ~e#.5;> =T95 .&ZE7@e݄΅_ʤ9}ժ޴+ !%g')+++,l-r.G/4024>579;>*A`E'H͖xMEΨ^LgĹ:bǬ-<6i r*39<=<72*!: y?;$ϝ#HsРAؚ݇6|F n'd#h&=(y*&***+v+,.R013|58;=a?BEHJIHF@6([ 2(˰=EzRͩ A(¬ʍ]?(#U'O18=R>=H95}.$#Z!d!ۣՙ.ʮ1ζ2+ڭY9W *D' !%3()*c*q**+,+-(.02w47:=ItIpIGyB9-5 =%q4<͋gᶃ}Nٗ<2#/6;e>$>a;7;0(/ "oei޸ES˂.ӠuݐH"N  3$m'R))*B++O+*+V,|./2C47-9h;t=AFBIVJKJGfC">S;82+"6\Aӆ1 E-Y D#T ]j#&n(v)*A*++t+,.0>136A8;9=@XCAFIpJJ+HfE&?t6) ,,X|֧٭Ϸ2շ߆e8)o18=?=M9^5/O%%G+4kЊ͜ˆEʤ̍ڑ`c,!L$')*R***+,./146(8q;,>1A CGJ>m;N71 ( N8-)hׁ҄Υq; Y94K 3"%')*k*+), ,-/294<57:y=>@BEH`JL'JGB;R1&K>QEƑWo׮̫~CE̸-a= f+30:?!?=:6.$^X;Co̢ȿ˺6?sެ{""%( *)+$+)+Z,k-./1,3R5s7g9o;>mAtDbG@JWLxMKF=73u)N MӽXYϨa$3ְ˶/aһMf)3]9>s@?;5/(Sw܆^̄K!H̳*nbL"|"%(-)**+ +,-/;02x4}69G;G=@dCE;GJAK9K+H>A9/#  b?ܼӲ 8#ۺ7G*n4<?D?j<8o2*! |bv @ev}Ҵ9U߮R  *$'k)+*+,,-./O02+3579;>A`DFHK2LJE>o2"ۡ~ȃ? 12 Œ͙ފo 'W2l:j>e><83,$y}1۪̱"@ɖ ͓(e wE"&)+,1,,-M-./1X24694;>9A$DHFHpIJInE@7)_ {2Iu/ePdC\5.n&08d=v?z>:6/S&U pWCdwyL(Ϥ0כܝ-UJY_"&h)+H+,&,^,r,-Q.0q2K4C69<->A>CjF8ILRL}JHRB^8- LĤJ릎ީŬ-ʴ˺ūΫe{#&.7E=?>M;71)}[ ;;ϓp)ʬPբY,  #'l)+#++,-.f/k02 35799x2,G#V<MODjˎ lث^=f\`) "I%)**+,--./02 35T7i9<#?BQFIJKKIEB>Z3& 38=s(wS7_,\1 ѵ7' *379>L?>:5G.%(;v8q6u=Ҳiwq# i!%')+\,,d-X.0$1=2468:?= :7J0'V fIRVDTyRQ˞̻;ԣ؄܍L"X A X$(!* +, ,-<./13g46H8E:b5@CFI"J|K JH5B;0!^w=}P7A@*Fy 47#7.6=LB+B->a:j5,!a}xoԽИM '9E׉) =|0#&|)+T+]+-D.s./135679;>A4)m WxgbA=ZŧS|%ʖWW; y+5;?G@?<&6/B&ܽ֕+C07ɏ8̇%־i`\ $,' )**+,-/0s135*689;?BLEISKKpIF@7, F z( MYW)oإb(3;[?A@=82 )  ߶ؐ\0wɭWpՈ:` w B $'{)(*X***+-.0^2H4S6q8:=?BSDFHiIJHUCR<'1!#4PОCxSRn(Z3@?;f$08>AB ?t;Q5-h#)z4k6]i\οc}<`ЍHةnh4 P&|#&()**+ +,.301U24]6e8;=@D:GkJ KsJHE>3Y%7 \oO†;-ߦ֬Z[­HpF2AG*75<@A`@N<6.%A LJd&И̾ɾiʿU8זܛ(D-g!%]()/)s**+'+H, -/1a345i7:^@9?=l8%0'> DV׿nq ɠA/H֏RH7gY $i'(()f)**,-/h02469n<?ADjFHJgJ`F@90#ܤѴnZЬR[R={_PHż.7I-P6tl> 's"%X&( ()))_*0+t,-/3124K69=@EIIIJ}HCp;2$ :KٳhlӲߦ֮(APо'%1Q9?BB2?.:63|*  $^ݦR`dYɠD(Ҳֻsl:R< :#W%i&'''(()*,-/136G8;?5B8DGBINJ}IE>4) LɪNhSdY##AFߦ!.6=BB?;6/j%qMϲ;wzə˺Hѩ30AbP I.!$e%&&&S&,&'(* +-/1369.9 1t( A<^J?x̀BDX a v# $%2%>%N%g%v&'T)G+h-K/1N36q9]<@SCF]HJJ*ItF*>4)er!9^$u }:rKZѩĭ!羐H.w##P/7>(A}B ?;5,"m <،ҡ95gɇ&KSD4ll !t#%%%G%%O%&(%),.u0257:>+ADG2I@J'HYDA :Z. ;zq{NgRQßu7d(4a<@BB9>9o2J)ea.ۗՏɅzȅɌ>])ݩx|q p #}%&&g&%%%&(m*D,.#035f84;?CG=IJI)FC>i4'C=Ӳplͦ諭߷t}h0#09?BB@< 6.-# S9޺/ǣȢaբژAr / #%&'P'&f%&&a'1(*,.~0l3=6f9<@D2GeI7IIkG5A8\,aUv٣Ż![bߧ2;ÕEӬݑ{)5w82!)[1z^Qvbئ[)#j #&U''''+%%E%''(*|,/2t5 7:>BFBHI\HNFB<3( :uʥܼA2@ާr5ٷ̽>Rة{_!.8?BCDAW=A7/%h`=%Քv]T8!$&'(%'&&& &').*,v.m025f8kΈҞInX  {$a&( ((( &&m&'()+.&042C47L:r=AyDG4-&uEg]7¶'Ϫ!W"ߧiҲ¾>ű>6  "N09?pBDBe=72/%+Jəǰ$л#ٰULuG x!%A'V()b)D((J'''(*g,-0259<@)CGIJ#JIE`?&66+\")ؾ~ (g =/gw0Wb*5=CyDC@R  %')b*)):((8(N()z*g+-a/D1~4?74:_>BEFrG9GmFvBB]DG9HMGWD&?U980. ^ {'޲ %c򬎰6.޴B'B3:?C)Cj?:4+ $ӂ(` H͌a<- `  %,')***q)))**K+5,./1X3629'<;?B'EnGUGE\A);4(" I#SԆ_¥9d)|9`!/"7>CvDtB1=7/%~O֚Щ˰yƂ(kЎf34##&g(#)z**N((@((()7* +v-A/037[;=>BFEGIHFB:.# D;mrSAR6qeۏbw:'4$<]ADOC@;/4c,!N- Asp3fǍj); _H $')**j)((M(-(*()*,S.0M258H=I]HE0?8*] 8KӮLż7஋%èҷά؂ ),6=B9CB6>8^0&B#['ֹSƟ7˭ώkޜIs:!%(_)))}((((9(C(Q(*=+,.1*47#:>B}E'FHH]Ea@:c1$u+\4ƴϪ4!\3%Z6'W3q:?CCX?:5 -" Fw'd@/ʩN۪vz fW#&(;)Q**)((X(())T*,.0e269=S@DKFHTHGC=j4)z 7hتߧ٪_l΍O9 ,6=B}CA=80&=؎ҕ́ɧTƊ?˘Ϥki  ^"&(J)Y*)*;)z((()=)*,-/147t;>B@DFHHEA&;n1#]+i#<&p(%)R*7*")h)%)~)*n+-,9-/14K73:_=AEGI>IFC=5*?,b ai]M+/?wtڸ13k5=7:=@CFqGHRG9L2\)hp~DҐ̀?ȎN)ܟ> Jo$'c)*+++;+3+,},-.024C6(8q;4>JA|CEFbFE@w:3y(+_S[ش~ Ʃ84r#0 (3|:>a@?;5L-$ ;yv?"́$}˺Ծٱ2R|w VR+ $'e)f*+A+**+,u-\.c/1<3469Q;><@CEG6FDb@9/d}+LEυؾ`xج櫞b2HċPq% /7Ź~!Ƕ` |+3:@6BV@<60&AUN9޻QE%ňǀLTuo2 t!&f(*+Y++R*+ ++g+,.0136x9;q=@OB|DYEYDB? : 0#mWۓE'm³oyr`lC&aݪ}+5+"*+,./D1/36A8;>BDG HG,Dn@G9/ j R͕ٱBt̨(8{9uo>{y $]&2p9>!@@N=P8 1)7oVl&̘ȣƤhxlѷ: 4"m%i'()))**;*Y*+-Z.0A24`69i5|((o BյFʩBܬ¬nҠgmz+4;@BA<7p0% 6ݑ֏Ь#ȿơȽԕh $&(C)v))})<)w)*7*+d,.0257;%>kAD/F4GGCJ>92H$ Ɣȷ'̨ԩ˲Td2ת^K".7O=4?@7>$93+{ & j>|uƲwSK~ [$% #`%'((()*2*"*=+?,.\/{03>58q:=@CEG+FC?90!;Շĝ)$`'yȳ !&18>A@S<82)$?/}?غ̻zqk˃θu?.{T! qK!$X&H()!)3)<)***+,o./19369 ڰy&a *#Z%'))))***]*B*n+3,n-/F03H58V;9>ADLFGBEHAK<84(V SP|JdzȯǬwf>+:!4( ,6<@@A@;5<-+" `sӉ7Ŗ9`+ѝcW)C$ #%'((P(((())*+-:/1 3G6_9=AoDUEGGE@G:I2~%[٦P?!!DS9k2)++$aׅѢ̕ȺƺEs#΅gEW4  !$3%'( (( ']'( (a)*,.03=6P97- s`1:g?kFG/axA+Z6<@4A@0;5.$ c| @ƓKn~_aՁ_1,?"$%%&&&m&|'-'(})D*,.036:Q=@ChEEFFC;Q2'q wݹǨFڳͯt̨ʨo1UͳGN,,>"/-8'>A'B?:f4",a! DIةbDRŖ2&~ #!#$}%X&&%%Y%& &'(*-0n3\6:a=@BDDDdC?9M0&(Hd;>WGP$l3)SƳ9h8R F/&c3;?AWBA#;s3* i`4g1Ip+Ǖʵӏ-kZEV!$X%%2$%$$}$S$%t&'(*d,u.15N8CCB?K80' UXi[ſơ5̴Рէ|Zt J@"4$+%%D$$##O#M#$$&(*2,/m26:>IADG(HEA&= 6+eh1|c5&h֪rqԴں!ikY$31!:@CDB>7/%[' K0:"Ȣ0Lɓmb&W_ ;""$6%V%%%+$$###}$@%&(+<-048D6-N" O)9Р˺ŝīEɸKޛ'm( E!V#%Y%%}$## ""0"*#+$&'*-1C48g<@*CTE3GHFA<4(w@9乂/Z׭lo):qϫBo &1C:@BB/ADGGF-C">b8:/#wN͙/n\e٧1Y@YDۍT)h3I;N@YA@g=W80&&B9}* S_|Wf:~MCT*b 9"D$}%&8%%$##$$%$&)+x-0937;>AtD\FVFODxBL=5+$ԼO7f).{v˜ӽݶ +I5W<@QA ?_;5-1#8 \4͎wapDǒKܝ2)(] V7!"#$%&\%$$<$'$v$s$%'h)C+ -U0L37~:=@ABDEA;2(1 Dz/¥}^ojgt ׏&5" -7<>><70 'IOp6i͵f1.W2DJ} eF>"$/%&Y&N&E&%$% %G%t&#'M(*,/~26$9=?AA@>:+2)9cҲڰDϮPaˊҲcw L&.s48974R/7'21_ܝҒq"^nc=>ZVVA'tLLb@H lp b rz4!>#%$$9##"y QL_R)I" 3o/Վy֡ٗo^ hH}9atG"O"|ԗwЈ='9 Y}"%c(,k/0///-/+)&$9" TR~sR 9F8-Բ9ϹкѿՃOW W$!]! t/@qҼW/QHЀVjH \=x#( *-0$00Y01T180A/>.-,@+r+0*H'$ I {k0Ԟu˕˚ˌbރm \#$F$#O.# `!߯حDԛ&ԫ;X~%O$)/+-/1k2210/k.-,,+*)x(T%!#9]+ȷň3Ʌͮմ;݋N "$!$$%/#` b غ 1b. }a3 $')*A**+,-.-.U.`.-,+#*)/&B#!<L ' Sr5z~ʞyҍ<rS`!3&((%! abjrMAӯҴ]Jտqm-W_L!"V&*-/>/0000`/.-_,I+,+m)(#&R"#T'RI.Ѽp^Ȁ=j ")-//.+&/1mk OEUHзԗwߣ6 b!H&E+,/3456j667x8m87z55I4O2 /h,*z'4#> F#Sć;AS(5UȔ̶>ّQ O(b3p:>?=^81)@,8f{Ѵșfkβڴpib '#/5~9X;q=>@|@?=sADEEEEEDB?Q;8 3.+(#l0 1[ۜyſϷ9Ű9PNdH$c9 iJ-8>B_CA<5-" Y%ИƯZÕřzE[W X@#, 2N7`41-P'o7G߸aú|Jij8g|ԋ۹<)#0C8<>>;5.J&>?5}TŨúSUhٷ1|$z!V)Y05:=@DFsGHIJIH+FIDB?\;t74/)C! 9,C>ƅ/\^گݲȺ0u‚hZ &1U8=)>;71 (1u"oZĠMHÍƞL[ݎ #,T4|;i@E7HJLN NN LJHF^C?<:I743-' ^ Wҹɕš ݯOYEQJQ)2B +E28<;71e*N!ڂҵ^³l VjKWޣao (0Y7>PCYG5JMOOP?PONKIFC?G:40*9"t+kǴ@Ķ,DZӻQn\֗߅U &A1N8;<\;6/%2wTԾ̣ƺŽ}BL˼QI!)1K7= B2FJ'MOPQ PONkLIFC@ ;7E1*"V4 UBʬ<򲘰%U쳗qui/٥[K +38:;783g+"o ?S04ˤhV翅#͖o % cR&.4:2>B'EGiIUJKLAL[L K:6/' |ܳџṡ˳ANY\[K i$..59B983D+" 'u ^ǩnw3ĂάD;z ,H$1+29>ZB/EAGIJrJKJIH2FDB@a=:B50*" v]֚ݾlвZ6q廘z̈M0? *2676b2+# Dn?Q-tVBܽŗˡҲڑGExB?v;A60)" i O3NҼ巿NpSC{,)-x $-4$7)74 /(`i[Һr?2Ө,Udv#h,M4c;AFJLNObOOOlNMLbJWGE0Bi?O;45r/( J'R{\UaI۱5rt xI܂q(B05 6<5d1*"Ul >nG$u%+dƑ̬ӛfnsY"+3:@{EAIKMNOVOsNML$JsH@N=;74/.( }D c շ- B򵇴ĵ߹\9AՇ9DO {&,1/=.+{&#9t&CbǞ¨n32J¾f"'/7>CGJLNINNLKSIHF8DSBi@r> ;g8\5}1,%q'lo{n7"")Hٍqb4R4" (N+,@*% G"#os@GQp_kh%.6=*BGbJLMMMXKJH@GEC\A4?D=;:73y.3'P-S c>wW7ÒS񵘵 NٽSnΖr>7B !',.+&P /WEęW$5}#'Hԗp&/8>DIMOOONM"JHFDmB?@k?=V;6851-I' 0` :&Vض-A6o߹1 r;nWU^#),4*'?  ]% տ*6 bѴ&AF%/7\>PD6I#LO]PiPmONLJ`H[FnDRB?> <;973~/+%ڢϑʺ᳭ᵇ۽xRdϓ};  C'++)#R3UPתcнq9 %4( ."~,r55<8:273/Y+O&f rY?tŸ򻸾Dp<k'$9(4)($6@ 0)˔EԽc0Yysc^ U )2:"@{EJaNP@PPONaLIZFD\B ?=;X9876<3.(!c?_QNjjݷ=5b>bs¬Ǘ˺(ޮe :$&&#Z' P>Սq R6>D7I>MdPeQQ|POLJOGEjC@><:.7s54$0v+&!YZ_ڌ.]E̊3ע)iVr%''$ZP kr˄iֽB͈ԬoP ()3;AGKoNvPCPPOMKfHEB@=;[92764n2J.*$"2gʺRmDS;;xn2[ ]%(U(&P!w|~ܽxÃBX՟ݹ;*Qp-&/7f>SCHlKMNN$MRKIGEAC @>=W;98 64V0+% 8ֈs?)ʶL׻F.wK1EY&*S+)%uO/Fq5MF y~<Yd$.96G=DI LNPPNMKHF5CA>?J=x;:99752.V(!5^ѳ=tXˡbOߒ"od%+O,+'Y  8Gć޻ڿϞkrs&L !+49<:75i3/`)"RC3׽]+G׷5/{X݃xq%G*Q-U-)"j{ޕP"u͡3 <*\3/;:B8GL O-PQ7POMKI"FDA?=;9/64h1-)7#Qtp˿5LĴ1^·'NʌQ !2'+*'l!}u#Vڿ2ŸǨ^$> (19@SEILNO|O1N3LJHFeDCBb@><:853X0y,&M[{z괠&p-Oǂt٪` 1!(/++)c#'{}vDŸ̏H+z%=M'087?EJ+MP Q$PONcLJGaEC@><97/420+% E*`@\v쳝A쵑ۺu©Ǎ̰ޭG3&)+j*%= "iX w * :dh$c-6\>DIMPRQPOwM\JH(EB@Q=;}9r753\0+%/ 7ԕZ˻7 $=͙׊v%>),S+'1Q7 ܛp˴kÿ?-׸|Gk f"+4';96'3{0,w'"^a*`=~ķK򳨳乚``r67s A#)2,-C*&#kh|MT- [k(%/8{?EJZN$PQQcPZNLJLGELB@>r<9752/1+ %+(coܵD$Nе8|2' / b$$*(-.,'8Tv "b؃|ȟo6Rf׊@S%2/88F?F1K8OQ~RwRRPNhL'I|FCA?<:174Y0-+(#S0Iǵܴμ$Œʃ\ ? $+K.2.+&m bp;.[*,cßȷִ߸.e $+.#7!?$EJNQS RRPN|KIDFD`B?5<79741.%*$M$ZǻW"X%6MɅՋxkK{!(P+-,' V /9 golhr "E,5=DIN`QSnSS QOMfJqGkDA? ;864L0,(l#IN9 ԫӻɴճQ7&l^Yӯ O?M  ('+-+& v:4At/Qڿ dͰJ J!+4=CI3MPRSLRQHOJLIGDUA>;9E7/427/+&3 JշT1} [Ėɂ\Ѽ+Ob)n &c+y--[)"  VyZ'v<ƶ̠a& a*3;86831.+%ZU K~sx_ Dv¿PvθWG/%_*-)-y*#:]d̆qSakG9cƞ]Wi&.t.(2:AGLPROSFRQOMKHE B>;N76C5#20'-9($!> ׆ͿuǺM}{wOǴ/Om mV$2),-*0#qSs7ƛ1̼pwœˎҤXj'1.9AGL}P RSSVRPaNEKIFC@=;86=3n0-'' Q Kjڿ}ݷ|͵08L Ãˑ5O%a $*,,)#5<ΖP-VOQLQ&0;9AH(MYQHSTTS Q"NKHFPD"Au>[;853Y/+&U Wprhk϶8d=F*շF|= g#(++)# ؟πh𼦼kİ#ؐ $&L0^9IA5GLP$RT SRQcO]MJaGDB>;"86530-s(m!, fx`ΨVve_|&5֐ ]$),T,+%>+7N0fJ^߻) u&0>9^A]HMEQSU U%TRqPwMJGDBG?Q<96p3c/+& hyH;N!_c^X}O[-<`/ 8.%*,,*D$Z4kثϘtaŻ"(Ld-֫~*  %q/8ABHGMQLT U~UTT'RPMJG}DA>;852\/&*%g OJFF-hS~f؎fB<%+-Q-C*$(thϿӿJ.ָߣ 3$/>8A3H0MQTUUTRPUMJGDA?< 9630,]&],ihŚȻetai+ν4f %+5--"*#9q5 u,ƿ¥_} $@.8'@H MRHUV0UTSPNyKHMEWB?[<9>63u0,&ř6H߸@,CK7ӫM]3F&+'-.*$35}uιN×!/L D$e/h9B?ISNS7VW7VUSQCN8KHDA#>Q;952j.)b#XkS1bLo!L_i/Dیbg.u&|*-=,("FXF<ק,s|0~þ‘pފ% %T/9BHN:RTUUTS]QOLIVFC!?;!741.*/#RwޠÛkĸ@C>Լ\c9ܺx;KZ(+. -J* $~h߱.*5fϺȽC͕ s M%0S: BIOLSVkWW[V TGRNOLIFPB?;731-(!ܓҍɅ¶^?sFqnֱ1i7W"F)3,-,T' g޼"µ%sFY$ߋ.M&1;CJPTW5X2WV#T@QNKHEyB=:6f2/,&T Cɤ&W`>íf͓,{."(~+,+& ӹTtP&þɌXaY '1;iD JPCT[WWWUSQMJGD@<9 52.*%eU O{ķkĂ8N!!3'+h,+&T RNAۍھgoڽS@'2>;DKQ\U0WvX;WVSQ]NYJGNC?<96R2.c*V$] a(ٳvfWHz۹ϽX^Ȗ͏gٱmW+ $*--*$[{nX}m7ϻfwqĚQU_Z *04x=FuM`RUWXMWhUS:792-e'! cϹtoԺ˹H~־4Wڀ7j _$*,,(", ŭξo+ļ5ax+ 5[>FMRjUWX WUy%e+-\,)!"Ўɵċ Ͻzĵʙڎ7!-7*@UHUNSVX(XPW*U7RPvMJFC!?~<852 -)$#-pTքJR|cǹٺFm²zΠ_E`&"*Z,,<("WZȌ'ü Լk;| "-80AH}NSVXlXeWSUlROLIqF.Bf>:M7J5*2.)z#8hxfؾݹ3)H.R:Ԇ&|K t(,<.,$&M 6?/ ޽N zƖ; M#S.K8)@HNSVXJWVTROLIFyCt@j<9 52/)M!&DҚdwXyɹE. uˇFS.! #T)%-%.,'1? wǂ-tMM- Ə̜C`S $\/9BJqPUXYY3WURP.M0IEB2>;7413-'J] /X}G{v5yw \ͣӬڌZ ~#o( *,*%T\ 8@AI1dz־¶/Sզ+Yb&1 ;"CKQ-UXYXWnU\ROLIjEvA=:63/*$K 1ҿFʹȺ6׾ŝ7I" K0$i(+T,)#pEھ7]~ fèKϯXk('2G,NMSWYYXVT,QgNJ{GGD@<86 3.($![%\vhĿ%bUiV/ıa̰-b j&+,+'d  0t{@"IJ罽yDʺ^LQ +6@IPUCXYYXUS1PmMJGtD_A=:=6j2.('? ܖ~˓HǺbq̶zC /#*u.>/+&& E &#fAǒԾ!C"w&$ҴZq #/:oDLRyWYZYWUSP LIFC:7K4/)#"{α..ĽǼټʾVˢܞTIr%*R,+'!>el_L$)5?FGNTXNZOZYWUbROEKHEB|>:63.(X!@j<E Ԝp9ۼ‚:ȭ8ac<Z%*+^)Q$ e߄083$"8@8]'X8)*5?HEO$TX@ZZ0YFWsTQNK2GDA>L:7%3-' ~ xEp̿ǴA- ¼ɂҠvKD '+)*)5$B `#[ȻĘϾg޾}ALY!-7A`IPUXZ[YWURNKZGDA>;7 2~-p'7r >xGO!TX[[*Z XfV3S`P"MIF&A>m;>61m+& )ۧd`À!ؾ O&c*P4+ 6&u)}+A)7"Mnݑ>5ϼ3ƝRS< ,7AJ.Q]WZ[ZY~WTQNKHE AA=95+0*%RK2ٞaV¿P[0`HlS^$t''%{ @iLĄ&佛pǘWuyYE $m/:CKQVYZZYWUfRO-KHD@<7k3/*X#|ylɧVr$OȠЄ"%4 "p!&(*($ 3ucҝsgg򽢼Ѽ߽Λձk h&2'GNVSXi[>[ZXVSP:LIrEA=L9r6 2.(w Ou¢bǿUWÙơʖ Ӄ\ފw$!"&(F'"D,tZƖ«XwLj ŖуHzi!E-{8BnKQWZ\'[Z!X U}RO>KHzEIA>!95|0d*$I d9Xғ̊ǒ(`0yņȑGd#ڼ_B9#q&\(P& !.ܛa0u⽢EPR7. #/U:+CKRVWZ[[?YWTQNKH7Dj@<9 4/1(" ZŝؿoZɯN? ݰK9 4a$''$53 Jڜ6ж5 p,8 BK!R%WZ\9[ZWTQNKoGC?<84}/*$1ׅXʳ¨Ue8Hj͓T|?'eH2 *%`()&!mMT`NGս˽/$Nj@ԑXDY{ T#W.9lCKdQVZ[>ZY9W:TQxNJhFiB#>':7S2-("#A|}OgÞ9:7>3_.)(")uߡ=@־c­=ȑ:%m$(*)&' aIZؾD "Լ{'ZЈ*"2]i(4}>H-OU>XZ[Z)XV=ShPM2IEvA?<7@2-'~ r]ܽuhj7JXZ.32VޙnPz%)*H(?#x[ΧaMU˲Ғzd ),@7AJWQQVZ[[|Z9XUJR0NKGC@(<|8Y4}0+%mL D٣N1пQ4—˶g} L!%)2*'![qҭ̢ Ͼ{pï;2_S +*# .:CKR#WYZZ&XVSQMJcFB?o<08>3/4)"|twnʐůšN{kűD(ܢ&Lm} P$''%  @Zl*' ~O=|&1;DLxR`VYtZVYXFVSLOL_I,EB.>|:7g3w.)i# L\Lɧ¿ ZìEcHr "8&6''B#S 8׸5qĿwsEƟ=\IV(U3x=FoMSTWjYYXW$TROOKHxDAv>';914.)M"1 (ݔk]\6};ə0݇= %7'n( &"y/`ǽ#?˥$5_P+6@fIOU:Y ZZYWU`RkOKHXD@=:61+%+ Bܷ lì;4Q0ʳ;:no3Q*{$'}'% ԔͧȦĠeZ Խ2,} *">-8dB/JqPUXZOZ2XVTWQuMJ+FCG@=<9i5_0+%d  ܝӼ̛HÊ[v.[,<5ay'^n5$''%]{Ǿ龃#\ɎmT $/9BJPUXZ YXMV#SPMjJ2G!C?K;774W0}+^$| eo̶]p .kl%gd $`$Q'((%GQdRڲұ̏zk~ɿňʨ؀ D&1;D0K|QjUXYGXW UR;OGLHE A"=:o630<*$Jg o"8P^jؾhL|țQowL$K'a(X% U ˛BGcsžƼ*z 1'^2QGMRVX XWV{TQNKfHEEA<8M40,'"Ird~l}ŮGX,AĦPU ~2 !&)i)[%!E- m'erנϰɪDp}ԼcƳ̑aV +5?0GMRVNXCXhWTUSBPZMIFCa?Y;>74;0,7'" mdۜҏY)€F$eĠ'Ѓa۞s`C ko%v((%_ V%xLFi5DÄU9eb m  !,6Y>FMRUWWVTRFO.KHEB>:730-(#7 "Ew܇Ӣ˩łݼ7NïDŽ˹ԺXX[ x"'Z))&& a [fPޘG͎ǯhA< 4#C-7@SHN3RV WWVfTsQNK8GEA>4:Q741 ,'"OG ڏ҅"ħļtEɿ"=о+l #(*))@%IJ Wy} ~G]QΪ[ߋf%g T%/9B*IHO SVWWHUSPMJWGDA-=96v30,r'"= oz`VP̱1{˽_{214|+̢^6{% !')($ 9+ƬľspkDÛȾxתr&1=:tB_HN^RUVVUK<+_ϊA+p&n09AHMQtSTTS;Q!NKHzEB?F1r.D*p&d!8O1ɹ»vӽ}ìǍЩԳ٧tGU ;"%%$/MJڈʬ0ŽbȧϤסEO)^e%079AHlMQ)STTwRPNKHEhBp?=96t30-o)q%c @ ^܎Ěº¹׻w%džʓGN]8V\ cf#$\# }O?GP -ˌM޾ ϑׂEr  %/8@FLORSSRPNdKHEyBn?<9^6i315.]*&"r ;1˓!8a1ϺH)ɤًvR#9$N$("* h<̎`5Wy8ȳ߿#K $U.7?FKORSTSJR,P8MKSHEBz?=':C742U0g-*Q%[aqĄ#&v'W~sNȬѱDݯn^w"]$$" JO ߽ǀ͘F #&-6>EJqNuQJRSPRPNLhIFzC@=:853p1^.*%%2I)ߏcL")ĎTv^"%&k#8[ 'eyͦǚʿŽhCEƝ̞ܵ !,l5=DJ>NgQSdSRQCa@=`:M86N42/,*([#i ;ʸ)۹EÀYxՄۖ ^;P"u&1'^&!fR3EEd"Q&?º,Sr*4^T;9p7i5=20Q,'"#_4ߎԽˢ_Xߺaxel;%AzD"=%'&!9|ZfêeŻ=d(2hh)/2;BHMDPS;SSYQOMZJGTD)Ak?=;8642/y+&!f ڄWǒ [N"ڎLwBf$% %)#V6uojh$~ɤ G&_09@-FiKdNPRQPNLUJGSD!AW?<97=5B31B-)%:zF+۱踸xD̦ބl2@"%(%["  ԍ̸ƺ©@49+π\4 #.%7(>DIMPrQQPO#MK!HEB@D><<96o4n2%/>+'!jq4eܷһVE' Ysslp9 Nf#'(.&D h ""!åȾľyåb~ 9"),5=DJ?NAQRSPRQ(NLI;FEK/OWR;SSYRBPNLHEB@c= 964}2l0,))$cnrߒ173Էʸ` )Aڢd"&(o'Z#v iC _}ؿƽpϐߕ[ DN#.7?KPRT6T@SQU;9741.%)$CAV9ɻPx߸ԷƸL⼱L "&((_$1E >ң˘&;񽺾ðȸBև޾ p1"v,65>FLPSU/U2SQOKHEB?=8:9b863/+$. 6W뷙J4EǿÑ'n#&(X(9#5"aYn}uqFP݁JkL =g"K,6b>FVLTPSU%U^TiROLIFBC!@=:37|6+41/H+&g'RʏZl1d 0Jdz̃ѫmF7*!%V''g"r C[ܯ[f;ibJ  M*4=EUKP:SU[UT9R4OLIAEChA>r;806q42/+%Tޖu˔Ex%}8Ј.W! % (9(T#bR f{ qZ*"{Ӊt *3IFDA?x<9x6419,(-#27ԺQŻݽ1q ,7h!էS- o^"{&'&"!t2 &݉ԇ$T L4b"*4=ELlQETzV VTR0OLIF&C@{=:M87,663.)@#7phSŋ2c=¨Ƨ8s?s"&'&"-f 9 ͽI>Ƃې[4%+#5i>rF!L7PSU{UTBRnPRMJGDA>};87\5l2m/ *$}kF.LUPSUxUzTQOMJ7G8DLA>~;n86z5#3/*$(} J(=ǾBهA #(o*2)c%I\ ](ύɨ̽>i#`k0) b\ +5?GMRoU0ViV,TRP$M,JGD A"><:9I640A*H"  T^l껩ʹ"ۻf ۻl$(*{)%' 7,֖S(e956jy;9l7B5'1,&YL͡ (ϻ%9n6kOi!H&'&t#u I+ zX@Ðvݢz\ w#4.08AHNRgUVVXTRuPDMJGE7B?[<9r753".( *n&)kãIu/K³ŋ SԹ9>%)H*($  9vbSÑɽ-0/"W(O@B #$$/O9BJ[PTTWWW+USiPMJGDlA3=;p:$862@-)'#{?ï񽩼ϼvM_;975_2!-t'I} #)SH\ e¬Dɾۚ k %)<*#($'zA)Y^›5ǻ!E`  %0;3D K-PTWWW8U\SPKM)JEGD@=; 9F64 1W,& ڭWx\lJv˹x !'*+)$iEbAҕˀkvռ$O14{ 8&O1FN5SW.XXrW1UXRO;LUIFCt@V=;98#50) "J(#~wݽ*WT?F`ɁFfOTt"-(-/'.)o"Kdh?èuM-Z2*6?@wISPXUbXFYXpWURNL IFC@g=;851.(2X5ԑƂM;Qˢ&Sz*HZ!)i-P-,)?! $(ԥc1eCMԺĢʫђNH!2,7AKIPTWWW:USQ\NKI3FC@g=H:751+#P;˼7򻎼esƌxۚ!)$,--)" Wӑ̯R}I"ԿIJj= "-8BJP^T(VWqWUTQNKGEaBe?"t0>KYh7ݻCS9ݛI e$/:DCYKQ[UWWVUS0PLIGWDA><6976?2,%\n҉˰6ϼ̻׿TS_ikr#a)m,p..( 5g dې:󾐻rscZ72 %C0;DKQUWWVU RP'LIGDDA>^;986 2,%3HZ۲҈œBqD7!ÀˀgQ.PN go$,*-.,&* bќ}ƌt`+ %1D<-EMGRVX9WVTR;O1LHFC@=;973/I*$nfŻ?U!wO)Dxo%9 W"0(,,i*!%J 9+t@qȼXȋ>߻ K&2\= EM(RUWlWUSQ~NKHFC@=I:84640,!%jNr0ұ|;b1UaB}FQ? `#)C,+,*%ch@Lۨ?uƥF޺Fr΂֗oQ((3=FvMQR\UVVUSQNKhH@EtB?=j;J:86 1+$ %ڪƟZtt9($̠wj+N $k*,,)%dƩ`Jλc22:c&3>6GIN)SQVWWLV0TSQN|KEHXECR@><':85i1@+$c V.SjĈ[RqIy:ؑ qz$/(+j,1)#/(y@pȀΧ&p(3>DGCMSFWXXVTRNKPHzF>C@{=n;-86X3X/)f" yY^kťھF-`wɚOӗ5ߙIm z &t)e* '! _='³Ż꼶P&oH"zS`X(3>FMXRVSWWoVTBQNKHECe@0<:675w2.7(" w#4n_†1_ƽ+ɚ[xߓUy$(@)c'E!_k$s҄/1JڼV齺b,ЩH (3O=WFLRUW}WEUSQNKHEC?<97=53.'!+ -ڲriνk@]Δ٭I vG~#8&&Z#GHB۔?Ȁ ̾tD{GotBC)c4:>FMORTVrV|U.S>PN?K^HF1C@>;86=3/~( +1dbғ߿.H~e#Q_vg^'Q"$%~# AZ!Ո7t!پ6*d96)4>lG!NDS2V/WWVZTDQO;LIFD@=;841W-2&Kں˨Ɖ4@۽G?O|_gEabrl"#"V /@݀cchʾʧѓ٣:nq W+]5r>FM QUVVVTRYOLJ.G6C@G=;O85+1-&bzEf.ê!%C47χԐ?W}>@NEdޑ_-ƫÄ_iD|ҚT/`*R4=xEoLNQ4TVWVTR\OMIFC@f=;955k1Z,&AS U1LG|oFHīǣ0& U[FKU`~?zȤJ6XpƨHٯb*-(G2<]DKQ0U&WXWIUSPMJ5FCf?<9F63t.)$} LGŤ]ݿr:dŠ<x@p,r6e l6l!GWۨԢbj])Jdž/ҋ"6l'Z2;CJOSrUVV`TRPMrJuGTD(@<85a2/|+& @؀*i{=cϐSYvxEcPlu 6ȾĈǎѫ&"0a9BI,NRUWMWUvSLPNJGC?p;8U5L2.+r& 8 OJԋc@adncȝˤҼK- A5Hi]IH1ts}ѧؾC7 #.|8.@OGTMcRTVOVUSSPpM3IFVB?J< 963.*%t1]dٽ 7c ȑ˾-Rڏߨ`>I  = 4EWk1bFU{>6;B%l (!;+55=+CINeQSuTbTRPN7K@GC@=:6h2@.|*% + vތd\Fū[ĄŠkɡ;U8]2`G ( k3"B,HˀS҅"39a&0i9'@G1LPS8TTSQ{NLHEAL=9d5/1 ,(e$l qeٶӗarLjŭƹɭ5οӑޟ2Sea0qӯˇ1Ї&vߣQ "Z+4&;BH/LOQRNQPyNKHDA}=951,'"" r1f+ؑљ˓[hσѪAאO#3OLO*^޾ګ֏qRP֝ڤe4 \q'/7 =BbFIKLLL.JMGDA=:=6[20-)%!f3 #EULAZB֕ԥpҧ=u* $[_\fVU}Vp CDkۧڻ'M2ss&,28u=PAPDFHDHHGEC@=:7305,W(2#Sd > BPI/1?عR_]AUZLu]h>\$" ln$).G2579@:":C986425/,*/'$"R]AgS H*T4ߜ@gmP%x!!6Tih$w <";&r*"-=/1233312=0/-+ (&$" u`$_ ?s.Q$|m& l[#4)qr;9SZ6p Do #&](@)**** ('Y%#!BwM`d9 -Zd}^i!W99y1.>.\Sc!y[Kk!}xx u!#%<&]&&&q%$6" :2>v}  ?!{;Jhm^=Jos+2) %;Jv(:R !  ;Fd !!!K ~I0U ,]k 4EUuDY8xv [% 94h AW{z<c_lrp : 4JugIztBfO~/QnY+6a&% 6` m 8z-KQ xB3ak 1 $ k93zK(G_gF=n^ HwUkE QsHd:& A ]Ac8^  T 2Z"r`v]H+^F|} c,H|  X};mw%- ?  ? X  . 7KWS99`M^=6idY/  ? T  EX  zxA 5  jY 8:& gXlTM,?_1!O 8k} x g <GN % Y%G =" 6 Q{'!AxKk&NCN9JU{Go  6 % D a f Z k QJOeH% loh)rk/ZHNqSzbnc6OO*:-Jq i , 3 k d O 9,QK1L+&_84PjGAX S{xD\eݴ zd44bQd_.|{io?  f $jSh1 !Q"A##X""! HX il^lx'cH٢V$04jo=r޸R>yLsa."{=cnA I0 !#2%&w'()R))p((W(F'&$G#k"m Z E'"1"@׺OӍ ڴ~ުOiDJ1RNJ79w ]o#x'7*-I/,01.1 0/.-m,+*)( %"k py2,Υ\ծkMuSHI'Xw=l3 RA"&*(-!/23N345 4322H10W.,)&t"% Tz+EО{y?bͻήу*Fۖ;i o  FA/xyW5OY[ x#Z(u,0 2579+9: 9998\65 20.0*&"e{L 63n p͑B;N?yQ̘%܀6?>L s :T )%GbJSv$J &,/15L8;s=>?K?9>>z=!:7\3/+n&"U g?ۿ-ǰď—Ušae?ȝAΏҜ_ uas x  } up6֙\&tޒ8 /'/F6%;@DLG"IEJKJIHFD~A?;8t40,^'"qB .xCۏW¬IlO8Q:ջ^Y8dNU %< \@`W/kvyݦ6M?< (0B7;85S1-(" i4wSk#?KæZdDϩ\ٞ C 8qCߡ۠N׵k(wFuC (1/6:<A DGIKKdJIGECA>;85<1?,V'!DOXVӉʹgVVÈ[džɵT[Qrx$ d Amg ! *g/rXީ b:!)07uFBFIHK=LeLLJI6GkECA->+:7K3@.)/#o) `V%@}ƍuvÇϾ)s 9%c O* $1dl&־F ߉ 4l R*%-4x:?DGGIKLLLQKJWHKFCA>;8S4.)"b nۏ8;,Xv5ūP˷jIC  U^jT ٥՝ՠj &S 'a/H6mBFIKM=MMM*L JIKG^DA;=:7j3.(! 1 _׍xsWn WA HxS S |S;u`՝PEH?4$",_39?%CG!IKM"MKLL:KJIDFCAD>:6w2-m'd D ӈgRY 5q';7V2-2&]/*'bԫNÁblԻb;)DZ\l Ƽs̕ѓ޵WJF0t| |9ׂ okϬі2 v JL'027>CzGKGMOOOZNZMdKIGZEUC!@=|:362t,O%`.1 hawJ¨lHڻdU|) Ad >yubҚ8άΏmڂ|/`>;"+3:}@AE HKMO(OONM K~ItFD3A>;p74/)#Lh AQީMDz'2纋Ӽf̥ѳׂ1 /!0 F 5U̖ϛN9'M08A>DIMOQQCPfNLJH7ECB@E>;9G50A)"B/H7Β Jzغ ۺ þiʍN)ޣ!  t!"a yp [̶3~͇Ѣ!"@~S$-6C=CILOQEQPONLKJG8DBAd?> ;8D3]-%Gbذ!(úi F˜ŨT&CO!#o !!mB%Baɚɖ̺ۤR D",5T;8q3.( ^ U 6{0KAҹxھRHvۥ 3pt N! fxml͓ʌ}ɉ]2ڜ< Z*3;CHMGPJQRoQP5N\LJH@ECB@p>l<_950*f"5@?,ubݽLE&6̈8NtJ ZYd""1_  ,;bX۝<а@Qd$sز{2t-(2J:AH LPR RRPOM9K2HFDC^A@ =;61+$[tɿo~Yչ4hK<:ØƩ7ΔڂB ir"$t#  [ ́ɝsƝoj-<-:(2;BHM"PFR\S?RQONKIGED4B@`=;z813-$% T6~˹¸{G躶<ĺr#% "$,#a z a-DH۱ԛM$ƽŤo@۪~1}'2A;BI MPRSS|R;PyNLJHFD_A?=;83.@'Z1/ˊGʸLQ3Jk)̟сa aI"$K# LxXC~nO 4\Ɉ͝8Rqrg&B0[9;AGM PRSSRPNM#JH/F*D(A@)>*;48'41.( ;r"ՎY1nO޺I7#o˟U~xP  A$W%$!`^ h;mڮIʁpå ǹ[׽߯r1 .V#.Q84@GM>QqTU%U%TRHOMDJVGEIC/A-?<:85/0b* jnмrRu)кJ0hQ?*ָXzO!2$'5&"8 d:|ҶW.ö‰ģSCz [#.g8@GM9QJTU:TSQO+LJGECA?>;8v4a/)! g NAZݽ%䷰:n%x#'0) (# ?Mz=F<klIÞ#6Ϯ0/[ "-7@HMQTUUT?RKOM|JHjECA?<:c8651h*# A˥[ع뷰 LU˾cQa̕gSPr!'+&,J)t#@,V˕Tvmz°lZ #.8AI3NS UFUUTDROM=JHECA> u2jtzpQ`$Xټ̿|=J0!*q/1/+$e  9Uϔ)׽ HhN1&2:[<:62&+"-mE>@#s"Q赳࿽Ǫ0ԭܓk(f/4`41+W$ iK>%ySyD2hoΌj4mh|l*6f@HO;SVWWUSQwNLJHFDwA?=;q8k50*(mv&@ûBN%²ijѵ*+E#,14d5 2+"~ J Mɼي !)-8BLJ`PTWvX5WvVSPMK}IhG"DdA@(><:<62,% dw@CӅ罵aGݴ#37|Ƒ;U.(A(/574/#(@%AGߵսVyq'ń˦/{ RM$1;DLQTV%VV%TR\OMJHtF&CA?=;9*52J-$[{#EzQvҿĩȕ.ܳvi'!+02~8F95.'F_4ť*"l*VޑtM'<31=F5M!R`UVVkUT8QNL?IGiEECsAK?K=<]:N6f1+}"K0[cIA^) i$z.6: 8x4/'& NvϦȬ˜Su;cSn 7+6P@H{NRU{VVmTRPN?KIHFDBA@>*;D8S3G)Wpe.̧$Ų~X~JբޒkS ,k49<1;6-#ilv^}޻ԊGŸQ*bԹckm׍)!/A;lE:LRUWWVU SPMKJ7H]ECB@=b963-@%b8 ɹ޳&l;]>sez,!;-6;GsMRUVVUTQO@LJHFxD[BA5?=l;-8=3d,#Q. &۪Ϩƌp uij޲i48 UlE4;c(w29=[PFTk!.7"=9? Z$N19>s>;_4+sm8z3 |+oƸyy )6@H&NIRUTV,VTS9Q(NLsJnHG+ED C@=Y:7-3(+" ?Y׸ԵܱoP\#ƒNkٍF @.8>@>:22( a Jved ʲݴηtй5I!/;cELJQTVgVVTRPhNLFJkHnFECKA@=:72,V!($A͎֫]hmY%Z5ů W5 )4KQUW WrVZTRPMK%IPGED7BA+>;:J83w,$/Vta߰ }ھx(1t$$2#r.K9@EhEWA<:25%RO^$3;-{<˭Y + 8rCKQ(U2VWVQUROM:JHGbEDCwA@>I;97 1'݇RCo3Ю尞ieҦۤRV$3E=xDGE@=8-*bǛ 䰚ܮ<=ĸ>ٟX"0[3O%h bܱ4z~DzXԎC -2:UEDMSVXvXdVTRPOrLJOHpFEZCBlAq@?=I95'0(z js:l)ͱsgt'#*% 6?AH+JJME";/ zܤ`qXį7 Sخ5𵀻IŽ(7|#2_?3I&PpUXYXW7TQlNL7JHFE]CB@ >P;86Y2.+!6 89ņ70˳9;WzO#*9.AWFJH}A7+x ٞ zhP2OɷQy A'6?AKRfW^YpYfXGVYSPNKbHFDChA?~=H; 9*7 3/*!aX)Lu̾|E:(TlĂ0%1C<DNJJD=4'H@5L|Wά0% , B-:oENETIWY3Y:WUR`OLCI4FECoA@_?m>EIjHCw;1#sƘ ﯜJ'W;[ !1>8HPUXzYYWTQO+L6IFEjCA?><976[3x-$ ;҉yl\߰IJJ ɨ1/)7OAIK}HC:. OW͹p 5`7r'4>Hm'6JBEKeRhW+Y5Y+XUROLHI`FDBAt@%><{: 7530*!k R tдẾM~BJW%1aL6](8`AG'I,GA>7X+c PYʝA䯹嫬anȕ-.w,78CKQUWWV)SPMKJFDAB>@?J>= ;_9+641 .)!3(I*w2lΌq6b.g;DHIE> 3\&[k]loB_Y#Xfhu /;EMSW.WWUROLQINFyCA@r??=<:8752/.)Q g%s Mc1]尢ŷ.ћ%h1 1s>+EhIrIE'=P2%'W'ݽ8\氤i[ ԻÞWr w$2?_I OUHXXWBUKROQKIOG DB@?>Z<;w98I6 2,%X4 cᴥ/(ƾ?IJӘz=S;:z8O6^4^0*#i rn\wญDj>#H4@9E?G$FzA8]+* wh׺Z۹1) ʫY; Ǵ7ޕ ?)5AKRWZZKXVS-OL0HFbCA>=<;j9752.(!m ٬h7dv/2Lz@_+78AFGE,>4c(~;U׿޸«ԫ"ɠ |,Z9BD;M SXSZwZxXVGS$OKHVEVB@>6=;:6863/+x%jlj-̑óWв. ƷiuMnҼSmA,i9@uDEC^;0L#BZ>M UٶR E!/>;F N&T/XYYlWVT[QGMJHFDA?=BA>7- (H@پpc9خ\Ɩлp#0> !*N6W= ??<4|) 7;ܯվuװ h'q?6(%1=0FNSSW"XXVT(PM_IFDA|?`=;9642{/+y%y`zO۸ߵLµ7ijlV(4]:W=>p:M1s&S .VSz߯655|Խ '3g=FNASWXXpVSPyMIFDA?/<:86~30&,)$fb5LKA&R1L0"ۮ[)b'2,7; ;7/%* ̽mnJ۰k̷ d֎V D(U3=FCM"RVWWV\SPMJ|G+D4A?v<:@8`6{30-s("py%ѝ e;Դ]#Lپ[!D͵8cw)C3N8:95~-"ۓ4|Ѵ-.Ž,͹LZ)4>GSMRV&WWVDSQMJGPDOA?[<97p41W-*Z%~6~ܷKǺdUI!Зp} ,E366c3H,!aہVPXӱ&zϘf)04;=ELQmTVVUeS]PM]JFvB?<97 53U1-*% mp͘8޸ڹۻŠ(vh\9`$-00.)!H *AӔ3o&дU!5/(m3DJONSPRR\Q`OMOJHDA>ҖĊݼպ`оBg+Vͱ7D^3 LUpf&~\ʍe̽B6Mr2'1U9@FHJMOPPcOXM|K HMEtB@#=:8v6:4M20B,(#@= |^Kgǔ-znZ߿ž3]ؓSa:Z!P մ΍|uMMVyo5%.7">?D)ILO1PfPONKIXFC@>\;9S6431.-)U$@S)؊kPx2 UɡvОԇٙ9 wXf* y5ra·m=#ƚ˨F !+84;BrGKNP?PONK~HFCoA><:86`31 .g*&* whRsH˥%ͻ/C2Ys˰ZӅPE9N- lDGi?qޖևʳHß³sJ˂kma ((159B?EJMSNOOWNKIZFD`A?^=:8\6 423/, '#+6غǞhQc˟ϫؼ;U=EB $VD)Tb^ċʩ/݄E$-5 !<):9b776Y30+'"` {A@l޺%PCxͷъ^5 1! Q ;+4̕ʫ-ʛ*Rӓغb l6(408=>CHJLfLLmKI FD A?9=I;:t8g65~42/a*%|}h-λ,վB,nRə)ڿbU?iD %> ;cӧϞ˹;x؟fNX%U-5o;@DGJ+K9KXJIaG}EUB@i=;9r76w543/0.J*%1v  L;. н]RPĖ!Eѧ՜ޖ{}p AU z~kڰ҉ϑMzhM '/:6;?CFHIIHGDE:B@?[=;:U97[6542O.)#(Vo]΋eɽ"Ѹ%qOn΁Ҫ8wtngg 6K3te8̜/̴Ι+۶Zl$!*2V8>DEH3JLpML\JH(EyB?=):9J8u77D6?42/+y%x \~rˌԿ_^ŸHMq#N w 6 <, Շ{Ѯ! =!\)1~87=BFEHJ'JJIGEC8A><:9+8u77 642/y*$R =|ҕ@ [|oE|ǶSfh 6D7v_|֭gJ0Ӄ֧p5 :(0F6I=< ;2:; ;;85W0+B#l E$asxT߳T@)/i>(v /+Oԛ/޵R&N/:7@=CHKMNRMLJH EC@>=F<:98641,&  z&͂Ƣźź"qy?̖|Ժ6p8/4 1\ Hf[VLP&ԂIxW8; $t%--4$:/>BERGGGG'ECAT?(<:9l8888875v1-J'!4?7Z(LÆVּ;4pO'B9EFGGFDBr@G>>=Z<<<==<;\96o0(#1m:dOCKzݺvGۜ'rU\ }D!HGJLLL^JI FDB@>=<;:98Z51,L%A& ]ж[!sk: C֏gu ; ,)d ~7۠բԴԩՈךC g?'/S6);@RCFGoGGFE"C)A?$=q<4;;;;;:86!2\-%:y9؆ZɧڿBWйL30D¾Ō(ԜjrQ (0 a{irۆVӶaoٺ@I7 ('/6u;72U*Z :I֒˾(s# W˜FB ٪[  }  @HC-ڋ=_zf˭̕ѾU&!n$2-v5=BCH&K?LMVLJHFnCA@@?O>>=y;97X30-@& ]ugaյclXq}KqvSa % ?IeJՃ4aI%.~6==<;:9Q7Y47/)"LNq>=񻪹1LǼ߿iF΃n߫#jC yZ&xZ jNdXX>ע3e 1'/D5;u?BEfFGsGGFFECBMA;@@f?s? >=2| 3 Pn:DJ W̥̿o0ՒڜYg 4!+]3;0AdFJMN|NN-LJHFDBA?><;963%.H(4 _ o{ʐæ^Ƹ"OE ƚ ҤײdMt@~g T=Ar׮PgЯy6^ n"'/6\< @DGsI%IJ;IHsFnDC6BAAAA@Z?=:h62+"!y OH.̽ѷ%5|n[Ɨߵ  W +""L> tS%ږВP+ @b!8j  *3;BFJM!NkNNML`J0HFODB@?">(==:b5/F'W)<(ݱ簼幇0Gm lr<ji"U#J"7G u@ ̪b6^-Җ׶ޅ7t H<",5z=*CI]M0OPPOMKNHFDBA @)><:740+D$ 7 c ŭnUI༯}W˽Ѐ'ok\ b`3 yb<0a̶|<ς)Rަyx c!*2:@DHGJL LLJKFIH$FDCDA@g?>=;962-&TjjPt E - %go$0Mjyd[!&(&"< =f)ԂϤ *ƽr͖׌;l<V $[-6U>DIxLNOON:LKI;FE-CBM@??T><94.L& ` r?LkŭA˹ůxד$u ")v-.C+'%UD?9!ɨ ö(9Ԋ)qb D&1:QAHLOQQQQOMKFHG"ECBaA1?=:7q40*#%5n6ʉ"c{𰛰ٵ0x‡Ʋ9imw+ 6g$)c)'o"w &sβ/1LKiŒMM`LQ'719n@FJMO^OOrN7LUJ|HG%EdCBA$?H=?; 8n51s*#BNvB[@w-Zg$bُt-{"())(;$A f0tVљ= ĒİʍSGn%-5FLQSU2UTRPNMK*IcGECA?!,7 ?FLPSUTSR{PO>MKIjGeEWC@>;94.&;y5dv=qqd1WҒ{?Y#.3y56R3+! u6c/- 4T6 "-}7-?GKMLQTVyVU{SQOM&JH-ECiA?>};7E2-%nAܲ{кYWs< ,*27J8722%)POݥ˘l ¹'>ţ.OksZ S:$0g:CKZQHUW WuVTRPJMK~IqGEDB@S Vo[߅'Z't)/4K>JFMRVW"VUT\RYOMKJHEF}DB#>;]83-&w,"շ$"d8@ҳ+ʼ\MʓD z*&7058r73,'"y p&8?j~mLJYjX"-8B6IOTaWqXWVTRP6MKIFDB@ <950)!j HN=+s #`)=zȈ Ve u*27(87k1)X^,ݶ*ʈJ^,sm} 4ra >&O2i KzkϺָIN$0V59:70H&|hВËԶڵ*O;'3>GNSWyYqYXVTRSP MzJHFC@=:C72+M# -@i Qc| ańc< ~)39;n9y4S,#tԿN? YM*!D-9+CK$QiVXYY@XVSQqO_M9KIFhC9?sGeNvSWYZ6YvXV0SQO]LJkH$EBd>:6v1/*# E`yշJﳦ35EA߱)} G\,74`::=B;6(.%C kWCyVl]фt/0+ 87CKRWZ[0ZY_W]TR?P NLIGD@=95i/( cKoЯǬzҴQj"Զ0(ōҶ#|B#00W7<>p:N2' R?̀5&Ieֻ^e!;*/6AJQVY[x[uZWUSQ3NLCIFB?vnPKs>"/h:tDRLS WgZ [ZXVTR OZLJG5DQA{>:6s2,%ٴ Ǫ#˷W<Ḩ(Rx"3(39!<=92=(^L=Y1Β*ʸ4Ƕϼz]{E (a5<@IQ=VY[^[YWURPoNKI7FD=@=94W.#'e ! # fW_wIеd+f{ÔΗpn k,y6=8/4$UeޏӶǾFŴwaGg.+"..:/D/LS+WZ`[EZYWTRO7LJgHbEB?;7i2F,&6   |Fʔ@Xഏ+iaY2C %29;= >4|`촱ƴR:NץT x'44?IuPUY{[AZYbWUSLPN GOvTX?ZZ(Y WYTROLJFGEBX?;85/)#xN1l<mrsQ9X/ؚXvd.71;84q.)U#d]̹H}ɻ!Y0l"1M:>8>v;4( uB$(#ò+2Ÿʚ"#/;`EPMRVYY6XV1SPN KI]G@EoClAZ>;61-,'P /<GU"ޘpƟ¼"ش/W'Kx4+ N_(5i<@?:2&g leݜɂ异{hʹ˷Ոy] 6&3>GNESqVXXvW1@?:1%- ۅzƬ)[dϵFyPپJ,(7B#JQ"UcWXXWW.UR>OGLJGbDBy@)=:840+Y%6n? Kb  鸵޲p߲#ุq¤Cd֖m 0:a?R@>T8L.+!nKהsƴ4s7/#0<EM-RVXfXXWTQNL@IGDB@`=B963)/)#T؇ż緀0g/ͷ|ћ@W&|3;@O@<5%*i n B8\Í H(S5?HO1TBWYXWURPMkJHxFzDQA?$<85B0,i'e ]pܳ3Ƿ֦~%2:=S=80%z gr9yں!qƵ}hƩ\ٔ^n,8tBIOSVVVUT'RO|LJGWEB@1<963q.)$_O ,߼` ŵv賕$·5'%29=7<7m/I#z1( ܳ0ұγfBxȣјl] -9 BJP;86/2/"*%!k YXQ WQ)SZ#6.}ɯ2 *5u:<8:5G+ Gܰ5X6|a%^$1i<8ELQTWWW UsSWPMKLHFrCA`>;85p2+-'!F^ @1ɏݷ$ oC˼/ \C k-{6":s<~:4>*1? kׁ̑é!رvldÛՏVG &3>+GNOSVXWWVTROMqJHHECA>;74Z0e+' !7S'>ڜ`iܶݴbu_V3"Ƙ̩Ԋ ,*~389V6o0(_rzzĘ*50ùiuذfR (23=FZMQUVW V3TRP{MKHFECAB>J;$74l0o+&"1otY{l<bϳٷ=Ȋym;nfs'06(75/B&D 5֮aB^όx_*#5e>FLQTTUOUTS-QONLJGEB>;8Y4a/*$ i',Nӳ1Iv;o$B-3V4Z2-%H FחphcЈ,)4>QFL.PSUDUUSQOMKIRFD~A>a:7E30+$ v6k9ݿkԲ[5Z[ʓѵ> @#E*.0q/D*" gLDOŹ|oӹ<#)04=E)KORTGTvSRPNLsIGECA&>S;}8c4M/I)#) ZT vѕ^\d\~ͳm;ʻbFƂHӬY |\%m+.E-(! |@Lώ5q<4 i ^ދ]'2 ;BHM@PoRqSySnR4PKNEL@JdH{F}D,A?<8K4/+<%K Fpԭ [ôX < %$))&x 3^cÄkEKƿO#C ul9'1:ZAGbLOoQ{RBR QCOMKIGEaB@U>;R730+& A]&ΛH.{bęџؕc&=P!&O'V%!fr9+Eߺ̆ހX&D0C8?F!KNPQQQO|MdK6HFDB@f>(;851,(L"^ lu ٗ}ȝ'︙tӴö.^ȾՏ\ z""`3Yoj_p8aǨ . #-60=CHLOLPPPNLJHwF'CA?> ;9o63/P*Q$ P\hsa߷eym׸ޣB!^ [w_ <ޟՁͪS²?]Ã(f$j < *`38:AqFJvM7NOOGNOLKIFDC2AZ?c=S:841<,'!5,8إ\xLvqɹAEۈh/" 2O2 N>G_Uh7 JA'1o&L/K6=eC$GJMNcNNLKiIGEgCDAOԲG6Xַb 4,LXdW lH Jbe}y'UmhľYxWJ: I`"+3:@EHKJLMLKmJ H[FXD@B?=<9752/'*%  v̞YLݺTּT>ȩB/՛ۖab] jJQ?׳U<:86J31.-)$w1[ǸrZ#՜ /hp| + o?ߚayϨ gwRG + })18=BJEH7IJgJ<:86441/h,'"| }PʙJfFAʽsҐ׸& dX  dXA! c^s;[шHޔ"O"*\1'7OHJGFJDB@?=);z9806D411.+&"A)z9ϗtC_ei<:87 420.Q+a'#&s/ƇRͼvO0|ű΁Ӟ5,L'~P}ߙۅ؉֟+dy *e#*05:o> @BCDDD%CTB#@>=+;s98^653"13.,(^$ Sߚ07ƃâLO?Wbwan ?/f[ۍݪt, T"{(.37;=?v@A&A4@@?C>8<;M98>654E3101.+$'c" )H ^Kƀx¾ܿ;æijv w?HY3 m"F $ )t. 15C79;A<- C"&*Q-p/134^4444C33p22s2 111Z00..,*&"WAp 8aGބzևҿ:0PbwćƏɕD,4ف(w/m #? &<&`J640FM< eR "%'()*+,y-F../x04000d/.\,s)&"y ܓG&όͷ̳^̴/3ۅ-]_.Sa_Q\mA ?bq_ jb!&#>%j'S(**+.+++A*(P%"=n -/)%s-L dC~jx _ ]U  "#$##! Tj+5+ 0 /i{lj9*{,_;a=z6.+WOCG[s+/vY? e X(..4d +   ) 7 IK> $9>;pM.7E()p0% m:(;&  C+l  bLZiJ_> 3 yYYf,k pQ@qo2@CQ1"7r(*AwDS"s9R4U ( tCf=s`kB  %q|ihYt0pMabY;G%l5J.B~;P@ > ` ` Xy_@9IB3 w L e Qx*R  , 3  ( F LR-\i`zM|_+]Ka.l57>X0%LN6?7,)u ' K [ T . T " ; `^lc^Ln x H  `xX \JnZx``CQTA y<4cV6Kq; m{@"RrL o !%! 5. p W :#JxRpUq3@W~pj] :]7dpm k Q2/G8#cE@3qiv? ` # [ )>Z 3Jߤfi߁O- (c?a%+t98*`\A . d ! F m D  +ZEHgw3}}af~% Q[ ]M C޺'ݑ9k; 4LV#4}uF)ul;T ) 5nK! w!"#%&&''(('''&&%$#"D h36 Lm[!߾ݨMחXӮҏѮѠF.)4U'Ge?]&E ; "x#%%&&'''(a())**t***\))@(b'5%$y" b 4 n>v _W*ڰ؂bTNЇ ͮ]>fɻA+ɉ;ˍ͡?*w$ F?V!U$3')+-/1#23456^67747655 32g0.,*(&%# y ! P\D֝҅|ǗHcL!Ŀ6cQǴ.ӝSP/jC I]OfaP 1i $t(G+/2478:/;0;<<<;;q; :998*7&543&1/-c*']# )P ' Z9 UޠW̥^^½߸oܴǵSQ\7Τف r=8\*O" [V"'*.03579.:":::::N99u98~77"6F5]4820.,)&# f& > cm'#П̜Ŀw Q^̽yĊk̍q1l%O1M]cq 9 k 48P#'+/?2!4u6M789J9999p9 8~77=654321;/.s,*(&c#!^ |jau߮ڭ ѩyɟ·ú+OF> zŹLt8j}]*dZN"*-N; m)!%])`,0&2579;> ====?<?@AADA0A @@@,?>=|<:8642(/1,(%"f??> ':Q+Oyζ%κ(YZ20dZ D)ʨX3mDgF2) Y>t T $(,/25k79;><=>'>>>>>>>>/=q<{;]: 8u642/=,9)%"^i [ Nf qjP77%RļDQaY[;Fsf5?<, *"&+$/2c5?79;4e>??3?=?!>>G=x<;U9753{0."+L(h%x" ]?kO .  ,Fذ#h*Qps! ƅ ZHmU8,!.nLASWj/ GD e$) ,03579;<1==>?R?@a@@@@z?? =?q?@`@@@@@@@{??A>Q=0;:m864}1.+(%T!y~I uM߉oՑVӳ&J WN\̍_D(\|[cRm#<m 57 p!Z"&*.2z58H:2;<=B==>*>|>?)?l??@@?>=<:86c30-*'$!sP=&% !jvJR')Ÿj}Zcc6(0*@=]):TwY~v-VwnAnZc c#(,04x799Q:<<=)=>>v>?o@@A8AoAdA @?>T<:8e52/,)&# < jI YwM6ɹٶ8Q z\έð7XB4ZM"y?W@@AtB$BzBBdB A@?F=g; 8k53%0+-*'$ DRN{ل?@pA'ABDDtDECBA@R>M<-:7{41.+V(($!Moh Z$vP ¢!Y(ȭв?L!gѣz<J&B>j}M <S"~'e+/2p468W9(9:;A<<>!?q@ARAB_BBB/A@?l=^:8552e/- *u'$9 KE - }ÒzTˬ1I -|<:5753_0e-3)&# L?ۣ~͜ĊԹ&d8M!V.-ʩcB[y ~ # S@hrT%\v7_d H# 'k+K.153#456[678a9d:?@ABdBBB4A@?"<:P7420/E,w)&#r)5 O'&صŧJziլK\ 837Ê؇m,]7 R;p.RY!$bݻݎ>~( !G&R*.024C45i56967k8o9;=?A*BaCGCCCJBA@V>=1;R9X7E42+.)$iu  V|4VH0;ѭҬUu̶lGFu[ o YqQD5ݍ&wu ,0 $(,e/1 2345d6M7A89;@(AFB_CPCD_DDVCwA?<:67O4T1i.x+*'<" D^ߓVHʆŵ~=Bӭ$|rȻa qO|A M : C @ Ff_7Atވ#ܬ@/NP !6:!&),/r1o234556_7q8:Z;=S?@ABCCCCFBsAL?=;p86 2.+&" u}2'Ԇ`ʤNaϲİ)'Ƭ#8wٺTp  7 O@Z;X 2Hcc܆ lS0 Vb [$(+.0/012383457*8:J<-=?@ABVBCCBB@?O=T;2852/,'! |wgM1ɹ0ɱүUd&׬\}i:޾79L{ D RUATPJdG #''4*t,./01G2235968W9;=?ABCD+DDDDCCwBAo?<84/+1&8   4.ۜՈϞlϼȳ7:k۾ζeo @ \wuA݉۴ۙݒdT! "&),-.p/P0B11235I68:?

    @BDjEFMF^EEKDOCA@=:62i-y("Sto umߪ٦2}CֵBqԬޮTο8Xv AgT )Q3\,tٱڴ3xwDkG"&`(*,,-T-r-.b/\0257{9;=@BDFGaGGGKFEqDBC?<;8 3.)$/"jMVȒ/!ʵDϬMmb!džϷ O  m H Z`CnRXd8#zXb*& .!$'()F)**+-.u0S2i469@BDF@GHIIHGEC@=95=0,'&/;$,+ٿ޼!4f5h;ַύ7 kFR /'G7߅,;q܌. "$&'(9()*+v,.d0369QABCEqGHRIVJ;K#K|JHF]CR?;61y,G'!"ǹå漣\Ѳư)ݬ笞 }w`?ϖLuS x{ 7, ف݀OG%5 A] "#$D$$$%7&S')+E.=159^Gob & *,/:I/a =xT8 KxgG^tRXmv  ^!!!!!!"c#%(,048<-?BEH IKLLMLKJH!EC?O:5@0*%#<% gzGԢώ8º9 ֮?簸e?|cؑf}g up tk\ݾک1آ H3~k; sIz}N @!"%).C37d;?B EILNPQPOMKIFB?.:Z3,$"j/Sʸem _ỤߐT #"  O$l8kښ%}7rot ym=}`c"&+m/380  * v0.޼d7۽ iBgx $&vZ!3=l"n&+1C6;?CG J LpNrPR1R1PO7&.&$ܺLgQ˿žJS4.È̾ev e KXN|5k l2 j 4U il &L+1@6:,> BG*KNPRxSBRQOLMJ>FeA?; 4T,h" N{/W4׹3и*TҐ } > qrTY ܚ`ޒxe{ 1 R R p m +m ]$!(w.>3`8=AEILNOPQ_RQPNJE?M80C'Roka}؛#'Ī? FչD$͡tsCIx G)NW u dACWDsv`m"&  l 'Vma .$v*0[5e:=? CG^JNdPQR#RS?R#OLoHC<4,G"a QB;ұAڿJ}tѻ羀\mʔA۬e8 cE> V Qk.|>^ީTܗgw]:  J gf} [ I&,28?=AEI\L$NvPRSSBRQDNKF@Y80s'#J8dFXľ\ݽڻغeͼ#'8ܑ] {Z r $NJp6a^]Qe>)q ' s ;G l,#)/5w:i>BFI%LNQ%SSSS QmNHB dLq_wް`bm`|giJQG8q {$&,2s7D}s@޺ ygB0³Ƨ f XjO uOb$ ދ,wJqpR~'G#g}EG;L8cI!p(E.5:R>BFhI~LXNQRjSRPN&K_GA:a2*wZ].Hz>ὝgӸ#} ɫ͘j،_R ?Q@xu z|Ngo3Hj{_,H=Uj,war")/~5;?gCPG.JM%OFQGRRRPDMJ.E@A91~'p-#C빤!"ۻt@fe=ʂ4jL9 n%vߚXߪLRT8In+2D65 g +Q#}* 0z6';3?CFILQNP9QCQbPtOMJF9@N90&ZU*rK~Upo=Q{RЊֲݘ0| e5]P b%\8g;߶ަwzsf)lA&eZ Zd2g5 y$5*n063;?wCGJLNPsQ%QP1O MtJF@9$1'D( ܵ!rFʹa}æ ߡt #E a6޿ݕF H0>~n9@ z>y ,#)/5;9@DG[JLOQRDRR6PiM-I0D>7.$on k*%ҵ3dzKDd4,Ԛm}X(cm K`BݔTutjSLq}?N; /$*06A;H?CWFJ&LNPNQbRQiO]LHC=6-#! 0=z81kҴlp޺hD֐ -{E9( \0tJnO$ݟށ' k"$<~o -$a*t05a:<>C FILmNVOQ(QPNKH+C>6-\"vl TM(&88zӺ=7}L]* 2G ~Akݒ|9߹a(&o-WrKCD^ p]Mi#*p0P5:o>BFHIgLTNPPQP6N5K^GB<5/,! SʳĎ8hڽдOL\*ze Ji#߼Wݥݢz'qa=cm*%:p Ys$*S06;?CoFILNcOPbPOMkJ#FC =6s-# H,Uٽ̾i43ʽHS8ד8X6-@"I Z tTZC<еHŸ. ̑Ҧ0 F;/u i.3>+Iݒ+WZ>DbMXb& , 14$z*05C9=AEHKMOMP'P@OgMKID4=6-# S ̽bvĵF縈(¦ ]OMO{' 7y7߄ݔ8܇ߝ#P>s:W0+  ")J/=49n=AE1H2JLNWOOONML'I)E&?80W% b6$l3n(QܾOPczPPd F r5`Lۥ1ތBcO/0$g+pu "(F.#39=AEIKNO}PDPNLJ'GWCv>81/(] 7/qm[rciξ1y|_~  ^,9W޼~%ܓޱ"oS }.Z  &-28F=!AEVHCJLN NNNZMdK_HD?:819(K/Om޹7Ejɺņʌ^n  l }R[ޑܑۅAۧSO<k2Aq9@ %M+u1p70X3_XjTS^_6o0'?Z fNKs~#}Y,:eL-) T$*16_;?BEHJL0M%MNM>KBHsD@K:t3+" )ޢ}q򶠵x߷ w^f+)lIC ':euۚn݆߱}BXEwK B-S $"(.48=OAPDGIKLzLLvKJHcD@<81?'5}הqI>\ֵLs*ϘՎ۪'T 84QmQRr^ޭ۵dۿA`4$j\[tharJ !'d-Q38><@jCFI@JL=LLL:K8S1k)edzsDBuQMNًZ:)Jz -; ,hI {aE"*۱]ܼ}i#q`X'9 Pl   8&&+156;q?tBEHIK@KKK2JIKGeD@;5o-("5 b$^]س- VUdѪN.r{Y!O!z _D$ vDkb\P.  &]_( v}#)i/4r9M=A DFHJKKLGL$K5IFB=8k1k(<Bsi׶DǗ̵ gųE E6*`m6 Z!""!9 %]Aځڴ۶ݘ1qe}0G8 0Y :~8 &,;16;3?HBESGIJKL9LFKJHEA::3+$ nȵԲ̲FϽtW֖j:V[ "$%# { _ޭPځه٪ڦY* F   }n+X) zen$i*N/5'9=AD/FHJJKL+LGKSIGhC>7/{%- h-!Yֳ[Xiɠ *8g{ [hU!{$Q$#![S!5 ڷLkr m j /5P)MyG Q!'-/27< ?CEH(IKWLJLLKIGEI@91(lgSL!лzK>azǷtuͻ+d`i;$B%j$S"Nex >,{Eں إC^--L  " n"U8/ }u b&V,1?5:6>B#DGIJKKKKsJ8HEAe;4M+ NOEJ&PJ ̻ҐߨlF'_ #!"!@4 ),e{~ޔ %on + FmY ?7 $9)/49=PABDFHJFK+KyKBJIGwDA=6.% MS-+#hF˳ ż3,ޖ]!"]!{Ig$G٧hJ\b> g ~ y @-CY: "(./3H7< ?BEhGtIJ-JKLWKJGJC>80'qr+fT?Xѵ߳s!ضѾ /uabC wl!#n"!C dN`ۼ[&*ںߐ:A  t !_j s&+1Q6N:>B8EG_IJVJKJJHGEA;4,C!ڷ.L&-_ͱy׼Pؘ.> n!"h!Nv s@lۥ+H[E Ht" @#)/74F8<@EC9EG[HIJIJYJEIH=EYAT<6/&{SݍĀIcೈ0zӴԷ~4=3XYw O!K"#?!R6 o;?|u"lt?bڱcA^OW j * C d|2 5 |_!)&,W16=:>BDFHCIRIJCJyJIGD@#:y3* e_궰߱->(6 ̶f؎spou H!##"& !>FDړْفڀW 7mK f  Sg ( MD$*0.48<|@BEUGvI`JK*K;KIJI\FB=^6X. $\ Sz_ȋN yŻI֮݀ju4"U"!!%~MfܼڴًْsJ< ~)&  > ='HFT @";(-27t;?iBEGHIJKLKkJ]HD?9/1''>-ݛH×q]u԰Ա2޼ǒ"`ڜ/Z'UP!"^! . kTp1فTL ; s'  ,ML%A|  W&6+05e9|=nA D>FHJLDMM L3JHE3@N:2m)/u`B6?Ҵ( ƱkMYRص6n iX !! tv hkڝوii=.7r(q u z qBO  Z$)/49=@CF#H5IKLM/NBMK*GB;4*!/x @ ~٩n%ֱYE8+)tAʚУ{ބ  "Y"! k<]PX(ۂeNoh>3+4 p 0  2 > _8txjfW n$H'#)?.{38B<@DAFI KLMMMwL/IFAc<7.[# Z8ҋ:/۴pe @t{tݪy"   pbF FI$Z6ܮSڋ.SLL@W{P@ L 0 m lL O\"(o.3L7<?CAEHIJKeLLDKJ$GfC?90'%1VHBʔs))ϱvݳ #!1ȱՍ5Mu]z! KE]ގܶۚ`~6(r '  " ` = _!&,a16<:?BEH`JKKLMLiJGD?:3* 2pn*V:^kzֲCAM+tӑڲQD pb!!` f l FFڻs;ܿM(B@). + Y ,6djHB_`M o$%*!/59=lADCFIJLLMpMLIF@B;=x6-#V= l"1І϶.?LZ9}7LY%R@ sB%d4 mD(5gۏ`c}m)qWq T f 6fC- ##)+.38U<@iCF#H)JKMkN)N,M;K#HC>v80&Cw=ݕɭ,:`1:5ϵ LķYk` /e_LG1 g9*> ۴f%AYe   Y 5yy; s!'M,2"7/;?CcFeIK LjMNMN3ML/ImE]?81D(]ܔҜU"۲k8fJÑȪqG܎y0n D,V0- 8rN2vA m }.)o5  \&,2V6:>BEGIKMOOwNLISEA@:?1( WLÇ&նv.  ͵R F53d.c+szq[:'I D VY F, $*05:o>BFBI&KWM NOOOFMJFA:_2`(Z߻|,ö| 91JAyZ +z[Y :Mjhܓݳ<^_|SZ Q 0X8} P%3+)0u5d:.>wB EkHvKMMO2PONLIFr@91(je^ߗ Ⱥ"{d{nI˺،g )obtV ["e%ܓqdp.>NMqY dID{- $*V/49>TBnEILNkPWQQP3M I8E?92D(Y,&|O\Xa‚TuG7 !^M\^uw yV߫ާaߦkV{w/rCp`w%mv C=W$+05r:M>BEHK9MNOP OXMJFAD:f1( q[%6޵պx'J崆Hs[WC߂T>X Tlhh j{Hܑ݉kc~{, 5[;/X _X]/_ ' z%+]05:e>BFuIL,N&OPXP$Oz .>F A&j,h17%;@CFIKMO-PONLIE?80&uhjX~Zp)'"@I̖p/n#Zw \7x lT\3ݽUx ]6L@yT~R{Z,Qfݪ4'VMkgp6t; s#)7.38\7E.0#zU T]ؽñc bϼfk "w eKRuU+d;< f'LTJ"fv* CBa$*/I4e9X> BMF ILO]PQxQPO-LIDz>.6,!K"π9ϻ9R𶎷ɺ**=ʚJGKg, ! WRnb+5Q=H:toa96F*2ZJ 2  9&&,16; ?)BF>HKMrOQRQOM2ID<3)fR2)߁Ͳ|DĶ2_ˌ Z([]; W 0+kFݙ i{ UvhN&QH !X',d1S5:??CGKMOPQ(QHPIN K!GB;N2(0$/eӧ_mʷBJw0*;Ǭ҅D" lO UޠnfZUILJln[3> -A5#(-27ByFIMuP{RKSRQPN7ICWBF8IBLNQ7QQQ4Q OJD>8/#U 7ʽ&׺ϸظ>60ʻUyJC/p% Y${WJ  Wh1ߞym7ޏlS~C5D ;V&%)*0i6Q;?CFILOuQRBQQCQ,O JC=5+}hнN񿸼UܸcUz=KaςB`$+q&tm+uyܘܹݔPx"8?{%X}e6A !'V,16;?CG5JgM7O PR?RQOLGA; 3),֫ aH̷{~h,Yذ87Pf8 lJ߮ [ݾެ3xy9sr3]za9 ##(.i3L7<,@DHgKNPRQQOMJF>@E8/%5N {J݆h0š̻׹̼Rm @2s<{Oz-ZJ +:0DޛMYf] xNHu];e( O$*/48=2AlE1HKNxP'PQ,QPMID|=5+! ˥2Ź븙պ}RʺհۋhDc  Zcݾ}ߡYGUt0ig! +" &~+05:>QBFJMQOQ7QQPXNLIqC<"4*|}~ˎu]|2ǎZz/75mt3 -6 1y[~`e\HbYk*|R fr! &,2!7bEnHKN8PPPPONKGA>:I1( SMآʐŐо缓ߺ )*Z GZs wnn-I_9jc$ ^ "(.[38g<@DH7JM0OPPONMK2F@:1((fV֕* Ď ٻ5޸ Yp:ɤJ7{݉03_$3PsI rOr:0w2]L< >'\!MI O_#)W.48=A EIIKN P?R RRjPN8KwF@8L/U$~J {h߄lΉ9Xs> ňɌ؆cEPty(e  d |Hk5>5 p[`IKD8]Z1a X!T#).49=AE|HLOQQQKP~OEMID>J7.|$3 6ef~b@ƯP(bG-Šɫsӊ {m5Eq: h]z&߾0ݑRW;5, 7ML@bAr CJc$)/ 4"8=AEI6L"N{PQGQPoNKHD~>G6@-#B #s/>@k,ҼNs8VzK>ƃBnKNL-W|"oV3 ^z&}~N- ݐ޻z{c iOv& l4N6 g,#).38=AEHJMHOBPPP:OvMcIC=6.N$Bxh2g aɫӢنlVF~|$js >RW7MEީ9am'g3MO~, D= @#S)/49=AEFH-JMNOPrPP9N JE7?97.$? YBk՘ºrI]|7X!ʖςߗV8 +ue`E߿#;HM2oU OZOVa y$h)/N4g9/=AESHvK8MOPvPZOLJqGC)=b6/*&5eAքΙ ṃS@TEDq,mބ.F_ 8{+ߏ݊Y&ܞoAFi^Q9 xVAC + $D)/*49>_BnEHKM N*NgNjN\M/JGDC?J80?&/564/^Ƚrݶ0\J`exe Yo {',ܹ'ܯ*SY;k!&0v= QP$/*/59=AE]H,JWL0MNhN-M:KJ$H]E)?8A0 &DC]ռߺ<練*lbӓٙ߸D^   h5/fZv/t'3H3$sH $*z0'5i:+>6ADxG?IuK.LMfMMLfJH>D?91) 8^ʫū=rbӶ wȝht$,a ~wY& :\?%۞۸ 3NUR ZbDd2x</ z h;"(.3R8V<@CFImKLMMLKWIuGC>9d2*D  @P7]͏a˽`5ǛЪQrFzIe{a q[63 `u|ޜIKX j{D|8}gUJ| | &+1$6A:?BEH[J KGKKK JlI%GDA';5-%  ֡UrĻOpط qmXͷ؄cXs):K AF+]SݺߦTbM< Q ? J nwE _% *c/59=AD@FHJL L{KJIGEA=70i'W{bewT$[4s:δCbǴ ֡jz7\*B #hQ(J9M@|zh"  ~ }`  "(=-27J;?BEH+J KuL82[*  wO-d8P}Qx#.۷I5ęɋlڧI ' 6 nQ:ٍہݣuNhm b -  Z''|f N !s&+05:G>XADGHJ8JJJ#I/HF,Uf'%br6 D!7!_lf ",ۧزRڪ}Q5e6d w n E * \]8 &x$N)/348y^ADF'GIaJLJJIGEnB=82+*L! EjWNoɳ$mz9o[¶ǂ ]\E  2$ %#  y[u?pׯ ܡ As 4: 7 I 8k%*B/O38%< ?CEHIKKbKIGDA{=9p3,$~a#Ū'TűnȳG,e~[":< I$v#$#!&B 9WNܳם1۴ K ) Q*k  \c& @"3',2 6:>B=A05 9C:34-$l#ɱdJ?9cv4>> ?Zt!|!0 XAXL4\܇߈?$ q s 1 g Y 7 ]^q d !2F %*E.37!:>@CEFGHH~GEB?:5/\'[  4"jӰ6 ʶ5ݳO۸JĘ8bݽ1! ? `F 8ط|$I*`br n =  Q Uy d #(-259 <,?ACEOFH`HHFeC@;61C*!W )'4Ƿ轤dƴ&jiASْ_  8KvqTޭFڙ٘GٙENz} / !  Uq U#i(,048];>ACEFGGG%EC@=Y83+#T"M7}4&,ķ6*f[uI] p V-V݄1٩+Hi< bJn w   ~ 8H . , );!&]*.26\9= ?ByDuEFG8FECAP=94/(f $)Ϊ'¹>HֵPJȩD8N6 ~+I N 2 4ޢSڧ܊ oo G p ? ^ 0 > V !7%)-15}8<&?9BDjFG%GGQFEgC%?  Z M h >  ^ RG$k(-U1f58;>A CDzEvFF`FE'CAt>U: 4P-%uV tU6ܵKݷX8ֿ;Imy%1w )15o[ +ވ\ږbau A z U  GlD"'H+037p:=C?ACEFFQFEkD0B@?`;6q0A( R G585X1^Ĵ{BoyXƩ&Lֲz$T K~* n` vܞیt,ݒiak < A  V  ] 2 df!f%).2.59!;>a@BDQEdFFiFDC @=u94B-K%5' ]5ݙ?JżhC=Ho6&! ǐҞD.d 1Sw Z* 5lk1"6ޔwEK  $ bp  8 Jp=|#(<,147:=v?ACvDFFF[EDSB?;M61*"o3X:;r¾{޲ow`AIլ۝M/d tA&s-ۯhߏ]Kun!s] r b 7 e#>'+/369D>AO=83,v$E8KѢRIR)D^&ݺʾZ­Ǟ=m `o` ,w)?^ܖT'G<|`|  q  ?"'+@BDHEG?HGFDA=9}4.'|C(Bb̬#۷!4u4!۝lZD \ xt]ޝރdG;XP  G x h 7 vt <<"&*/269;>@BD4EmFFgF^ED A>:5}/( o '}ز#āʹLi+]Fѣ/H^j t fJUj޳(}&  DF B2W6!j%*.15J8r;2=?ACE*FoG GFgDB?R;6=0*#[L$@Wi `P>]*嶠ČɦP٢\08& |[U |_,0Rz(z!X5W^] Kqb0@" zN#i',O048;=@_BD3EYF#FFFErCo@<8S3-% o=b3]۴% Զd @ w\9zH Q5`z8S > ln"&]*/3@7 :o=x@1ByDUEGGGFEC@<82,&mW3 9HUzz).4/x ջے&h ' 8- # <5y-__vmtK 0 1 y |F)@?N8w$;(-16+9@BCDDE E;DB?@ABBBBA1?=:62(,&B (c1+& )鼡ԽZȦ%9׮4~u] k f9e^> G"X, kR||$"%(X+M.&024689:;-::8B52.*&!mC Sܘ|yʊŞ@ïз٘@/c4|o-(!ym}:Ys "iNu >:ZB;M@. ) ; m > B Z 3 fxl*j m!"'"#$#+#+# ""!%(X/ \ 7Z|݋TXͻFp3ǘǡF5ʚ[`лӃ֖?ylv \  = U f`RBkD >C7]x!"#"!LvQ* B$4c=oE+ # sY: a#%'j(9(6'R%#e!!f0 r.yqA!;[' R;c @x ].v3 G;5B_jmeh x\pc0HQD w:SY13U s k P^ ("%K'(!(u(]''%#! IH߭۵lHLs:B5_EގqVo8 w ~FJDgG|z.P#E  R$ A}0N\4{,?u&1 $ : # ::A|#k&*,./0O0P// -,)&q"^ f'N&~x.ܛٙhz ֙k 1g>}լ0:޻;4PcUWc;im]r7E l LiE <gH6P(6 p X[7s1!s%s)-1o4868:b;A;q:9741D,F&/.Y@afBֵۨҼun*N-pņ{ŵ;rdƟoT˔`хC<` B i4}oA;< 9^-Suo  A{  ~Y  ` UO?]a^!%+(B*,-.///%-+($ Jpx3٥!хε[1G ư+L˷͚8ЁхOҮA5&`)5! , T B@ X0_Y !$F&B')`*c**)(&# mI cDr TK , " +3K!$'+-/0/.-,*&"cC:v+ض*&q΂,ХьnIҙ"}Зz}3է!  p E \c~jl@j oRW!#$%%%%#"3 E EZ=] qJ#)F.14689p:<;;;J9a6W2.(l! 2MP%A|̢:ZM^Սԭ]&'n$л&&2݃Lp  o Ry)e-ZK1/R   3@dA | Khw{M, i t3j2";%)7-J169<>@@`?p=;K8 3.)"( XԚHҪҦ * iרڒ՜ӌrϗ,;޴w5>V@zSfT5jT1 X @#M%'())('C$! lz+KoQY }w4> b#',17 ;?BE:FaFFDB?;60)^!8dt ׌ӐŖjʖ1̋͸3 ͎ˬ'%W ƒ¤dĦƑɎ00[du&uag8 f8!i$&>'))))e'%E!1 ay& q f7^j #&)-1y5e:?6CoEGsHGtEC ?<7-1!*!B,ׅo.^*Ǵi@;Hk:(6˹>[nͮuzց۹2qcEzI iwAACCC @=I94. ' \dӊ#͟ ˡ̶mR3Ϸϲ4ǥȸFm@*Q2Atbj `#Vr!$'x)+`,Q,,e+B)&"N 2Sv`.Rjw_jwn- u  ehCKt$2)).4:?B_DF`FF9DB>+9@3-\& aP` }Eϊ$/?v:Е,̰-Ȱ79;ɹht@2K^ iQ#%')W*z++ *X) &$ :f t:{IX~Q I^> GMV %3*/t5!:@/DLG_IJJIFC}>92j*")jE{߂X@IF XҡҿwѣLQEǪ2qcrAY?h&M+Y: 2YR1!$<&K'(((L&$!8mdEP0 W]A0Q v-} T$F(8,2J8'=]AEBHRJKK6IFC?:4-:%ET4)?eՠLA*_CE-v|heɟlǶ?nSn%$?kq  9!$=& '[(('B%# D/ G4bZ"hdm8 U =~P"%)C-28A=AAE&HJAKkKCIGDA AeD_FGGGcFE6B?<83- %]p rq\>-ԭ(Ҧ/q}4Κ̭ʩȿŁ&`aǻ{aӛwZ`~ 6 b  V@ ":${&p'((('&"#  u"X\_*9 ' EIx"u&*/491=sADFHcIIIHFDB> 83R-$%z],-@|ѓuW(MtAmB2ȒƹKPÔĄťq*͓mFNYK/%H M"U$@%&'?'Z&%A" , Jbym%*2H 3 g =$*/?4*8{<@nCFgH6IkIIHGeEC$?;7q1+Z#;urP) ы_pѪ-͝ =ȅ*|Ɩy6scD$ڷ\u!ac$4OhD [b!#%N&'7'v'd&%" hK: ߴfVA! jk#P(-26:>oARCvEGiHHH)GGzFC_?;6/(u _K \nL&ϦаѪѼZϦm6ǪƑ$ͰיS6M&=]F CB'yd"#$&R'((('2%,"Nr2[]Uk ݷޝV@RT OI1 %`).D27ADsFHJ93-h&NQiغoΐwҶҜj-QNjuűšɅ˭Ζۮb`F[r!N`V c^"%'()))G(.&# CI N -܍pۙbDC0r_ 6#(.l38އ`mgsg9 jE [i*9#%')6*D**('J$!~ v/A݁GQ@}t? 3"&,2J7;? BEHIJKKKXIGEAo=P82_+.# |RRt,հѮV^1Ϙϛϩ1O%y}r YaՙH LHA5BCF  5!L#&D(T)**G)(&$ Qn 1g?pߧ݊4ܟ_Zppa ;"(/.%3x8=#@uC^FH`J$K1K4JIHFC?J94-&Oo R59CУώ`<{ѴMHDdlǴBŽIǒQˎάҒhB(d`~ F `& Y#o%(#)+-++q*n(&'"5J zyFmکfd_l%YW $r%)+16;@?BXE GKIEJ}JK;KLJHEA<72+|#  pܛiѤЦ/о9Rhзzk˫ʢ^*hɟ Du\MeGV/X 8os "S% '&(*#**p)s(%&/#;ST3 FEV:_ݺ@ *2_B Gb!'-_28><@DmGJMKL'LKZJ&H:5/r( Z 8;ۏί́JВ6A͒cŗƘ͈R4 }xr= {Oz  Y"$&(p)**4)(&|#' JN \P%ڢھݽUSHk& ;w &H,v28;82j*"{% iUeyά7 α`Ϲ -:̙{h]Ɛ`9Ӽ"_TdM 2; .s!$'*/+----%+)5%!d 2q? o'#{ܯ[M0 4 X!\(-.n48<@9CjF@HJL{M/MNMKHbD@:4H-%}|hڢ >Ϧ|#/βυ`ЈˑI$(v2ǣȩͦ8AUt<_I2!2:xg G"'!U$'*R,e.&..-,}*b'"/ r+qj jط#הݭt  8~-%+0599> AdCFxI3KdLM{MMdLTK+IED?9e2+M""5'ٶPѝ&,ϥЩғ4ьb΁JƳɈz'4(#  &,2_7<@XCFI-K LMN>MLK?HD@;K4-%S7x؆\^D>}ЃF˯ȢaJʁDh?dބd(gADu !J%Q(+./1+221W/-J*%!2z !Jޮn֚ل)%M+#1%7/92*L!/ ^A|бi^Fх[Wm+V1cA\D2%[3iPv]F&5n ![$(+.023;33~2/,(#. 1< #<)/I4-8<@&CEGIKLMLwJHFDC@L:_3-$*$Y%,ӯ>r4ϵϷj?"ɧ@_[0ϟPq-%iz .u|$z[ b,#x')*N-02x3p4$4s31.+:& ' I|5ԑՔ׊ܡߗZ(xv !%"(/48R;?BzEFGIKM4MHLxK1IH$Em@:4/)'Pvgx#Jhִҿ$%΍JhvIF O] #S8 4v[]?{7?#'+{.1v345w5@4$2j0,(+"  %ՒּCf l$*16;@&CFbHJVKKkKNJJJLHFC@7:3," ;Ev؊cԡџ StϗϼͰ˔-6Ȅ;ȩ*xХZc 09\p)e| "&*.L13456'5d31.*~$.CއոUv7Gml{.I0$+1v6M:>ADG IKMtN*N^MLoJ[HEI@:4&," T{ڣֹG/ά]ΓgЗKшͫ[7Ʉ <է؊gJi=,~4y@ !&]*k-0g24x5b554|2.*% :n>ߐnӲ{Ջ>&h1Bvt #)/L49>^ADGIKLMN M{KIFC$?;6R.+$Z|9ZgϬlio,=c'ѩ}-oPc,{  47v _%J)-/245606 5P30- '! W-Ihԟ&C-,;e 49" ( -27;?ACFIOK9LNNLJI{GD@f;60('7 E|4 վҖfοv,Ѥ8ɫg3Erښ?BM \9"Efu ($)N,0*35 56!6C54+1!-?("O EՁ%`Yޝe=o '-2m7p;?"B DGUIJ:K KLwKJIkGrD&?H93,"cg3bD|QϹ̟~NѷIs )̑fENg5a GFJ\ .#(E,O/357j8,886?2.X)W#v` jـտSҹ7ӊBQ( Lz  N&-26:>AD GIKZLwM\NMLK6HD>82+!dL +ֲ^o͜m\ЀЊ2vx5p1]R#%KCvsJKKi O#(-03f579777 5k2/+#%>) S؊ԯV֨=UT{%+1 59<@BE4GKIKLM9MLKHD@H:41-/$ O9ϽΔΞ 1БдЁύL656Ϟي&WFOhW+T{ q+"'#+/25G67807631-b(C!][ ap-lHpԲSұh,ۏw~ %"(9.38y=@C%ENG,HJLHLMKJHFuD+B>92w* 2w>v3[#+(БzzP^*0ʳWрt#4pDNx rt8"&&+y/K25.6789 806[30&+ $@DU]<ܬؐMҦr5ם&"z/!'o-37;Q>BDFHKM"ML`KK.IH!EAP:3+":. M|1zЀ΂M8=Ѡ1Wϵ͕ǴLp uN$x/,Li!%* -14'6o89987[41,&e*EsT#ݪI?CЕvA"$Xw?  &S,2)6_:>ZADFHJKKKLLKmIFAo:4.[% ~s@2oGpT u2πzЦq̦Pʃ~Ѓbk;xk(vx $[)-1f4689X99a852.)5"f Pzݨ5սйϫ~Ҹ٣qbZTc%q,2U6z9=S@CEIKL2L%LcLAKJIGB<|70&-utgZ?p8&ˡ̎U7А $``7:T U ݾp3TAk8{ry3 O"(=- 14;68::;974}0l+$ %u\߉T% ϲBex{7 $*j0Y5:=q@DFHJL6LLOK}JIGFHDO@;T4T+>,Loа͓ˇ-Ÿ h ЛSϘwc_Ɉ~U\ۧTAT^wUy.u= K!'8+037&9:;;]:75+1,V%r9ھҾ27.ҚT J"(r. 3i8<@*C,EGIK*L_LLKK J:GD+?93(+!l$ &<٦ ?lɫ~ɋˬϚЛ%h'ΥADSAFձڜ)(bM/y#!&]mv ^ P&+)/3697:;m;:86<2.!("rf!BQmЋ"ϛҕױRuXpc%\ G'x-a28<@BEGI,JeKK^KL?LKKIE@;5.%7![فОɌɦʊ+μ|ѳѰϾ/˄ˤy ҮY߂p><[Ado'ZA %07 J w%*/3E69:;< ;9703/)"%+ lEfBxϛnҕ] p $+16;z?BE^GIK?LvB!DFH_JKwLL:KKK82+E!cqmށ7ӔL]60̠ͦВ/+5͖j̈́r jJDPwsfj |!u&+|0'479@:;::$8U5h1p,k%r0q-ڠ.һ ΖR#؇rgz\ !U(/,4u9(=A\D;F;HJKoKK=KEKJJaHFC@<70%u MKݛս3˥̜HДZ"!ѦQωTopWKԷor} lL C#\~xS $(- 04Y68y9:y:886 2-' PWӓ@9ʹΤѝ ׆xl;Jt%+16:z>B!DGIIK1KLKK$J$HFDmB9>^8U1p* !%g TҭβCeCez7͕1 |ܹ"3;I=1O-{> s2"1'+/25S748Y88862.)6"7 YBNaW}ΚΫϾ }0 '!(/>37;?BE3GsIKLLDKyJoHFE*C(??93D,$5݊׉^PҤc5`#͘8̾8Њ 4H+k$b /*9,@ )$_(h,a/2M4H56=66b5#2/+%ZegӑјvSQw؆܃y/O n%<+058<@CEHJJeKsKZJJIaHFDA|=71+x"R /!hU:Ϻj̪tO'Ӊ{сЋm`̴YΖӨ$A4EZv !]&*6-03`45b55n4;2/#+':! OHޒ<%f@ό  N&',?2G79;93-@&j 4;zorn͠ͿnϨАИpo`A̛͑̀̈=a֐>>MvC| "b]#(+.1m33484A32N0- ):$bjub'1й^QS7m&0#)/>37;}>ADFHIJJJIGFC8?<7B1+S$&bc;7-jΨU&АЙh1#0N̍ͷωќӆagKi8V9 l;7 %),W/ 12313=210.K+&! WLЈҌ3N t5%t+058<7@ CTEGmIJ JnJ'IXHbG.EWC2@m<60*U"J tէ  ;οkϹ3Κ-mF{ʓ ͷ6UR0Y8G} COL x=$''*-a/_012,10.,(]#h3 :'U[֮Cw:Y԰x{ iD^; ' &A+05u9=Aې-24JOKT~L0 O$'+'-01110n.,)%\  Voԭ-җ R2؛۞D"+q !d'<,16G:R=@CFHHIII{HGFlEkC@1~o"(-2z6:>LADbFvH$I8IrHGFZDDCAA<8d4;.'yWu o(n@BJ0d͕͓ͩͧtFuʩSAOCF GHIDI=HGFDB@L=8n2~,%H *}NRѧtΚΠ̷}ʹʹ͠ˀWɱ6(нFk2ugN"iwg  <#&)O+&,P--:,+')Y'#%$:(YܬAԦԨia,&# vF#).3u8<?YB4DFHTIuII|HKFEDEA>;V72n+$wf %ؽb#53M͂Ϳͤ:M-0ˊ̣ΆӠ)96@| * Qs!$'W)o*+,P, +)'%&"1@ =O\uu֤S Յ֖>vvV +g$ "(M-3D8.G%HjI,I\HGF-DC@>$::50k*$; 6;_IԦ7H0Dh͜f5n^ʙɉTS̠!Е hTLe?EF]&b ygn $&(*p+`++**(P%#5 6 Lz }ڸ`nއ2^" "\(].2377<?BeDFH{IRINHH(GEPB@:=L940*$D Aiӿѻbώnϛd_λ̀͡˔$ʨ@ϚMy3a87[ 9 !$&()))l('%$!!; %i]e"qwprl +""q'-27O;\?B;DFHI1IHGF DnB@=:61,$ *}؞@ϖΈnν"4ΙȧWMNN5i Lj&& =# m*"Y$&-''}''C&3$" vgq X.5ڮ]ئZdZ  v9#7(-o26:v=@CF;HRIJIHFDlA>;8\40O*#2 :Eܰ׿α>ία3L.ϩxqϷςΓUTKɪQS\Їh#ߌj:c[U~d4 u #%&X&&&$#!! eE pD ٍVQ&ZDx#(-2v6:=@CcEGHHHGFhDB?4/*&#Tw 11yOΛΙ΁΁eϝ϶;Y^vy2ǪȢ ̕s? R\4(l\+i  "$v%i%%%v$#g!>i xG߅9__!܇ހ \$).l3-7]:=@CXEG=HUHHGGFEDA>; 60)!0;g n܂֋Ғ|v͙4XVϦϽ͟5ʺ7ȇjрGWlIf*\Fg +"9!"d$%%%% $ "m K^+8ys!ܞ&6\Kc ##(.A37S;>>AD7FnHeIIIXH[FEB@ =[::60)!d ezs@Gύ$Е*(]ʸiȪ3ѸTvیGY_#΋m-( usƤLƚLJg*{-תo)y5D+a hP~@ !!"#W##"!K}^ ^'SI0eڇۈ?(dL]| Z"'-D2p7);?QBfDGHIJIHGkEoC@=j94/a)!)jwT7/sh(ϔϝ%ʺ:FƇ ]̞tө*~yAW701} t|S K!##### ! XdzQl a/ݩ kv$:o 0$[).385<:?BEDGWHIJJEIGEB?<84/)T!p#m8gEeNϑ΍Ν~<2ʐǩ^ʲFo]J9(N`ZM:yS Cc "~#]###"6 V9@[s~=ݒ[ܑۖ"^.= F LL$/(-2e7:>ADFHQIJIHJFDBk?<94/R(!{pۉ$Oϰ͖ͪ xrμTȀ9~%kub1?4ڮ $_bMb$  ](MP@!" "#y#k"!o asY.bX)u۬ܖ @>g(&Pp n$).26:>DADCFHIjIIHGiErC@q=r94.( *TOkϗϺkͧ,ǺɧzupSvQwwqY%T)!) > (5! "B#W###" 8 VhmߧFۜ ްlHot   $*/37;z>ADFGHHHKGoED;BAu>:5/_(Z?$aEܖqdCШЁΤc#ϓMʤq?K `Ǩ$Qڝ;yh\B7?Se 4 "'"#;#M"!Xq?XC!ܳ߸ LQ  X%~*{/|4 8;U>$@C?E:FGH{HHGJF.D]A>Z:5/)+!h+uٰՄH)ϔv̷Fȩ2138 <ѠN9w[Rap+%d5 G_ ""#I#o#" t B {+g(B8[ܘܗiwkH  &+/|37;=@C)E.FGH GGFEC{AB>F:X5*.(%!GkYg*+8΂n΁ΨόϲLL̿ V ņtO\ϖҮVݟ]vB$1 h #U!O"y#r##(!! {(=޳Qܯ*b :H!;&*/S3w7E:=u@BoD~FBGH:HX@BE4FH+HIVI,HHKFD@=582+-!1 YN5r̖y;&ͮ̕^'ƓKȘ = njO93]51 B#3!\#]$%&/%$#  wZv kF+(xv )#!(,M0n4{85;>sA>CFGHIIIGFzDBW?;5/)! D Ձk̷͉N<"ΝzeU_7ǥО܀a,3QR\ 9 a-z!$<%&''&$;!P yM.MߡQj"ځuS# m##(G-1M48R;@=@fBE>GBHHHHAGFEDQBC@f=.82* * [fذ|̣˥ʶʢ˷H6f-/ǻgǪɕˬ;$=sHJ$E]n@y`B v[Lf ="$&'(%'&\$"Zt Qp5:t|&*߻!d- #3]M$c(,1358;>A+CADFGHwHKGFEPDB@ <6D/(! 1,ڋWΖnʬw̕sDCA-ʧ͟a&~ 4KHmrC6` Gd l"%<' (;(('&f# f @sTbvڭ%nK'b (A$F)i."2C58;>d@B}DFoGHHHHHF$Cb@6cc"%&(*Z**)'$ 6 Gnzrفֲ%rڱgd% " 3%+/4 7s:b= ?XACEGHI>IJ7HFDAE<9L4.'M}` pj˳+/L̶I1ˀʡȸɷHԜv{+?awG5c@-'!!: "$~&(*+++)(%!]( }^ޣDקOu&٥ۻK2` BP|%J+)0q48V;]>NA"CfE)FGHIJIGGECpA>94.j&FsY!dLDȭɄ˘^ 2ȀZHȬͦ+{~l=aC|l KE&#!%'*&++++q*_($!s ݉Qլ(XXޟu#  %*/|37X;>ACEGHHGGG6FSE*D:A=k83*,W#;H`Zd̆`j˃M˥˩ɾ()Q#ӌؐ"e+9qo\ nGn$ y!$'})+,-.-=+\($ {F & B3؛XNԬԫխײeݕJCj\ &%+O0!5/994/d(S !aD؉DʵÆËg?C[GW"ʽ˼[Ѡzڰ7\#@IN0S/Q MBD",%(+{-/`00././+(u$1_  ]1ܥ 5sӖbdX'b) o#$ ).37:=@nBEFHIIfIGHGFFDlA>f9a3`,%` tuxw>jƥCɦ%C$,̛aˀZ͋/[j p'_9,p.- -#k'-*",/#0110/),G(L#8kS{Hbָe;Ө%@݇ -Dy!%&,05$8;>f@BDFWGHIIdHpFEC9@=9F4C-#*G -ѻ͟{:50W*! +]@Ϥ˓ IJļk)ʛr9̸J(˳ʤIT(,BaI~2y , [h#"&*=-o/13`4320-=("M +N6{҅ѧDӚ՜A`tv& #h*c/448];>B@IBEGHI8II:HGFDB@X<5.')_KŗÜJSÆ*u͘͜e˟k mՑ*t-D[e=f$nF ?4!7%G(,u/\13n45$4c20q,'! ifܖרJjvDC֎z7 Lt!2' ,158<?RAD"F*HeIJJJJHFC@=71*!d C x5ҙlǢūĮı̴̧̬bζ@Ѧ֪ٻhX;6P 6) u #(+/1345^5#31i.J*z%<<Vfڈ:3wон^t1lC* V#)-2`6:=@CF2GHIJJPI~H:FFC?;71'_vUqÎÁz3 %s͚͟ͰΗDcЭ7<]aCLx~oSF:$ z ?#O'+>.1+3456`541p-C'!l "ܝ: }о-E֓tb9 *(e%*/W3j7L;>ADGaIIJJKJ GE=B@= 8c4.%x o%A6*bÆcf.)r̯̩ b{βѝزuK/|/{s ;$T$P(-0]3c577|7@630n+%p<-:wjҏ+Ո׿ f18+ Z#)f-1P58HG[EC@iJB7f %)-0|256666 4S1C-' Ll F,<;s-8{8֗kQF d&,]148=@CGEHNJKLWLLJI;FC.?:4k-b&L*Ņ&KvɻʼʗXMϮОұԺ۱;Q[-c4MHn |=[y #'+/{2n4677t6l42s.)x#V \@ISϑ-Ѧhzo܅+1!\").4s818g."Z qܮձuKšŶ? ɹj"ΐϞЄѫcՖS|g6EUq"(^ #(-157:89J97752X.)$4 ޾bk|P2$ zClh%*069n9r1[(ڪ`4d_ǂ@Ⱦɿp͸: PPU'Սq۹~a6kY Fy@; 'pn~""&+/ 360879#9k875 1,' 8ܡI>ϛϓ-ѱ!. NM#)C.t307A:o=h@CFHKMrN N,ML"JG/D@3:3,($U I}.u6ǥ~ mʩJi/΃|Del(6$FW4"c$5[F #(,036 799864#0*$  OkeWSvϳЕ gY JS&,1Q5L9B&DGtIK@LWM;MMKIjFC@;5-.')nrk.ҁʉo#|2f͵Νω*ЪJхҹlZ YWj ߪ7ODD,h h &'+03j68D9:J:U985P1,'V d0}x!רHoRo΋(H=\t %+1159Q=5AEFHKLLLLLIyEBC?2;7>1*B hV 3ؚRȸ^ǹ(]ozN3ZtӚ ޖ;Cen <23 ?7$). 14689 99x8O6_3D.(", 9Cs#ڠSRλ%y@ړMF "x)0g59=8@,CFHtJKLLDLK4JMI>GEEB@;J5F.4%%OgF ,QJbsX͵ΡσЊ~ЕoBДсm -Oma5/Z qbX"R'c+/25799:29p740+${ #yؚ(̶͇̀μ9+Z'}V&-27;??B!EGJK?L LL^K}JcI FCI?6;R73,J#- =ъ˽~cT)οKαϖJto(7g"|n9=gH[ /l}$) -2K58D9:;M:862p-(!DK])ٷnλ?ҸDyeB g$*05:=@CF4HJJKLNLLL=JH]EA<65-# " Քu7ǂǩ'U 8ЀЭz=mT۱.M[3|~Rh'+BHO`"',l0368:_;:9750+q$ q`4ωΈ N)e/rHL0h l&t,3#7;?`CEGIILKLM M;LKJ?GD{A=h9#2*liWc3($ʤlbYˇoPnϼsHVI(n$ ҿwԊ)۶4|F!9'<BD O$)-147J91:=:X98d52^-' VttAϔT̕MUI#[9 T`#*j0<5#9/C8 0(; @7d ױѝ^vD{˥ϥЙђҋҼёBБЀ'ӽ?ރR;pEf'AbN N#(T,/25*6788j75v23-(!   Up5Єΐ͸Nd6ڤ>9MI$* /Z4q8< ?CWF0H@J8KLLLL9KJGUD?:4.&)Β=ȸdyɝ˓͇Ѐѿ҆ҨMϨΫΖpθ^ШA֗B,!?`b*U!%*-1 357z888d640e+%dE}ϼͮYQңـ -]!l'-2G6:>CA?D;GI)JKLzLL,K_K*JHeC>@82+" 9܆ѭ]^7ȻɖS'&0Ѥήtε#xѝP݆_cv/'!*O5( #(F,/25789E9@852@.7(! +^2ؚu͑Jdͧ:.ӔA٪/u9X%+/4V8Z;?BEGIK}LjLLL7KJ&H-D@4;J5-$.;![ e̞_\[,w+!F϶W#ybcCMN-l-A 0gfN!$)}-036\8n9x9Z8v63/;* $ |cCۆB̸͘!Όd҈_-ݦ4v3s m '-l256Y:>PA8CFHJIK KMKfKJIGFDA"=r8|1*# ]vy˽@ȎJʉ<ΛrҍG,wѫϵr<33L$yJ O"'O+/)147888752M-(%!uBiXَԣ,β20ԣ "mfe$a+H048950n*" & <Q65;L˩N,ІemQ̺ͧB̥w-ѭQ Ma$p1M (@"-&*-0 23554V30-):#ZYhX8ϛTѩVڿTDL# V! ',0`49EFuFFF5E>CBAW?=g94.u'J OtذԜ|wAӀӖKъq]L̢̇8ζ9|02B|F|-* 2!%c(+-/o01;120C.,)%b b& y&\ifګM՜֫4 u] %). 15f8`:=>@GAB*BfB ABAt?='9d4/),!g%|eIvЄDVFӯӼ гw̴ͣlQ&޸P$C38x15 $ Zm  b" $')++,;,,*('v$!4k h'w'3AdI F1?"'S*-l002+334`5?56^728x87c53/+'o"r RJa{h[WR4ۯ݆ܘ'kϘWϾѧ gBdRmk3e5W ' W" !##$Z$,#V!i  ij"mm8gq - t 5oCF ' I !=!!c!!!/ 9O r*.>`M2'&($PGDIx44L}Wu~a ?bN>( ~ J>Fz 5Z  &1 Z VH6R#x>X^nl=6)j~5VGt>OY_{ v 40A4sU5G  [dpߒ&hmaDW M /  tb " o=qTQi"sbGyE|u { |EU/#"=#%')()+a,-e. .#-+)/%"X_ !C;"Qxw̻ͮ]͚҂Ԭݗ2}x  i 0 ?  3 5RV ?>qLS/w|*;;Z;FH?fO ' W#&!$Q%&r&'(^'%#o!; vz~3 w~Kݺۙ٩K԰e֠R{ߨ%[c)dJ|C}]Z~NK^j]/gX g (  / 4 Z   )!Ke !  !!!R x (nk#p"!bex4vn: +   (pn" 6 7 Y ^  V i w @j ee!$5&()*g*)W(&'$!M sG#3݋MՍҦ4˔eˍ׼/p'%G RG$Wg [ 8@Su%[ [ mL$]PdjY< C oq"$S&)+-r.K.-+)'I$!<hU ]<>u і(˟7˺0Ru+ދu5sg>- 3 d!>P7i\ * O K \, ndPK^ 5/  M#M&()*&* ):(e'J%$""Cea9dHg]ьFʌLk*1ܵ'U$1p 4  =9Q+ znQWr >V ""# #`##z#@#1"! ="-PV g#پB{ʿ%"dzSGA " 3 v I26<+(O} u # l;>% c|xc" %)[,/y2V57K8:G<=>k>*=:61+&,ب.>źbBxFņ3t,+a ? !?6&y,b;+-L y Hw!  |4:, ! 30.H"% (*,}.L0&13|5J67/6~5B3r0,'"> gھԺ^y-WπӬx{T<S h ) k /wb )S!& *9.15;8{;,=7>?=?M HX]. s; i 0 9$(y,E0F379@kAAAK@>=<:Q60*)"BXV$[[>A<9о[wv '$"#"'l &IfHܔzb _ }u W  c V $B"3&)-U0r3j6U9G<>??ABBA'?>=:5L.'> ~k>pϨQԻ\׷?EO[4qΨԑg4GnX? Y` D *.{K7Jea}} ( 5;=\  }ru U!-%*i.~2=59;><@tBBCpDD=CaA?=;s72+"I/jѧ>JGݶŹFgƂ7А" GX?7_s6`݃~uJw#D N OC7 c TdzH Ds $)3-0k369.;b=1>?A;BC)BA>;8L3.!&1]6Շ Ƕcn ?.7/m 9܂!yRjSVN )6P@@߄ޮL0a3 } 7?r[ ) o BU3!%)-147:\<>@UBCDgDDB@]=9^510;)!!kО#pxAW0LӚrB5 w'y >mz8FެG_OPkeFp < | 0  Y Q "'Z+0#4+7;=@BC{DGEEEDB@~=95/ 'l V߯όhP[.ojYԕ9Nmg BEs P* ]@`, y  arG 7  G$)e-1,47:= ?FA#BCDE DCA>;Y7d2-3%Cb}''i'̸".L\kX< JtCi . de-}Bގ ߌJn (c: >  O\+"6&+8/m3N69@\ABC\CCBA?=:6U0)Y! r]˶ ;c\ı9Y)'?RM =U AD~.6O S4- ?2x;O3 p !G%*. 148:=Z?AC(D/DDD{CB@=94.&,C/ 3!Eh崱lXȄͩҧ:.bg ekn|% >G'#%Q3M ~  CA"&3*Y.`2.58;>J@tB5CcD#DDDCB?;7f2,%20s0ǕԾŷ}6ϴ]ѷqͫ@ld =U ?bPVZOZf@zT QI!y + ' %$s(,0v37 9ABCD)D>CCIB@==x94/)  xثʫq2r9^mV}2_ zD rf2 :VE:1rz&C V /2  m Y"'+y/3n6:9=$?BCDEEEE3DA>:6<1$+#"E-֠`bUƶnܸ滀I_ϡLN EW  jVA*QL1 w\b{ 6 A4nv k 2'b#(T,04x7:=?A|BCDCBA@=:73.)"  lNפ~V.9|&ƀ BkL5 @? !n,ml|'UKfu%  N(X *  Z_$2(,04<7:=?%@AB1B2AAa@?=;C73.%' bbeǣŠ趟IݷCO[$2B  p_ 94EJ߅Hc 6P je?D _!#%X)-15 8:<>@_ABoBBBA@?9=:j61,& F:7RP8&$'X|@gAkB8C CCWB&@X=:c6.1S+%e C0֕"AݹWqѴ`ܷϺIkōɵ6#M:io3 ,a'[#ߵ޸5ަ%Y16D C W9n>* x"8&+/26J9e<>~@B4CCCCKBA}?=:v6@1 *$2f cbʸG %=Tq-WO˞Ш:.[ PG e_/qduDZI[7isn >pPL_AqH Y  l Y[$(,04{7:w~;73N.( #]eZWشrUM}ȏ~ҧo- &><=h 0-J"E߁7OuU` Nz. )w z F .uHs!%*@.26$9(;=?AnBsBC_CNBAM?=:61,^% :oߌ͌`ϼ̹巟ش{6 A/jKU 3B, 2$S^r ެ OlUjUk R x}%uFu/b/i$"(-[1y58:<>@OAB_BCBA@><840H*#'ӮŗѺ- ӸBż M$5.\ 8x"<3)g}}da"ru _ v3pr:K<ScY!%*.92!59!<>I@AqBCCCCA@=:84$.(" /5 9Nʵĭ!mYߵ޶&f1] .ʥ|ڜxBN |` eW\?AYB[BC,C0BB@~> :61+}%; lLŹc>|O J&Ӟcau ;$ v{L w6ܡޘ2N}$2 mq n8'#( ,[0P37(:T=8?ACCDJCC6BaAa?<95k0)"P'Ƥ>|uVp=ՕC[ cCm5-mejlH ݍ2VFa TM3- (,$ s%)-158;=?ACCD(CCC"A?;b7Q2-'r )1(x wg봍(eo(9|G@ $, ,59 ݻ!(-x|R !6[z|@fDn"!&Y*/:3E69<>@\ABCMCYC+BBA|?q<88\3-% qא`_߾\Qlv%GNJ ZWH, -j 7SwE8߼ܑܷ@C>  G -^ 9%W#(M,04a7:Xe܅ܹz.M% 5VhTFur";&+v/3`6:;-61o+% 5 ߶)1躘ɵշ𼧿L4˓МNA>GL$ OwFjޮ݀96Zp:QYw1 m # %_!M W}x: Y$). 2=69h<\?%ACbDE4EUE#DD B@=Z9P4/)z""fN9L{%svPҶԻlk:ު_&JB>  >2ߋ'-,   vsE:"'A+047:=@BCE,F F8EECB.?<84.'M# a)Q?:950*#~/0ԲJFa𵐵rC`XzX3tNoQ w%Mݑv]@1Y"Qek  + Kj!K&*/37;!>@BD`E|FFHF>FEZCA#=94/#( $3S^ʠ$O*E޵0 ~_vkUΙkء;S| k^ $=܍'ܬOV}8dK  :|td-) H vl`,#(-h269 ׺T9̥Ѡ`f||tEi RuJo܎ܐ^f}'u \ nq 6 6) D!&+?/37;j>ADCaDEFFGFEdCA@=E847/)!L r=(x@|N!˵HR µƶ8]z' 1PD m\o3Lyw Q݇wLn#K|O  $tUv,QDQv#(F,058AuCzEFEGBGGG EC@<84/`'s nmοLӵϵ5ʺyKf9`} Al[ <:d%tݻ*I߅2Jy| j [Wa;~L #($,1d59= ?BEDtFFGkGGECA=k9a5b1Z+$hA ]@ ȹ^)̺ŽKzïϐz٦߂J Y) 6JߵV4k\B <(l5O%sKlt)!H%*/F37;>}@BDF8FG'G%FEB?_T g   DHGN#&',_05/91:73O-8% 7r ғŧ03})Ƕи(*4^\ ڧuGi  ^y yre/ރݬ>qޑ!P#xOyHv X _[e /$).Q26:Z=]?BDF]GBGGNFEC@=:5/)F"$FT6dȪ㻱'(۵EXB-S#tݒ =~Q \aj 30@߄JCsj_qt " L[\g!&+y0*4|8O;>A-CELFLFFFFEC)@R<83Z-&#^| c?Z6Oŵٽ:ĶbQ?6ʨϓ}1&W l }= WlZ}p7Bj0 $ |]: fM/$b).-2c6:z=@gBDFFFFF(EoDA>;60)! hߋ,"׹^pȾT%MoiZM G/. >| @kf߅>EUfeh\l C '>x4{"',.05 8<#?ACEFGZGG_GF&C@=8c2,%m= cr͎MrڷIyDֻńc0yJy F  *1`H-JoqG40 37 BX!g%* .[27):>bA^CEFGGGG'FD`A>D95/(!.R ׺[ʌŻ0A|"Sw=f¥mT6gc 4 $ ] ,_= Z4E޷3,$<6> NaS)  w,X6#s',1!5I9=950Q*f#u4Ҹ4ivh=<*ˢ LJ*T K HG%35-߯ I{" J o1B"]u"' +V/4T8S;>ACEZFGGGGFDAA5=:95}/) !N wZRۋӬ5翧շ淏ӺE$ɧν-W_0 San< ?A^ tm3X1#]Ie  FtG!1 9$)-159=@BDF4GmHJHcGFCAk?ACyEhFH&HHOG(ECA>;\72+H"rSh[gkb㵦dɾɯ͒%יݶEx  Zo4 ~* ޠz2(^c0} ' S"c  #S',048<>AvCEGWHTHHGFDzA>:5/( ) oOpٻē<Ժ4<^!{U}ܹcg E ; vRM2ދݦ݉ޘc-ZY&T gQ{kYB $)!-h1m5?8;>AD(F.GHGGECB!@<72!,& NiފlAê-添Q10P{ar׃uWz7_C  SBt O{#,sݷޭy9J`60 e 2/u<"y=p= [%9).-2V6h:/=W?BJDNEFyFFF+DC@><*83Z,%2d-^}5o5Ŝм칤$p-Ĺ%z~  ߹i\{q j< C?\0a%ފFݪt& : |wa !!%%*p.26M9;7 2+#)Sj٠ѻqĂrõ>QK^n`c"ԷsFX[Ybv 0=)hJ9ZݟZG:> %e '}t %&!t&#*/k3y7:G=?B|DEFFFFHE-CA?<_71*"V "~oΔǻM:ﴏiԿJd֭&N` "Au ~W#!`^ބ݀k&]>]&p Q? z X05"'o,0i48<>ACEIFkG1GGNFLDCA>v:N5M/"'T; /'MWyx½u>^_͎Ҳ/6[s /P V.)g/{ ߮ܘݡ<yR Yeh_vR.e9VA@b$). 2369 K=">jR+D 8\#%S N"m' +/37j:=@CDzEFeFF|AC(DEFFF EYDB4?=I94R-%+?Gܳ-̸ň˹.D!Y־^1ŝѮ kGTM3xf &T Wًnݒ\ d  2z:  #FI#(y-D15b8<>ABDmEF?F:7>2+". |ئU[ik V%Y ^pY5pD]!ڙ݁ bJ. pA- o "^&+v/47:=@BPDEFXFFF*DCtA?%;6 0* \ ~ΖEp޷ͺX.TχnJ\=d4 Za OM%@nVaޖ|ZI $ pkQn2 Bg#;',20n48V;>ACDFFuF`F@EEC:@=>95 .c&U>/ Ӯ1LҺ]=j 7ď̆.` L  : FwܺtZܘݦߧm\4  #2>$ ago$s)$-159(<94,L#4g(«Uj7DZQ=K+QσҦwh"hcd*   R|`(T}*oj"  ex3>|y] f%t*J.26R9$AT#Mv S (jb: $(-@15y9<=?)AChEFGGGKFrECA>:5J.%iɾŋ-ŗ|%ДrqEnۡ3JC 2 ~Qh$&"&**.]2e69fc/ ym"v&`*f.1d48;<=@qBE)FGvGGFF8ExC[@ +@BDEFGGGEDB@=F9+2*z l ZP-zMy7Ymš{5 kƯȀ0hbv=n&(Q[ g  g lh=DRJߒxی9Sݴ`@anj.o4L ;tQ""%)-j147:<>ACME#F}G FFFECA?<_7V1/*!% wq ǢGrV>AbNΫ1u2Fp r Y O,WG7{'ܑm܀@5. ~ ZO N#u'++ /26)9;;>/@*BCEG@HHGG6FEC)?$:6/'r]ҵmŤ'bCy9̒ ҫ8ۋ[7g> 7 RxB1cRqFݡ~`2gt  z-S"%)<,0A379<8>AhCGEFGPGUGwGFED6B>9v3S,$} %Mӡ1ȱƯèOØ |3˟@Mԯ3,:6"U  ?KfwH7S߆i۲ۖ!(U6Yq| '+ U"N$'*-1I48:=@RBDpF2GH~HHGFECJ>:l630 'C niiVІɤ*ůƆǐȮ>˃~͸AԳl xv= w }/LE@ܛۓu޼mY 6P2S  dmSsA 0""$^'2*>-03i69M;>+@dBDF(G+GHCHG/EDB|?:4-$4,ѢΚȅǍƵk@u ˗l zR#&-(+.147f: <>@BDFCGpHH6GGzFE*C@ &+C߾9ʽ ""Yl*;@BD E8EFFFF>E^CA?;&62l-& WuYJj)q?˭& ˑ8Gf u׶۪yI} kY`I[CBڇAs 5k9KDt< j-!#&)D+.03-58H;=?ACDEFFFFFgDBA.? ;962~-%W 66l" +d̩ rʢɭʗ˷͝LM\3ۤr,9 | h^۶DXBAJ^QX Xf]"%(2*-D/24O69o;>@BCEcFG GFFEaDCA>;97 1*#17*+FF2(nA7̷Fʂ>;cu΍ҫ5۲ H_{q60ݍْكUwk[XS #X&),k.14Z694;>w@B>CDEFrFFrEEEE'CA>a:h5/B' L17FQCnMW{ʮVɴ(wХE5(޿ t6Yne:,ڑzٷڝPs'I KV $(#+T.\136:8;t=?A^CWEIFGeGHGG,FEEC,@9<83.' c;^ T0۱E@F ̈˚ȊdT˟`"+ֵٻݹ]hx)np$:jij#gۮڮzAܬފH7AxE p 7Bt"U&E)- 0 25s79;=?ACEF9GNHHeHH\GKEDbB >;H7#2@+$ UZeS^֡WҐжA$"bȖBȈɎ5%,ط8 JT][aP2,+݁ڼܨޘ~T .fk #w"k&*-0368 9;>2@BDmEFGHHtHTG2ED`C@=F9G50*#2 c^SؘӢ*ʓA<ǦǂǍ_OʓXϞpbhNl<7#diMtB` E@!&)**-1.4O729;T=?@BDEFGH@HTGFMDBAM?w<83K.A(T!Nz7#Z+:ܵ6ԭҨsNȵAOūƉ;wrVЀ֪ڎ߻6SKh<C*v `&Nx |%#;'v+h/K258P:<>@BCjDEFGGGFECA?=:6c1-C(@"N\ R%/r1)Mɣ\uŧƼdzC^/aӖMQ,]m!Yw?qPL=!%! 6 ^- u2 )%")-1~47: ;=?@@BpDEWFkGZHH)GvFBDCMAv? W?A^BDOEFyGFFFhEaCB?@>M;]8t52.)_$PQ ] r$/oߪjُ]ϥ7ȻǺƇ"Jʨvd+ѫLOl4h(sW4u>5ݾ9rޏw0%m  #7(,1^58e;)=h?6@BFCwDEFG FFEDBAH?=;973/)#E g(iޑՊ͑c{7AŨƤɧW@|ܳ8/TP%`tMj:'5FHJh nIB#(-\158;>@ APBrCDxE6EEEEBDsCC B2@>T;9.51-F(#VMU;o[OՄ*А*Q]'%mAȖ&$t{>:P~ ߂+BP Q0c#V',|1 47:}=?@zABCDVDDDDzCCB A*?>;9!6<2.j)$z vPV}y^Y ƅŨc%KœAǶɴ˗5mRq]n V$4hvF:37`@ \ !A&+o/37>:w@ ATB[CPD&DDEDCC:BW@?x><)9952t.*&]! }ic8 Ҫϖ̠(?Ë>BdYkw'8&!\AZy-A@zY? EB  A%9*".269@RABCsCD#DlDqDC{BA@?>o<:8]52)./)q#* 32Knl,Eli ˯ŏ?,jħTƂɲ˘/(ژޣ 3X* x2[S|MjU7  x-"',048;=?A1BVCCCD7D@CC(BIAL@:?9>6<:8)5]1-)%J M ,Qiu_"gɭZC3Ɛ˶͈1B@وhS_Ry\DdIL?+ E[ %*/ 386:6<>@0A^BBBC BBBA?>d=$;:98-52.+ '+"] .Pa n-Ғ~rǻęÐQ|MC"B~Ձx\ޟQ[s(;Z?_h\c` `!$3(-{15I8n;=4>?@@AA @@\??>=<;:98L641.)%!w 5=WUUܿl6IyLMĦU%o[l4.Ke h;`e@' `|m!j%_)-147:<=>???????g?!>=<;p98n7K6<53Z0-)&!i$y b9UQޠZ$(` JŞX5ĄŐƫI42ϗ{)8cf;<'+x;F%\i C tl#'S+v/F268:<=>?(?O?=?>>'=|<<;3:P9G8"7!6 4{2O/,;(%# !1D*ٿΫ̽ǐƀʼnĢ+Fĸt\Lг %U+7)U0Ch5 cj!%)-v14<7 9L;<=>>v>}>U>=<<<);}:9`765Q4]30-*&"k~ # L٬(4QRō,ň1ǐʳJ`" UzRwJ[9/\|Iu[#; 25^"&-*-.147|9u:;oߨ\9-h"%?]OhD} C'WQ!L#&R)+.1!3y5w688919S9Z9M98877/66 5*421l0y/.n,*'$ [,QSAl%Ā^ģŽFЈfJ0t!9#]?5 f"&$F&V(b*,/1524o5k6A67R7|777J666F55+44 3I2M11/.Y,')w b MKXt\ݐ]dYq2'fİľfr̊~ҒՑ،9AZ EpZ Og + hW!#k%0' )+{-/134)456=666666m655r43210/.m,v)&# H$zdnXM[!˭cǴƯJmr Lހt :4S3lwnG@ Kg!"$&)%+-013j4|5L56:6l666666665_4[3K2V10/-*'2"Q} DB -U٢O=nɵ EĖķœGZR C' O'h$DF.IL=  32Y$!\"$&)3+|-/13 4456A66677,7"77 6635C4-310.+(o$7 }ux^cp~ѦC̥Ź=ČřƩɸIZ҉^)|-l \:[[+S*e_%[j \ lt "=$S&)+.-02~35567 7m788>88877#6"431C/./,X)&!C g@pt~؂}Ҧ5G̘ʐ' \û VzFj&1vXfp:g4)i8H}p nS dh!Q#a%(M*-Q/13596?77858e88888u77A6U53K1X/-+)<%" D !'zޖ٠sEύvjƬ@a_ǃɼ+ΈwG&w}VLGnV=R`c db/$O D"#%'k)+.j024{567Q78*8A8777j7 6H5V4L31b/.-,h*K'$   E޿qXP֗E<:o{ƟNï51úďū[ɚθ &v4=Vy;[(Ipq c 5".#%i&(*,.124e567)7777`7H7466i5432/0/A-,$*&'$% S/c pe܇զOPΝȦoĭožŲ95)R'-"eHPN52a(% ZsHh i( "$@%'*,/.D0W2D35$6!6788-8,838:8 77669564 21/r-+c(o$  קՄVZι3hɧFVM )q;&:X~4fX ;-=b| U%9V-!$2&Z(b*,.134567848888n8.77Y665I421D/-+(%!o` 'ޒϺ{ɨŒ@}FÎzַ҅ۆD/WbBQ71v F#>0H /?AlN!$F&w(|*,.02735P6m7-78W888r87765432108.g,d*3'$@ CP %7q ^>kte {Ñc [#~‚JжԬؗ܉Q|>;)#+S\qkH !$l')p+-/F02q346778F88888;776o5432$0/-*(B%!6^ *a! Tu_Ff6Ɛď¹Ҿv<ÄŅ פP/*GRqJr)U9Y8K 6 #&g(+]-/1v23456`67x8 88888077A63542109.,*Y'$  ?MJ|| ؾћFy[ƿs|g lRÔyTjsm[%C=nA'pS TQ"%( *,.02^34567E78v99`9S988j77 6@5W4E310k.,X)&"aq#mH$W{ތ՜p ˑ{[l4r~x۽E||GǗ'P)ݍIuP0K;Ys6dFC 3 p!$'V),.0273r4j5/567U78-88988R7665/4210T.,*'$r [i xRR׺ӍQͭ ĚMGٽǽW#)Ħvgq\DaKyCUkA+;:p|R %x*A %"%(z+-s/1<2345Q667&7i777777;66p55421r/-+(%"Mw $>9ҫ,Iɫ7o"H61cлًE;GR@Sed{I, } WpR;9 ,#$&(+,-P/>02 344566677666Q55N44$3310/0-s+g) &\#` :04dK߮ڮWt=72NCT¾IEȽ˚λVւ߉XC}]4fGglox 5`k #&V(+,.E/t0i1S2(23=34844444V33,2X1}0y/N. ,+*)M';$"B]9 ~sAiߤJ*ӗЬaHĘ]«|ŠŠh/ίѰ=61Jj&Gl6>@~<^(U7  < "3$'q)+,../Z//0?0z0000g0//:.-,+*R('o%$b" F4LD% L>(v~:k!сA:ǂWWǢkL,dhQX#t7rSq&Q$ASn /$3!q#@$&'()b)***(*2*(*))_((a'&%~$c#1" l8l[ _ bea0{uֿؓ/ҖCT ֮؃tfZD("gqP,-Rxu+]a{ hFt|;-4Vv8e  c;|j"G:+m|-JB'3&;B)oB)F-u ? wb@.>Sq^/ ( T J  < I 4 B q " % o a y E :l"6nbR"4w;wZ[KEw!?!FSX{v{X`p~pgR})#h2cx]@6^r@Za  6 \  . 5  r  | 7 * }si!HE,s, Y "P) %'pfy2YR9?PtsWJ4Op%{7: :1@q & F&Iu5u5hAp # " $ S-m6:"q-6 S'(Rz[j Y-jO#Ai&VK,v~usL ( y O q " b(s2J^<WvBSEbG}  ! s  k   ]2Nc 9 ",cR=v!&{ $G: Ag(zgW{!9UMg`FdB7Hg ; t w S>[CpJ.5X&FZ|ax T =U(]-FkIgzo7ߎާݟݺG5Wi@spT Yzv@I*~.{ I ? M+zZNt!AVX6   L!0 ^lM;+".p-sm}@&- 0NP3 U~C `0 o:pgd~{==/O b ! N a ^ G " k * 4|Ho;|^bM ;  4 I ! ] ] S 1 &Ed~H~?6TI uw"F=&Q=k Ao[<nu = & n 0 X  E k 5 V m3 ] | \ f > % 7 ` E( F1]qc,5+L~fm{cr޻< ]n7&&3Ek6<)RkLl~D [ + m , U { C =sM   g  * r 1 ~ QqI7f k y   dS7 H0 d-6*ilmCBko0A/]'s,JQNWS1u8k B  J c { M $   ) @ I , rI<|/ f+4FmjV3 n  k  ? N N <  .P"E^r) tYtri/{+ K=Luj Wtv[~*+m3Y;"y 2 e | i S F E O ] % U   t X Q _ x  V r r f ] F . ~ J \ 6*g~f)h<)E kodWPzbi/{FR\Xza3}na\O' d<|  k  f - c  7 n   2 - + < < b   sK_X i d S!`fAq/jZ!^}yItp{[ ZfLIy W9H ' " l  J  i D < K b  j >    A ] p   W u d 7  @ p s"\kP!m>Baa.!3 >@- l CU68n#wX1sQhH3HEyMb.BS & g K  4 > " v f _ \ / F MgjYC!C ? | #8`2XI`8-/L4tLXSsOGFC<oa-Sq\*DRM3,mA8y & S 3 w " u Q 0  < n  i)~5- {:QY E-L?A</v2R @{"iށG޵KAjWm[ Cw"_-GHb 3_ W - P ? v# 7 h   c W f73{+L1 7  tv2]JqN9)Q,|1&1=ޑݥlv,b/:aSC~VG,J]^^|IBlB z : U hl ~ u   z * 6.<9S:F d J nn>`=C!3 F@lB3ߋޢS^s@=^:`w-cA. 2]ZUu-C-bS ?  n  0 2  W ` ( v Z [ p  X+]ZsQ@41 B H 0 O  s R ~ zyT;PmgE*4ވ26|/c>ݷ޳ bA2}1'1 >HW4dg!  , 7 ) s?  _  S Vm%qq]&@+l}|i8   o"I kOmt\%8]ۤھڎsoڄJܿݜ޸F ET7JZWsL A C6_@@ q ]  h x z3.9~X_8KaYYx` =+jNIHjlaE )j|u:&ړ٦G*Nلڅۣ$Jg?t06pY VrOU>=0O ! w> W : a  3 o 4 R :Oil2YS"^A=[)p{ x # R3&k6x KFs+';ւ֤׹*:/c5t-)$$ u yBqv  k - H%3mt@# T n X )) . p V & Ij<Wg]8-[G@+"! ; t q!N^ A8)y0Id0gx݄ٞ0bҿј/ӂ1E۲1e-s9/bT* $ , a 3> ~  F u g 0 9~% 7  cDb7 F(biIZKiYY   >A%r7:eD7 VvS\z7R7TehKXJ<PO` z } <_Sq x8!3 & q 0 w~ $ Ik'el+ v]J65g*Q A o A6,w@hUSnQgϚΏθL8UzӨ ْ֚RݾI_ |  Sn jo  (^  7Y)r^ ABBq ?  RE xS\D Y=]${ A ;/I*(J֡ЋϨ)βζΫ|:*΍ϛoӺTb&: #H:ra jlqI , B  }S }[\yw]V 4 O&qgIB HnU0$d!G 0G+o93-bBՕ[дs(R,Z,"ѫ?Qtv s |  ' #"<P&,SI  . Ns!A( 9 : G(6g1:y<K T <_^wKX \ !`!!0 :oj8  UC@{ܳtr֤za(ǰƟƶuFE֮!?e  { qWRARyzz f ..t U x} p;)XPr >  mHy ""$%':(P(r''%$#4! jV$}g A 5WOoKdypy_&ߐvLXo̸ʝǕq|cĊYƲWʉYоԇ؛2/F9 N w H \ r y7o'W+`'  TqrN5 0 H0\+wo.  H 0>!$+&(*,.-,+a)('B%$#"& YH 2Xvl+Y'F&҅~Os  m4G; ɂXޘC<$l p  So1CI;0* E 8IuEp" zHUJ~!gb~[N N=y"U%(+h,-.9./0Y1#1K0/=-U*'%s" OV@ I !'squ܊٘x#1˘+Ƹ%{**̛ј-|!H t A @rjH^tm < n'1de F@WW&n \)`@  M  X}9"&O)- 0234 44h44g3220/L-"*'$ U ^ AZQTI 6NP`Ν Ǻīоk ywȪϟӀנ܊9 |Xg - B ~ I *Ie 2H33Z/IyqJ o @+Za4/a~P/h7*Y = [;-!Q%m),B/1o35+56?667!766552/,g(%C!Ho/Z$/3ly\dRnfݺ!Hh"DF- T 9 w3gUd b%{zrq`q! ]<=v &8eSIe]O  6 <[#S&*,/255799:;<;U:864T1.+'#) ] a49Ss1~8ݘD㼚P T}n$Z  }IKz* = hCixs {ag)a!uDRsssA J 5$w(_,/~2z468U9:;z<==j;97m4d19.O+`'#]D 3ha !ɅL18UӺ꼼Z֟o)| . 2 J!WT. B:J,i f% ! 90TO^xL b $9'l*.X15M79;3Mٽxo^uϼӲSN  &T T c yL1O}2 B6( D Kw-%ur%l bD?{ [|zn &|!%-(I+/.258m:@;w<~=Y==r=>?T@?l=:72-(~"N >QyCإM%x^iīes0e;׼aE&/zF:  K U N+bG&BU mMbYe!q"##" aiX %AfTyDi-r@*=#  \"&),/1357,879<>N@,AC$CB#@?;61.b*%Cq֚|(B; ræ¶K?޼i-Kͤ؊ݢ mp. fp " /ZMbY[Dq ZkH;!#$%m$" C_ 6_MbjA3Q:2 b2 #'*-0z3057:m=h@ACEDC_B^A@B=v94/) "guW/ C$) ͎@ BJDE^DCCoCAu>;8&2,&gK F|k1ڌ6д*ͪylRp h;x.J=̈́ڋ  O T " K;Vm#x Cw!#$%$$!y J;`-oL; ;n 26?NX  w"&+g/369;=?b@ABCD`DFFEcB>952+S"k / s \ڙ а>V̜ͧʼȮixL33dPysJPd8+x c  j>\: A}' wgDd!#$$$,"  .I)v:pqYNb>rUNF $'+T.26U9p<#>ADuGBIIHHGE>A=9$4K.)K# 2B)aǰǘJC{x Ƈ ͭyX6 8 8 w T%u]2kW< $ S;!#%Q&%$'&%#W cS% bB{oG}FE[} 2a TB$).2!59[<>5@:ACTDFH[IKL'KGB><70n)" dKjKճ26?]ʖNjLAPņD6Y-.Ѱ.`2-f _ ]ww-}\wXS _ j#.%T&'1'A&Z$a!btc  -uNni.BE6. Qh v%&).z2j6 9B;=@_BCCE6GJgKKIGDbA>v93*GG }܀i<}}m]TǬ+W2uǥ,A{k-A&e  =  , " Iy 1-'!n$'R)))(|&4"^jEv 3@kmTUC2$=X4\]5Lq% #$(-147:=@C?E{G,HRIKyL JG3DB?;C5,!J 0C{ _ԘQ>ƇƚƊns+Tɴɓ!ȳ2.60McX U  %GLp+Is  h $T')+H+*(%"*8 ~G%y~(--Dq F9 T$(,036:=r@OBEH2I\JPKJJ>IED?;60+M$ EWɪȾzǎPqǣKWbɦ]Ϭs؍ U'/8 J V M ^-Tq ^ "Z%(+;,^,.*(%"DaL c$C,1zol+/Fv) ]M $"(+.2.59nOD.KV(k| 8"j&r)+a,l,,*&"`n; @a,8 B-Pe&@rSU b %@)!,0237:l=AdDjFHJJJIAIaJHB;50))"?+cgޛg1кyȈ#ǞV|=ɦʵq+XVϬϳДՁ\k0T98wb9=eQ 0 $( *,?,,V+ )%"2 p . JnT)o 8 Za$),037 :.=?BE*GHJ}K@KIHQEAo=9[3* w  ? hĻ!Ā:ǃa"5͑9sѤz ۔߈'|/iWQfn0^e_ L!"%(+d---%+)w%!Id }2T;s2Kt#4F .d:{`S&#'7*.w2F69AkCEfFGH`IIH}EB@=80H%]y(F+KلXk}YċWȒ ̜ΪУV]HרVd^8eNG]?/rjSwy_ M"'*-(...4,i)}%!u{C %L$W9z1k(8]'ySW0SV%%ɦ,>&~՟Vڟ+3L(NV JsVK>| $(,o./R/. , )N%!=,R g1JM!nU9.@ ] -#'*.036:/=ADGWHIIH}FEDEAg=9Q3*i (F@M]o_VďǐX;NԬؘ, 'LX vu4 _*!%E) ,r./0.,)%` 1 teN[vMV&zv-, e')1] (}!%),5/?2p58;?"BoEVGhHIcItHGDBJ?:~1'P _ EɪI_{(|чӽՠXۻݘT#(wL+1pbH #i $(,<.n/k/_.4,)$ p K=Bn-kXm-TMg!?0 3#'{+.2(59i<@ BDF(FeEEDDDAq=950*g axyɟƂ(3ć|Ȥ^eBءg|TKt߁bTAm,w.wIC),VX n$e'*-X...-*L&" .Y6Xl?iwFc 4&3\3 4"&), /2`69=&@iCFHII,H&FEC?Y93/)!m 2z Ñuĩ8?,ѵ1ָ_1LRuB8s~\+](c^xg  %#'T*]-./7//d-*' "cy "+& Qas[[g_,q,S9M"kL bR"%(+T-0e3i69<@=CFGhHUHHeG9EC!>81*"Of1NҌ͘ɌĤ]~ºD9ʔvΫtOٗKP(Nj8~ s#~L0q =#4'),-.2-,)7%!E`  < ?uy6 w5!jl8Ho4[| !u$($+/q3y7=:=@3BDFFGHHGE7@d:v5/(!NV.F͙ňºöƅLG |$/*8a8 q9E82@ m$o(*,l-W-\,T*-&#V yW[!-n@8Fn6'g O3 #'A*-1}5<9 <@!C2EH%IHHGEfA=:w72z+") \܍θƢģ- ał2͋Ҩl y<,ff%$'J 5#'.)+L+,*(%"u b>C)EqKgpVJx O"Z&)-1648;>>ADEFGGFEC?;l7q2,%u'Ѡ̺ȻŞÛ¶e\ĕƟ0͸ e֧9ܝ|yYb2K] K $ ')X***)&# J/; #-L OJ8;nTKI<-x7Gm$oitF 7 $k'+.1585;>A1C8EFG GFENB?;71) VH 37ύ3n-n'ƧɦnwՔTg !roT!v1b;' ;W"S&0(*d+>+.*(%5!%] ][ q>0)'3A@h P{ $(b,/3R6:8=]@GBDF1FFEDEB@N<792+#$ _ߗة4•*gs͈Vz֓4ٙܛt8?,ST ~0'DW- #|&p(w)*)['%"e QLjh4YOy]qV46 MwzI"&)-0q4#7;>BA'CjEFFFyE&B?=09<4&-&u $џDsȸʱ(Ϻ$֎y|z߉I*):qn]-$OtJW C^ #&!$&'(('&t$! #~#{2t,;a8r , $'*.@148g;>AdCEWFEDC @>~:50Y*K#` dUf۠ՑR Ą:)QˤfѿK2gۥE=x@7whKM@YBeDEE CB$?<8)2,% DբБȾ:ƍnsɜ3Aϡ0d%ס2ޅ)mL\n4lpq$uJS[yq 1!#%%%% #e!l2d |vW1fb6[f`P9[PFE GbT'!%f(,0)369<`>@BTCCC$A@#>;!62-M'3 >FۉՇEtKǨm̜ML6}:>ې&$8r5dQ w4-3X+Lm7 `}!b#h$%$%)$C" $*PP8 `4YsvB{ Eg 0` A-""&a)-0s369J;>}@ABBA?=;9951+P$X IdsΠ|}ȃǽǦf˦Ϳq'Տ ؇%{0/aEd![qpQnK{ 4G!#^$^$r#!I{S1 *o6kK*)Z)>ly@$;txs  G"%),a/26,9M;> ?@A}AAV@Y?=&9I4.*$=oFيԎϢ ȱ ;ч~صC}P8$Ap/UDNR M3 !["##"!]p 0 V =P[ %Tg`, oQ: r&3"&\)-0C3i6`9-;>?@AA@?^=;273_-<&x6D(l?ʃĨsΉӓPl5ڸC#H޼rMOOsxg w4(Ad Kcr!!! oP*l uNVJWUF"`Z@CO" f[/ @#?&&),/295V8;>@ABBB@=9l5F0+$s |E$b'Z_C ohqY݆߁(2 ]P~A\7 G|n&-/R <u&J~3PD  's#&&)-!0T369;=?i@A{AV@n>i/1so.Q , <1!n ~ +  :tD)-BYI(B(?HS/7 J+0!$6'F*\-v0369<=?M@@E@)?~>5;8 3.(!m {,A/8ЎϽ1υӀKզMTՒKה-IbUR'@pj95 Lsq5d)E R?[|:=@>e$k% M 6D"W%(+.147q: <>@fALAP@?=:362g-}'{JY=hcҝ\nӊӳ uԲՀc٦7a߼Xa"s {#Bj'c r \XLzTf . 3kJ"I(<%2kdAr] = #&),/25F79;=b>v?,??><940!*%!I ~Gx^r2'іnшҶԡԉ.~UQسډܔ9wZ|B DFkQbD&   V46k[=crw mC- NjHi!$@&),/a2C5@8;;,=?R@6@@@?G=:e74:/)#9jt:Mc>ѼРB3HԐԩsRӸ Eݜ2 Se9}Gpx P'U t'OiLZ@ m 7 JiF( ^sQ L)Q"%'*-0369;=?+?{?^? =;840T+%<J`H{܅I һO<`Ӹb#|fуѩY?Ԏp 1p0hQV0 Tth| #V\*| JQz $k$|r9u" p$ub xJaly"d%{(,Z/258;=>?o?>=<; 813.)#o~o[9קӐңGu{ӨCԨTL0cz.[ҤHւ.47Z-3QnkW?:- [ g#+? )'^ S qw)vVG#WmCte~ 8 1" %O(+.1f4'69Q?@G@~@;>d>>=<_951B,'#J  %? -b Uխ[TANзMR]ydjݽQ("D$9G]c.SrT NWU)O  \>':Agbl\tP u"F%),==;i85J0+&!5 $}['%ږUՏCPթ՝Էӵbͅ/ʽ)>ڱ޼262(Y{J?];%@#/ T VB|U(s  7gM)g,e2>>C=<:s72.L(!R| iݟښxӞ'AӺ6gjd]sͧ[SUzطܞikK ]kF`  _<Z5K\2i 9#V>ha%4E<9r # c#b&(+:.+136:8:<==>>,>=<;`850,*&c:ݜڠdNӐџш?jћ!rkgRirһW(P$[C g@ph +[c^Rl<|^1|vQ  V u# QEo*,h>m^~ :G%e!$'}*6,/S14W69~??@&?><89o63{/'w+ W&ۥ ҁRҮ_ 1e˰y^2θr9Vܝ>XB\H\PT#eK9u QA ' =w F g$Vw%KZ cH'EW C /#&%)A,/247:8>>b>?>W=<495/~(!} H_hM۴տҭ/JҞҡх>ϳ`͋Q+̺ͧVѤL׳_s'eW`4z; / BU0k  ,?o \F8uuz[~<TUA ) "%(+.1479;p<=?+?@7@?<9V5d0*$EU,FڅPҌҞxpXDld̑},Ӥ #iwUV7#eQM~ b+} \!"! 3  DMmHkT] Af_>Us$ >!$'*-0369/;=>@3A>B6B1@=:251-P(" XC=]Ӥ>ҏXнoЯХ1ϖ&˗}ʬoAmh5M8WmTSy 3 ]W !"\"Y!d." D"\_AfM1.58y d V8 #'+.T15a79;i=->@GAB B@>:73/+0%)N .[l F{7ѠW `ˡi/H()1WZ"\$EfP@pR i!#u$[$f#s!k\e S3W-y{CMv;P-qB> " o$*'*.61136%8;t>2@BBC0B@>J;9451=+$=Hdk֨ԡLtbwѰЯUζ͒D]б*B\E'mq45Kc `W^!#+$${$'"  LexN932X<:7D sVo ! $I'),/358K:=?ARAAAA@]><-8)1+\%Jtv_"9ل{Pѳ -(W}ʫ\ȃs^8E̿Іv32]\S$)K'ozr_e+ #sr!G#1$X$#" v9 ~:p@e1&/Qbi%'S, ZD!#$(+<.G03\58\:<>@@A&A A@?W=}:6}/{'/z;-| шRЇϊ # ɷȪȩeSd"R%T z;1r{dK # >W "x#$!#"!, @AAv( *z" /. $'2),/x2A58;`>[@AAA0@?v=<;96z1+%mQXvM՘ҾѮж|бSrWCtMȃ"0˾YHE֣D N7i)PH *v D` Q"$%&6%C#- n4 l v( f?AC^CCaB ?=8:r6h0( mi;Ս;I$+v W[:\%Fӽp@L8}` ^cF( DO"P$K%&&%5#!G7 J{'+"GGDEBrOsW: ] A!,$(*-0369= :726*"f7 }X6ңMB{϶ωϟώ OU e˲ҵ֗j SI2_MK*3j !py!#$%j$#b!3M* QK},<o 1hD #   ~$(+.&0358:=?ACCCC"BfA@=9>3S,<# R]h$֨#RаFΈМЋЋxRͦu)Gɦ̸ϹqK"5 Dv "$c%% $=" ";B=  .jKSJy@!3F5T @}O&':g .i6#}&),/14}74:X=@\BaDiEE=DCB?<84-$WB YRMuS5ӆдjASȳ\Ɏ<:uF pKw7 oQ!#$%$# $6 a > 0f2]M`Ae=}q+.U V";&,)-0?35Z7_9<\?AMC5DEEDCFAO=954.(P!3\ԒЪϟϚЪ1O0yУ\ =ɣ>y d^l v|`%_07 [q![#]$%$#!t b CX-Z"%NDOA0 bn]"&)0,(/)2G527:c=#?BCtDFEDB@=9o4/(vqޏW!ӝeF5cҕҕ]сЄ\hZʈ'JeuWy3<e>S1 p !#%%{%<$?" .I P- (LJr 7= c6WdI #'?*-04>749<6>a@!A$ABnCBBA?w;72q,%| xإ :sϰЛag&ҒЁ͜ʱ)gj.St qT:CqKOYg w #vg!`#%%&%>#!AxN p2|Qu@Ey'fcF" w\#'),/258c:=}?ABCD7D"CB@=: 5/'8>gԚкЈgϫmһ@'9ϲ7w͋k &'̰m؟ܡb?g*PH)@?]= *a!$&V'c'&$" M Lp8Cs@f~tG Y;!$'*-M0a3694;734,7#*n sQ раϝx,?haz Ϲ>ˬˆRΛҵ&Q,;XkBlxE;pA$ c!>$}&''g&$"y/= J;{[ ^9JP hT0#g'*Q-%/2247:><@BZCE3EoDDB@5cE: !-"|%(I+ .137::4.' XH%1J.̊ͩΤ ίE͵/p ͱίyد6iO4s2j9L @VC  ]-!J#%%%$" wO Kf_KS2G zKj!FAW v"h%),u/u2Y5n8y;0=l?BCDEEDmBN?=9>4-s%- Z^ַҌϦ͌l6f̀/Χ#ώ*J|-iXдx՛zޱ?yYoZ; ]%;. ?R "$&&& $"~ aX3N|- F3.{|3RqB 0% #u&),0*3:6@9JvjNyd^ C "$%\%/$" DIq 3%+Rjb5(R8Ky9`- /g #&),03H6C9.fACDwEERDHBu@>;661'*$D ޘ ɒ{Ro`i1Rώ-љҌaQ,I_?[FadZ @T!#$%9$$%" 3;] lLc>y 99nLsp{]1 "0"&I)-:0S3Z6s9<:>ACMDEFFF#EC}A<6/' ORr͕҅:);ʛ.=JͱJфMӝzՑחڤݷ |h@ F!j (2!#${$$#F!/S$ | JW{6&o55{c)KsJw Fl!$o'*-147;q>AvCEFFEDKB?<71 (  BI ޿؊Ь̪!aOϚϳϽ4N(\Ԟui-Hr;`11@h2{;" }!#^$%$#!&T+ [ R~iZ0IU&mQw#tXu K9f"& )C,03c6:5=@BsDLFF5ED3CQA=F83(-~&D |wtWJ ;QΣ0ZЊ6,KFAVF8{67Qavu$|gm  0"$$$#" ?_J s r,[71Ux pgiJR l #'*E-1 4[7;3>,@BCDKDDpCA?i<70'6<2 ̿'H1 tkEenѤҾ*֪8+ (np%bO3 XJz %"#J##"!L;q~M{ D ns \hF}`I9f$zwF-Z v"%'+,.15G8<,8;3w-& Ix o.zׅ?5b̈́Ϊa ҆nHZݺd" V=5DbyM B!l"###g!>. k Em mQ o/F&3x0%W \ W#'*@-y04s8;H>@@B5C:D;DuC[Au?=:i5l/3(  #c1pجԩϨΌ-zC&oћ6}ϾvZң-R۞":gA. JW_d :{% W"*#T##!! (Y; d2`b!hY~ a"t& )2,/2"5L8];G>@B}CD~DDA>6:650*N"nF+V׌<΁ΔcҠЈЯ6,} +ڜJBw3z~u*Rs@"pvp E b^Y !-!!3 &r |; +Nkzb2H(?K ?B  Qq] b#&*%-I0369<,>@ABBB @>;}61_+%Y3&lҙ.Xp@ҏ# Kы<1nڀ݆@< b}h='L I2&*!$ El\Y"68 0 nY[Qr<tkJ8o60(O N."j $<'+ .g147:K<>S?~@??:><;96\1w+d$t[ _kVqf ѧcшqӧoԽsӞ82϶/Uҹ^X؃(U5(V mi P PZ  @ lW  7 fb ucBp+46dX4kq 8 b ]5"1%A(I+-036!8v:/?W?@"?=:73/:*%=buJwܲٺ֨}=ӢӺ$X҉p5PMόcq?׊ڢWO\?aoF[<q*T n %,8`  B DrYXQ"rlxZ M #&),03697;=>>>>=W;X852.*%YH5(ZW ٙ԰~Ѿs-Ӹ +4t\н~Xؔ B[-Z< X #/ s kH9ve1s#>7kL.rY cX&!z$'u*7,/2K479;<=C==j<:3863R.("]-?ۧ Ճ8GV`ҒрOϢϊϬnzi)G`l?%2UJUbFlz'o ]ZYdI$yc O [ u\}CQauW}KmjjQm  g"%(+O.03X5h7j9d:;-0'2t4689:;;9752.)$<h  X{JډL5ԑӃҗіБ>л"hUԞ`Ttg4\ y)"} A Rwn!*e={ ! q0e0V.*inKn=, " eG""0%T(b+o.t1J3679!:::9976$3j/`*& B l7PjCCZ&u6ѩ@ҫQђ'Q϶ϗ/9Z]"vE~F`Y3^ C =IeWj3O x $|A,Id3X ^`'0Z  #'*,/24r68u9:::M9752c.|*% G] %}3aKI0tҦљ\e!*ϵ2Ѥ\>ܫ+)?uK_j6D Q x iN&j,@0, mJ]UY3PX;Yba?B{1_/` MB @Xu_ =g *"]*]ASnrs=$ "5CNTJ& #%(+.:0315L78\99<876x42 .*c$(  *;2[ڇn+Mb*ϫϮϓVc&6mՖ!ܘT8i3 7P"+Om ~/ +Ipm9M g[<$>H(`Yjq\ck n?!$y'2),/24678E8`8H76/4`2/.)${r: :!I:8ϞPeOТ_ҝӡ.mM8v ,60)$Kk CBE)>  | X 4 @&KOvRrIFtE hWw!$l''),h/13556w73777)6664k1/+'":W sfIM(ԛҐх1f\"MUٷ 93(Q?z5e&.l'e a 0 +9 p F-F$$B-;mj7!#}<+!Wc tN #9%(+I.035788876331G.*%!pN r'9Om߉61IӑOѫшјхM_e>/VpRP=Kch  zs71E2 l Q 4:J7(+/Y. J b V J p"E%'*-0L24u57777{64r1Z-*3% x mctu@R/6d c9ѤD/ԡ3עLތ*v2+]cobGFjNH4| C 6T%%-= )< 5 % .V,Y6;,?(q@JV jL#!$'x*`-?0'25 67-7_7w77642f/Y*$0_ M~oכG\ԫI]Ԃ*| B@Cס8,=rcDnr C|b=V/ H.#K*1+  63R)2c o TCkc n5!$'*-0i245566\6W530,(#k% 7f0 4x4ؤ՟Խ8Ӹdgԇ.g99<o)b6?rC q(h}gq 5 6 7YG(4i.Z"5wix y |a!`$'*-0924666654;29/,'"Nd.SuݡfֈO7ձ>ծ؀zN~s e.I88;T M f0tUA d 7 k -H:Ritf p Mb!$('+T.14j6 67i7s65z3O0-)% W)i% Dئ@ԲIQb7ҭ/ո\"jv%vb=a GV%^oh lNv i Q X!fT;QL'h+_P0,9sO 9 H"%(~+}.1F35S67~8764;15-i)9$ 'NR%xFZHyמ֭,ҍѵҞ-ٻk0 ,+ADE hw\)Z$j_= e ~DX`sD i E"zr28K0k } YL= #&*-G0H24567L7X652.z+;'#j~|x>CDةY(PԜӥ7mҡӺՠڢݶ?4!@IfM$el0: e e|oo ulw%A8PI~XSh.z8STw9 dH2!$'*-^/2"4567654<2$/3*%5p n۴fo؀דKөX{yѸC65ۡ.#k!#Ri*U+$)J (Y0h46)  f %lbJO@'US/p OR(i  V"%(,.124H5l67/642/K,M).%!K $`V݁%UqGf}; &Ә3B9xK6=[z0G-i o ,iw " 4&6^[8bY %Z seM!#&(+>-02$456p65420-I)2$3  #|bԀӗ/ҞрҠ8mجݳmHVA6q%'a S_Ui`G  uOU:>F]suT|vJ C <%S #'),/145P67]7,53i0-N)&"3 +t)XOאմԨqGӑ JՀ:ܔߝ\Jm@(X&C1\q  Cua"'%)K,/24T5P55432M0S.A+]'a"h Zjg<TӞ"c3׹؆٦tݾVXW9b*muUXln xW7; 4 =}7[MO@`i73" $ix!c$$&),/13a4555]431.*&/  rN5UެَGlVӸֿցׁ֟+7,s]d{`'*_~DI.C0 Rd3NS&LO  Z]&$+9lX>R :K!$'*i-/124$57 75@26.+\'j#vk `)fn DԻ\&Lڸ1g Gd!%HT=/HVdjJ n(j0L~> m W]=H+*c+Suwf_@L.h j z ruvoUGQ"%)',/.1/3*4-4 33209-+)% [y~&/l݊l`hBH-!(8܃S\WGrTiH=Xu 4 DmXYx.1 X|@mn6_^Yxyfi g '# %(+./0i23U4E4431.,S)%I bJ&߲ܮeذזGԚ_ӓ].ױ 44߱3 ruQQX6c%Q/S_ m|(x2  i{Hp3}uupFPZ) ; #&),>.{023I22q2210$-p*'|#H" %݋ڣyՔӹX+^J#Dަ}HS!U1nStuihk e:A.i I|6{Rs/vh^1 !$'E),.12g21100}/-b*b&=!`'Qzy~SԘөҼ҈,ӸC+[{<߉,:z8)A1vD Zp#?M *K " 7(pb1=Nn  >D,m(s0?zq W _^z!$'-)q+.p1#23210h/q-+H'L"b$! DRQߒ'aԬӼ֧BI ݺ34fY|&J}Y <J [5ml~u= 20fio/1g?Q&(;n+o6 c",!~$/&)+-/:011001/3,)%f # JL *E4ܞa{ oԔ-wWؤa:;6`6?TOk C$okpD VD>TR1  T3]0$+l3 f-~8 9Vv b htpk!`$['5),-///x/*.-,O*'R#R ] Pڭ׊4+B@lסڸۏH߮!-BVF,Obv\S5LY=} Dx!Q* i nOIfa[ mLdE8iW%.SqZ c8'!9$D'+),-z.////S/.L+'#s}Q'e߹F;ծԯ@A#sݙG}E84xU8i; $ ew7;CM L{gJ$\; = Fk0*!=) iYQ(-!$o&(*,v-/&/0T0 /;,)"% V {).۶lz-։+B&} ,Ek|(*{d;wO ]:+U v 8 % VOMIRCCsi7& rEA4 -2fQ 4e^!#&|) +o-..O/_//0-,g*3'x#8 e}ܺ9Hg\׃؆q M8GK87*-> w^mNW  eBOn}$F.a#6m T s@!Y$6')[*,,-)-F-!,*p(~%!m{h? Z_yH&6K 5ك1 NFIv/K > X<a"7O( E-D}D+.cl" = v J:g #v%')p+|,-%,r+*p(*%H"k'A "L9zF=]ַؤ c4/s# u #sO24\)QR 3LE0h}  oTP j@+d__wQU w z #g&'()m*+,v,7+:)'%" ZqO %D |0xic. 'M CsZMaZ% J1YF [/OY #^%()*+++V*A(&a# ZhB f K5E؎هڟۜ܂ݞ)u@Gm$~KAOd? 0cD02Dv Mm(o]\`~A,6HY gON 1x'!#g%'))*\*)"'&% "Jba;p+qRU ٷ.=C:puwI/{R~ [ % 8 HEt?v-}#| 4 I W8Ry8cE0< l*:uc aI I"$&4'(](Z('&u$#`!Sv #e(Yl,ݑDܧOp}S "_>m7._,6CzR{`$EF6( xD"t H.  8v@)lWy!y j,? b3I8 A < :Q*!C#l%x'&(#((P'j& $k"F O | @3}UeX^ܩ"TrT`12/CX'>~iGe. V0xQs2 ; >z2Pjec_YnfP& ]k8.xxi{  gPU?!R#9$&)'8''' %[#9 ! A>#M&]=(Q$Q޾>58M@9(@t9o6(5\I;J w KpI 4 6_#S.\O&rR"5 Bs-D j@z "$5%6%%%s$#" KJL ` !Jc)JF\d\BxT'{b d3)a[yp{ {(6)[ 2 c`&fW9*_-:h?nr !  $7Z]L!2"$$%3%+$#"y X;Y s'S*buW0Y]_=T,ea@m<0] 5 D #/ 1YQ [J' FvFTG6N6C&?n(   5^!"n#T####9! PvC jbG 84FcF%Q*Pwdy{<{7-y"L'OU%a{9 *Z: u SEZbiD@@Z]>\Ay/iN W m qVO\jiaW0 !"j"""!u{B L0 q'_(^H=9|?{X487SUHY !o5! XwY L.. rD!7[vXk NPJ/0ChbH; j J  !"""! $4k] wE.8aRhG )fRRFn8+w =/6Kdv K  p*jk ^ N , tw*As>N<8E+E#Jo1`  {]*Ku !L!!f lH ]6G%?c"LyDy8+q5v2VQUSnVP^A(*s+ k  k F(D v4-Mo:q;|< x@r0 s  ~*nDBh  ^ K}<ddN N7A^v#*9JN:>UI.3eSOV$ f! G Ud S h>&KgArfM5UE_W!9d#vQ A :67%h}Q:5 >5& 1[PM3&Bk4bHx j5#bp 1 m Khs=  U b K 91 Vw&w6gCl)SU?9; 6 4CyZM {B'C#Pyrp{e"F8 vt44BD:pRCz&E  > Z 4  A a p}sp4UuCA=4*xmr/  > Y 6H+5D2D> < )>eRjJK.(Zdq'!lP1h7$gVnL S Y   yE%)Pz1gc6O4lmu!J_p JnzYCW2bS8h     `  9^{?S~4 E; m?ch > d TcDksL}he$ E cOqYF{K~Ze."Ld$v?U}O%U \  _ N#UN nTVdS?') 7 bn;sWN[ JB(zX@dH!M c.  W*7qw$Uz71={  | .  ^ /)xgB[oH?E]zDJ>y  8 )EZ= 8;8]xv5 lBH 9yE3 Ns)G"3WYqb+  )  B r * @ bhki_MKnI'@A,xdi <  { S*hz6$;C3 L\@% _[v'7p%X5lE=3umq+!@{q 7  x (5;V=Qq;Loo68l4C C.9S}C"Zp D(p   C~V$ MWd~+^?h @;>^BQIuu{ I j [ m d u\jLHTl' Fb, (.2E ~ 'UaueZ1 XT9D4dtT$4O!k&^O?z +9`4#tnG5 > 8 " M b]E9'(d: 9v,S#lKP7 {D j{!x|[7 n U?5G!S1I-/]y~5Rq_ 2? (  f 4 $yi &`S Zz#w # h i;zzE R  *5]Wmah87+lR\M?d$-:\ W H  L eB8T~!uhIO;TiI_8 h  ?mYt/{P2 B2ZC>hWD2f}yquZ[*>q8T!3'rYq]   ] I   w  ' / QB/Qxw pNNWu qaL E w \<usY>\ -.PX i# FQ PJ'.bt{ V2}E|J/@#g5 ASi r | . d + ^ w|[-Dy#PYRJ )9wu7? < J)ahD%"s}[  |CeKvUTdM9;D1"Jo IghM a   E ' b  %USFr4|=A}m1C w X N!9<kzY @rr++yCDr"$6 #g o F8:=(dB@va H  B   T swignz$|Y"Nr\LNCm.&9Om>0 y  ak%K{. k3`:Xjc=dy-'8O#DLWIPmgazHYzi ( T 2 c 7 -OX8cgc:#a e!X"FM` j[~128WU/=OAF2f$)jyO )A ?_&HK8P  , h F  !0sH%WFD/q7!C>=e}E n Oo_`#G@h !S<+ 7;ca:R^z23 v?k1!6U  L r T 0 U 7 7 lZ_T*CKwu#V0jRx \@ U 2n E~oU kD ;zvSH?xS*Y$nwd**O+)4:J]V4Pw*L j 3 8 X "e-+Q^&Td eJ\~.t_UoW *h)]WOF"CC \:<-*W OK]A-e2=.Qw8Iou~962W s A # @.u/6.MIvm_ /c B  Yqx~vl V@W5?i(R3r'Gl]Lua>;>' P K { <  27% 3e1OsC Nb5L_d.9CX 8 e NLH+cd P (hC[HKoC6lT:]df;{ZO0Ehs9O O (  I *Ov;s${6c"S;_*Q.V!J ) / 1 > ` ume||=/  ]9[yHtE#LwFt]^IcoU]|!F. .I'zsV6ju a t X ^,bKTg gDG){wd"- L z e$z K \8w>0SScje=HF{6m~f3GRtV^i@  m { G P/C^U9@gRj%'{pE1S4G-146C]^B& > P b r qtf1l[~ n 4x ! 5UTQ\}%w;/d$l,\E sX.;  J6KO; X #U5tlFZ:v!p#a4#=wDI|PITQAAPYL:  {}   fWPUs]f92e1E-V>vrfUp#:$ldIpLF  9 -AsKcs6Q (k{hsmnS(  ] p&'. 2 9*~R =Ym7X'K BS2jF@ P` [INhHdO:\|W T[T@\U s56WI_DsY<.)"  w ? `" Ra >Gp/E 6a5 g4  W U   Bm^ 0 . f Iu Jo2LE%"t:2 %qQvIk6Y^DZJI51^yL~KJF* ?AVZ]%dL @ J * 4 .  Q e +tb0K-+d6hsZ$AzaYja[.GF4|u1j&=W}+rAOi8hTNMViQKEp1Bx- @ G ! s 4 : ^J4UErEk }~C/& ;agfng;X(X]JBoG;G]^.jo:|vw6@u Q?.#  X a 1Yg^I> \ {c0O85[*#jluz[QwOW"`r#V> HK7& Mvm-ja_&k e&Rj2mM3,`ysx-FO9V G | ZNkNRr>}QBCMQhMfepuLtq>^8uc+Y2I7OOF-u-2+L\"X%fD1(! $,F{#``wlN)JO;,l!@6)c)f"l~z6r>ZW?UY+ /q:7UnIDs(=[Y3\%q[KDCAJ^}4hihR4^5U .#QXD9`Xg},Bk j?ItL$`q;Uf:+@bL#p*m|>fy.VnH|LsaX\pd)h;_A~/z-i~k=~ .pG-&m]YB:Qa|KTagZ0kh.]xdgB sX7*SkrjN#w>};n4 qF~OXS.R>XR_8 iY1$c-qfXUm)v$cOmJa`H!g1;8 {E ,-#x>@Q&vP Q%3qxJ5RR5]"TifR/_0"P=.aL$ ;e*^i1SzyO],L?UEg-{Bd5a:g@" %Ds;EDMd2rBd}pU5m7Z)BuL5.&#.S[^ddJqN0 1YF G!& a.vW8nO3tllpz;u?Z @mO'5*jRm#[s9ze]XSL?9>QnQ=W1HW^WC!`I=>F^^'_hG'vV9~cH.&R.o+b2]&KmkB{<ocXy[A$3XQH -JddTF8|aPUg.e2[{z[?yX<$jO:#=d5s6b5f#:HNPI4{@=yfY+w[D1! +=M\v;~K !+2CPI8!rfj~2Z$@ZittocS<! gF'xcN7 %=Sn@x'Ns 6XwY~6;0[:! vf^_iv!Di=$07BOO?' 1Vy"5@FF=/  vaL5q\F3# "1DZt .Px(St%<Obq{{vb>k5n;y>sXA0" #Gi&O|>QVQMB.Bh   |hTB2#th^ULD;6104>IWm!?Zs;awM l4vS1 j`UJEC@>CCHSLDH[m"B^0Obhg[E( .@XuvhS>* ytohfgffhmv (B]r(;M\ipstzzvyylWC+g4 |cE) )F^!<LSXWOB. -CVhz|odVF5&~~9Tiz   sgW@#nUB6,% *?Vo 9IPVVM@2# (7BQ`ks}|oaSE7+   (4<EQ]lyzvrhZI2umaWNHB?>>>=;>AEIPZhx*17;>>7.&*7CMW`dedaZSLH@81*# #(-4;CJPVXXVSPLQPMTWMFE;200*$!&&#  &(**---+*($!   pyo/examples/snds/snd_4.aif0000644000175000017500000005316612652732202015146 0ustar tiagotiagoFORMVnAIFFCOMM+ @DSSNDVH}~~}}|}}vwllb^TPHE8:02,+&""'&$""##(+*,(-01-3.4,.37>?>?9@C?1*) !$,28BOWbjmnwydhkr %" +47"25&&DKB>:HE1.*@:1+9L?@7CFE4,).$$=KNBK[jVB073&,1=&'! |k`J5%&*!ro~}ubUNA-!  nYKIJ@<S]= *".MdpxHV\V Ok"P8oD@y=j1q+p ;T ,g  ? a  ( \ | ~ ! ? X k y w o Z 7    J  t 7  |G)pV5QE a` u-?AIb{4?m MTTM?rtGn!EEuWR\Kl`*-[&uP&<D]!q nq2,^Oi(Bm+  C$xa\2 "0E\-FD Q D T e 6  + * % U P@/6Pp>I5d;2G4nO+ef:! B7JuOt++OZAGFZ[ ] 9gZIGy5}$u%mB l 9 }?$(!HyYD'jS pF+%% v* ; Y C 2 huG{AzjCMb1v*1InF)aGbsw>Wr@dRb \stY5*;FR *GtNC|:MMOX%HLNkߖQޮޅUFܺF۱ٶ٨kzZW ٷ0ؙNw3Pb׷\.ڥJݤި߈k^7+[bOk(mgu . 1ks2? & @ ; I !#!H!"g# #c##$U$U###2""/!!J!=!! ! _E;xJwRa  &-w>=:i` ui#d?RI *ABZ;R-@5.1ilZt6koZaf3_wa KckeR{`8)ޔ^٢0~ ιo##R3ʱʁʧɁQ>Ɔ0ƢƉ#cǚ10ʱ9͓9ѧKlk O B'G2A+~#Z0 o $3gB:jei.!"$-%g&E&&&& %J$$:$ ###$e$$%$$9#S" Nnw*RG:h 5 u p O f .ueY6^'d{#  z=?8xmrlh$_"s!_ `hXHbJ,J\ @E~7)Dq<lPkro;JGMQ,"Pjߙކޛߨp3O?߮؏s;Ypmڋقo]*Ft;з[-jtΠζ7ͦ#Ȱ[ɢ4·99.]s΂Ҡԓַڏ:ݕޅ!%FR1&Ky    9Ua=@F 3S| !"^"y"g"/! !(!"'"#.#m#Z#""_! &km r t !]h3NfVO%s=Z:o6dTrS<y 3  <   DSJZ\c76X#|>v73VTPQ7nE 5 K-!"<#-$<%k&"&+%%>$#"t! ' ; !!t""#(###6""% s~Q80sy<Z F  ]Cc E s< ` J?Gg`]X'?yh/8u$Ws5ߡ4ۚ܏I}ޅcbs֒Q\ݐpmφ'˴<|{Ϗ̗țDŽǠɭ4ЁZfЌ@hP!!(`55DbE !UU?fl:k?Z ~!t"|#e$)$%F%V%&Z&}&&''+'m''&&%J$#"D! T=1*:14! h K _ [@";sIY'sa6""jaQBTu* GcS(AswZ}e'3.zy   c H "=>LCes\H90Gk:xGt'}Y#.Vfr`d |'LK% :}"V&'L&?#{lK$[( 0 hfv   Jc X jtA q 1^ '7*m{1 Oa?wcU۳ۯ3-ZAz(؍ά|מxݘ@/+lɇU%|HXp$cElTHa #:;qO?٥ڂXmۙ܈4ZYD0.x\fT,r} $ E+nEY,3 3 !!" "#% &S'7'(D(''&%1$ #k#"! ] "FSWR  f 7 U  NA )!f=z.x-]f(pCOEkI(<   Q ; " ` V E MP  xxy)] B d H^L[*@o.4(`q`'H^l6g?}c/j#Ma  ]  %  H,iF#e R%YWz {?JE/%ebwϭSO9ј@ ze&PYNЗGʙӮr>ҸΝˉXmɨɩtXgݴۍ(L8؜;ް, !_2xrfbR:r!e\tfaO"%( )'q"3 I Z P#'*Z(.!(j # ms BD V  ? 3VDx/  E L KuR|,E%_ !-i5֤ܲwN˴;m)f-V.-F'-~>mD_UPPxZζ3U{616 "_iGN%V,2QT J &R(7~ H s O1y "$1$$#F!.Dn T!"$3%&''C%#!QZ//eS# ' q ) 2ne^Ky)\'V@OE&n .}mM * * i xY  & 9 R Y  . s/ znS (9N Z N 4 'hK4_a eV-|6R]k^i 9 o}L  /  :~l%o,.+%A@R  js7iW!$ 9J4, QTO!!"#&aSd  N7<z Tiܕ֕s;0xhŀa۬ jA_0˗̑΁XܭX sr dYVT  EE= 4 9hlR; L ' Z 6-^#* S } V#! q k A,e$%!7# $ ('"Z S Gfy X!  @u?d OHg! g8Or&  FisGH HmJ7y 0(LQܾǟ - ӂ!mM 2Y*N<ˋĊMzt:u6R ޷VϭЩӕҲ[Ԍחٜ 2<*uUݱB,\/t& E;U&A 3   H,@gYM!!![{J7CbtS @ & gI N'CIZ@k%fP.Pco KaN ^  %PL) M ! f fI i:?}K d q91 H]"D1C 1  e~^3 C#Br]F[L>{pmg!koB  9u'{k:e!(" t Eubi4 o- >* K %!Y-t T.&W# j ^ܶڄ; V j~7)INۙ ZQ ԱkPplڜl=ļ7~ܱ׏&η[SCmϼVֲحEs*6ȿq#m^u[۫[ՋPۀޭ_vy(,0 :M S _|e u ^ # W'T["W##"${<M!2!! f'S S MnE " r,Y"4o#:!y. (B{!Jhv4 a S + 6 Yp ) mTD 0 % d a S ` ^ 3 iqZx L L [  C  l cIZqN<DtgchywR'p 5 gF W 2" !c8n` a ?W QC =P $ ?jJ Tl ?:B"6H:):j^1 H;kzpdaAL۬!;M7DލY{HgM'uAܰGwxSSTӏTKR˞׾$ϼԶףJ׳2ӔѨJIŠ%Ժ} g{U~v߯y@V_Y8 ox5Ae# "#$b#" V(=^XvVw6>t{# 1 a P L > lUQ$PnqRBcTF. r^H " @ ) " r ^ ) 8 N =m5>+-[ );=~Ax %pf7x>V {g=fE4u!x!M^}}TbC "/!TB-;1!%$!%;  Z\U Y Y K| Sw  L 'XL |aE:@nd\ٲr?a>Fބts͍6ثއ%hЧYǒ4%׫B2؆׸W#C|ǤZ}v8ʬG?\?V̵̩{ȡh70љg4݁+݂޲vj4;a G8$k"i%V(>*V+V+4*)?&$5! x'e !">"!\D\ S Z@Qybffi#X`]?Io%*  m:xEPEM)\JNGR-R Escw7/;! G 8  y # .xN | #m:0E6_3oG3F ""O"Q!Z  "$#[! !"#$$$"9M\!%%#xX> { "F h3 A Kk(@MgaC/BA3DMRc*aO)ޝڍނeIfbݐ*+Ԩ9}нHyJ0 aӸiѺvT(qe 3`ƾË1Ť$ҽC.= άԥYC6~pmE 1F)e k 6 #p#%@&(n*L***.*+{,8-$-.}.//.,V** ('M&&+%4$H$?$$V#!su N j0}(Y:p>"HQ*6 ;z@ ] I   !#%\%&S'('''3((<'()))***c('&}%B#r!6d9ofI %  6 APD_hB ]IG40FB" N m1D{m3 "#$$%&&' (*K++-Z./00h00/.,++]+0*))2)I('&%$#!=WePV h3l+Xa*c%.e5Y^c_tH@'NV(#m/nI-oٿܦ]Ԡ̉ȩANpj(жհFwPYi C[ֿ‘fǮӣqL979B 4jjy > !# %((+/35 68887P53210//x/U///s.n-[+) %~!y+(V G ={Z)%!(ގ]ܨ9݉/T=Ui~']D\ lx77 C!$&')x+c-a/ //....-,++,--D+***T)'%" %o6 JQ -W{ Ml1P0.--!,+*)S'&$#!  " 'W m*1f6/6 y^7:7oQZad4 !6KX4- 7؇ϻʑȆƌă59KUI0Ӭ«oo֫?1Kˢ+˦2ϬơșYρ!(رIz}, ?,I"0&,041688988,7666,5T4r4045c5u4b3$10A-)&T"FA =NXst&(&r&ݽ#uלל.Tմ U߭B-J _ * $&')+-.1.;.024456.777_6H4p1d.,*&'C$" \e4be R<09GJZN$F]u4 h 2 & \ K"$' (*,.02v4#566667F7754g33C2 0.g-,+Q(&%$V!|]<0Y R > 5;wa%Ho[j ? 9 h X$iBJ)&Oc*|q_0~i  Lcl,Oib!7^,5ߖLg֋[ԳА`8Ь:~ЩѢќe~Ј΁|˓r+ʚ4EȚ̛̏Y͟Y@SҼ_ RedwMFf~aхѭ~ҠԪPI Cs"& ).233T22S1/.-Y-7,4*t)t('&y$" hgWn) < ]X )6ؗP՗׏9qU;92\ , TH 6#_&)1+h-/1[11`0N/4.. ,*)1(_'&%#"] .Q #99?M~lM {7 ; kq%bT; !u#)&)**+m-f.--,,++^*(('''%$$$"#>~~ '1UM$t8x e x%;[ y 1CB3b !"!""###$h&'.'=';'(((P'\&%$#", "7 F0W  SO"E5p8WlcGCC<|tO3d'WށZ֓Էңнc IœÃRо{)9kX޸rrëSϰ;i8/ܬޚo|9 .V"e%%2$#%'(#)%+q.1234j5 4M2=00-)%"H mhF c BU~j9!ژڗں](*ۼۂVڊۚxh!UJ W""%a'@) +]-@-X,-F..-,+**h)(b''&$"E nsQ;(d3e=_. I}u qDm !!a!#J$%%%' ((h('&%9" C tk@4 %  @tK>TNtU'`G 4  ^ l@z}d% "d#q$&'2'j'(4)(('(((&S%1%&U%F"!.!!/h|lcTL  b < , 8s6m9f'GXr-PXhTQ#s=2p;ҢD ?ECWʾȼnjgÊjݿfU?Hg#2)'·ضڴdӹxθ{;r+j;fD^R##r!A #'k)<)())p****.'%$#$ " Ggf.H) #|y|g6 3{Zo  j)h^@"##%T'(L'')}*)m'O&"&%Q"*Q< T TE+6p C@jN$qXv]t|w@  Zvd|  >!!: h W`Zf\, , A e  F? 9  " KarR"Pn %!#Q$e$q$&&&,%%$##z$p$$###o"!!!g c[b@aOtNC#Q`xR i  ( m I{v?W:wacX>(&! XW#vB4W؇!7lͰvk[ ҤzͿV)t>Lǵ{UYfLVK*滬^ёGcݻ?C  N#%%%9$%f&'K'*E,..6.-,)'7%#Q+tG 7D*OݐnIF3>U$ 7}K- v k!7"$')*****) ( &$!m C PcX/rhhC<}|)K^ EaAyq : m  dgecYS?   Q 8 0sANr . B!ro~!!"v#$%%$%q&-%$$k%]&*%$#####/"!J "h7 }eqi5jtte p   Z,=-|j|BtJkCi\5K2\ce^t*S.]ISߣڴԫӤҪ ͞Ƀǔt7K61Ը gSlίۮ3ϦRܹѩ٨'v  $l()((Q()))_)*[*+,+*)('#  j/~x/k޲ݟܗeRRm܊a]\$@5Wdl ?bSi !"$')*`*,v--+1))a(%M!5? nm,^N+6\ctH9Ys @_ - gv7iO #e l! ! )|o]#gG R Y X y ;'-Uq  w aUO!P!" !X!T"###["`" "#Q#p#x#Y####g"" H$ggrU(C7Ocq3  N   7B1d>5i9[!_Wwc-x'<bN2'F3}&Tu:Ά͞S`7BK_ȳlMQJDлBGD9!xu0^Z;w фP%rb## VQP!Y"G!!#$Q$G$f&M)*q*i*+r*))(=&~$#/OG^ >UQ1ݏ'9v %sjo\O!) J|Yk"`% "%(X((O(6(W'&$"!r ] 5> Q'jZ ?F&y Ss H O2*fm C y @Hw\IJJ)Pm x w \ g\&  - ' U +  -%[-[^dl a>:H3 ? - O 7 / ZHBG?+ze5Y:Np>-'p:iq708uh[D8٤HXڱ5ثեԽ ~:ͫx@̀EʷFȿm5ʹ ?bRݔ;a C v  PL>q^_ 6 u/fY)w&~ 0 r }bcZ2p}|x  x V.C%WcaFCAY?dsJmS & 1^{b@  x 8 8{dY` uAg ; A J s [ R \nn C   F . 9 Y OA+.3T|8" Dl" #/O'%! -lM}GQb w9kr<}j~$-MN!S w+Wc60c_2=?7f]-O7! i ~ m5N49  8Z7Qvj^g++IGWD%CB fGBDpb4  )m?1D J u #RQ;c xLK R}vO Tzv{jT+2\xA6l%m>s5I_[W?bnaF*Y)  iO:Lt~y|WHEFUAEkrl`]UTH1  $Z( }2 fBK:)^*4jNG3rfpVe{b\> kliZC98";FQ]`s,Tp &LVf4r'Om.Um   yp^ZIJ<3-()%!%*./+.).'-'$#&*)%#**0--**+.(#""$##""%"$ pyo/examples/snds/snd_6.aif0000644000175000017500000005326612652732202015151 0ustar tiagotiagoFORMVAIFFCOMM+@@DSSNDV)5Bn cWvf)}R)#;r@h*3@%/8.p{r0XBnI_r&fE Xk*2/{rDz?B+hK!_}Id@]x5>n#UQ^{$NNC) wS-\|U2 D  u W O U 3 @Z y  { [G G dg w     Z S   9 ; )z+ ? &lmD [Z g@CIxeH. %Po(C"(OfMK;NhOR=2qu`C#hnz5! |-i- 8ݥgߑc^i \؏m>nIخӕշ%#Gje[(ipN^sxYC/~==" Q+smk!#u$L$ ""X#9%&i&''(f(e'&&%%%$$I$}%%P%$~##D"! %74LvD^  E(EAt GWp[-YKk}.! A0r q N  P"vxCz w"s%!''W%$$#"h"`#%&%&(a(8%#;"Y#$$X#C#%&$"!!0Gk&Q|Ft\ i e C / = $G|MaYQF%H+}#(]SlDLKuVS'!5}ݻ3'bٞ׍7 t׹K.*ȅ_>!rmJYwC8ŗÆEæJ(BW!҉ұ)$D  t T^y%L!#s$?$w$%l%&&~')**p*,q,+*+-l-W,;,Q--,+,{-i-++,<,l+)U())J'&v&D&&%H#""y!7U=EC;! sIZ  t O D;_OFk@q NFNitU*C\[y[޳ގ߹yNسת\ӷE~ԛ*ҢҼǯKSl*o8#!ԾQ, ,wŠO4u¡ĤƠɍ͌Ѧ9ΪЏӪ֢ڕߒ` ]zy-MXK` t Wkv0 A!"i$U(,O-,,-5-(+)),v...H/11R.,,-+)J'(*)*4)(''&$#~"!oSvoJ#G? 8 | {HW&dYM@P)Ezy,edY+9dUr9SC0 zy`@J }crlogS!#$c$*%4&'''''()**+,^,,,,----R,,-5,W**+,{+*G)**)(1'k'd'E&k%[$#"!!Q!+ 7_wp4!cs" 6  M NEzFK _ |U,ciia~v?O N+b܂ۙ<ْ7toԽժԎһ|X{%%/##$$$G$$G%q%#!^!!!EM(xvv>1B5` 5~D t  N ( )S?YwPP-BiV'L5="'%x bw]0`H8&|דSB% <+Ы=Ѝ͉zGaQ7‹3@0N/eIg|f {}ҷԃְڸҜTհ؉ݯ$$[~ n >9:(!#%%&1%%%''()+",-+,,-w--///,///!-,D*)^( &&'''&'f&$"-OX\H[ {t;@1";{ [0Dc]hPsA:_tki'Y|y\|# z \ C' }m$ZA RC !?"/NfY m!f##I"##$#7 !"x#" [!"8  A ;kOgp'| vsGQ\MuZ v e P 2  a C s >Hoa\;O3PXp#Yr '#-!h6^8GqNײyWԳ ҒM%TζV̜A:ˏ]=4T­|žTK+ྸRGȳyɶɻǓzɝBՍڭߍܧ$sWnp/Zdh S  DPX M!$t&C'&'H'J'7&z'&()*-....+-+I)9))*R*+-..,()&$!U0"hM|h}ZtF L o 4Rm9 KJ||wdN4DN\j\Jvr9(W * ;a ~4 6d0 E W!"!J  "!_}-sz'*:|9guh#Tg<s\.s^9 rZExN8 S J F : 6 M Hz@g$ ;><;i?L F߫5 yZ7ר|#Γ++N#ϑΆ̌Gő~q+2{ǯ]սh%µAk`KХ[\Bnʭڣ^$U~9=i 0]UOv }X O  A jEbx3"#"#V%;&$"X!##$g$o$r%(+7+%*,-+(&&&%$K"P":$%j%$#d#Q#u ! 2 A #kvPSc@y#J!`0E$l9 |N@o 4WCyCHyb_߃޲yޏߎݰMܜYoXڂٛO׻<)z+87؈Cץ)`FйкуѵѩԐԴԫ1ՈӶ}b/ԟՇץUڗ_hܧO3YYz'u| jL b Ue{`m/%)r"E&yX!Q`5t%6 < q ;o|X akN&R %dW6.>z9#,_Ewy 9xrF  2 y $ ( n  A s A $ J 5 Z j 3  w    n F   I ^ L [ [ Z i 8 a l @! ) 9_}UdFdd,< + D O |   ]  ? i : V24v{0sf%uw5lSn*Vrk3L!#%O3/-pC{beVoBigv^[J:E>^V)aS\RNzi.?UVoJ/oJZ^LL?'i9@"Qa^mP~  Y a Q + T k \ ? ~ ( K 1 < 5   F : ;  O h n z  H F  , x w  ^ N : M'k , [ ;: g q ` N `  \  { y w X 3 | > ! *  w  & O N f   l  ^ < P =7 } U g O8 $  Q  ` #  ; :     0 0   eq  E9  #i?r / % 7X n,dDT'C=<f!$T< 6XA,TGfLc94E{P5F U.J!M$,fN%gv~ 6|P2{$Bf9BsRwB9Nr7 7}C DW_`,lN6%l}]& DAE23Zbb'fawQ  c;RO \8YY+U#$Y :J a xI <   T (1 4C a $  n we^ m~ Cp 6 i ia }R A *&F4}awd dn Nq"U p4A % KF)-'!u=PKL_Al&^/Ew({ P,<'J r(xBH q5?j+T`EU!:hw #=%gUUJ};Hj0VHt]iL /0 s+g~fh p3 >f6Z,UW.oZqb (k/O; .}t+XK~D6 -5xMu99SHWb8 D} )hjjc tFqt kMgAJ<S$( 5H_pD9kU|MUXe=r;N ;  (g 1* i2# ;Q?m; :lx$[ =4T PFW jV -v< 0Q>,yjy`JG<a&QtGXiv,-A[wU2nCMnijuTZ[u*/V9  .a %ib&Wx>i@Rb8y5|rB'I2 %e 7 A jjIaU(e4,n]Z~S>gBVZFBmw$* Xo  O|><er Mw X* 6<  _SY%wcR .{$8w<Ki X*!e^ snTlb8x*^ C!Q.+b S,0W 0 jKw\PQZ%CH id~z0 XzJ6qSxqs_D']w U < >h% -JR(s kFn">S  I0JK^ Og:U|*oS)ElOM SI qJ>'6D>wp3  c2*cEpU[ ru q&8 If <V if .8[7_%! 2 Y~2 ls  p l C Fo}9 # V?? C& ~j N~~k ~aR 1qaN\@ Y |b^{*a+MViR 7D<-ST;Za(Y+L.Ri=b&~($':%P|- ,l# !I5Rj  S  qQQ 0 `9C[_bljS .qJ@g~S{B?Jh1\Xd KJ~y4 /L +u0<-K!m z:Nw*M `ng\|==9% xT9!? D%TS 4/QF~P_F|WsL;N w4r4  bO@C"M>V 0( = [s$JSX|I HA N e l=  xh ri#Ge i7A TPv "Qo|DQAlz\v!;(Jw)wblrFkU B4 1BS?p* \ v |J WC aJ q' SrI^PD4 & Q r:6u: wi fsZGD0x_7 4ZUfxox`#XP ! \  *c. ?-F5 G ?QLJ`C3lAw(A^;=3*eNY #M)uHb]IDE @ 9O<C }1CvRko3 ; ^nRvLj =t. DF=8F_+k#-pY' :rHdE c #I0 ,71Hn^{Q |P" <] _2H sFoA~~R frM <  %.7M4(h 42BsN2flYfp K C$" 4]-wZh;R^. 7 ?"  70 QK\VbYqh_V(L4lEe/ j0<dQ_g ;Sv/|<rx= OK DK 8sz W[ [ZRa ,` !~aOM[J )$2e 4 k"o a(BQut(Y a tP"K7y S% $1.e)Op lu_bAI1 -vrteg q hSMsn  K 1/K>A}0 Z{x] X "vJ; B } C 7},l 8~`i? <}Q'hT6n J  k $od .kmKuU@A^,8a qcl xoL{$Yk,PwY@ d/BQj6 2 %AP(/[3-WBmW%_> B!6$ Ax W6 _qq 3MjP?W{^ 1E > 6 L , 'H d RXa  #}U0sp'aT[   L *#.;H`  B;yl[iDHlI{y+X.VXIfzk ##  =M1z[C #F c S P"KNq|4]5- ,u 37 &P kI@! :g  AyU2_~/( 1 H0 mz {X l]X(v4\ H:W=-I Z bUlC e31 zly I [ I:vFx YgrPf&lpI T] h/0#L@tdG   r l <~R6@WJyT Q|% W  3N]`)P`kL i J yci4~$  AUk c lV  `~ Y e9~bf$[ E4 3z= f ?2i1 V3Z`  u ~XFB  Cl| B1TkM-p7  GKuon@% @_K}+! T0 -& L8e8S z h Z~Thye!tE CG- !3## L\ M+! :}`9 L .\ hSna=,y;:(4%!kf$Kg ~@2&E, c ?~!q e!eUF  Irn7D n0{mcLc    h-%^ T>. X"  Q [E /  i]>6U CHOioE x99Z [Qh5va`f}{ '5L $>_1,~ W 5 \ Ak c"Zc `{ `j/":R7>}R7KixF!"8IMnfE:AHGr@) Y"p_`a HPMQ^w" R7- l n^ >zlf (2 F' Ki7phy%! T[9^uA+-PmfUyWD& # AWUbj`h9HKd#^:(aZ}'͂"N4&QF Ƅi )l9?o<uׂ ?S!bW 1A=.T GPU!҆m<4!$3߉ ;"+ږ r1I(~/]m{ }(Kwx0 5;B/lbMH9$%yVEEt.܄e8/!=m׻#|Ld4 (2 2XS,/N4]o7"%NT0;TW GG p:( Kon3EU h9V%z=+!+;k%JY)dtV D&QX .! !N$&n g>u 5TF AK b %)z `w0 /;gظB,x ? 2yYETdl <f# 7k M9B  $   `9 38g[6l q2 A 5 {Z. ]'-F7ey  O^s&[$[?t a P( )[: {T_~m6$  UMH %mw )sB%v!+ ,}E*"d,L 5  J5 F  NO l_wT4{ \ pg zO 9 s,2#EO@  R>Saj |lGDet1"5 O _  < O gg  zV}Iv; ;s >|) ~S q Y w la p2ks9iw_pBRvO9*}'\) DiElQ7 = 65_f x! T EA~ P !F>[K S A p > y;x=   )QivJsE  WhR"<va9> qnE 8 [ YNHd  ( \ t# gU 4~Sel =/m&Q kf`(i d 2I 8 >y" = 6 '/jSSg&-)\Xkd5W6l u & Y M7Qw-/# ~U9{< 6@l'JVp x $ou@.hS}. )  o gH[] )  x  vc ,F09NI&+ V7 2 (92,]}Kt -<@^_-M{ L #^tH[gI0AMa^ Fl6+q_?t~b.F C-} yCjxa-*#_\oeuCngQZ itBI?lO'M \ y=`cAGEc"ut>"[( $PUrXf3w9z0PA 6{[4kI,{E j {&GCSI  `UOtRN?71'-qCao=u&34 bn6Log=}+2{8|:vCsMf-2:] x,2l+ @P/B9<s1D@#V[@jPu1h5Zr; S(;Cvt,  n }6V_1Pl<NtP. p892OoU@5Wu }<-+@ONt&'U"tU  Z*{v(v=D 5 PG5!|{l{sKH+u8L2c nLF(Q<y*#zKnHXW =>}Y,Ro}}6nL<g3ZL0ioUvjIN:=iL8>y>p4)Rs'PLF~a2 S__cZ31U[rn9_Ni`3gWa8_fg@5ngQYmiqWJ-B92+VJkU?Y%>;7Jo`(Z*j%\>0Gb#g DP5"-"QnCDT6TnTfzt2] +['1J>qQ\!$e-:]GBwf[=SH,ptNi-y.;v-  _t]'d%OY VN$tLp`|B`%StQg3:q\03 z3!+)4kM5_P\1EDc(( *ENVPsV8)9Z@GPD.bKm:M54V&:?( 3x%Al`L`/<,-~?s!%U NEiq4/h2=->rI1Tu* =,.Pf?Hc3r ?K$M$6ClKqD 7sQv(6d@'2o ,WCMV0,BQb+tCR_`?1sG%-IH/ _0jV@Bw%a=%][$%l/#rSAP$@r.ykG|RhF*&d+-@bG ;Q *]VbzY2P27]bFwL YSIAK d&`-~S[!dI\xLWJu .@4OJ1[{5\+:xe\) 7 q|iE>dcgFy;22u +8 }Xpe,K3 \nI>!f 1RK|-]d1/T"/ |6#G~t|;T}A3sZ|Y}->?YorF)}, @ yX$0mBXS_b"",@Bn u$Y]{'YQk 3#kWt,>q+j:#c}^R@ZM&M.+Q1*'[SuK4d`4+*G  T\-A{wk~ gQalI OL=14` HxAKWz /Zj\Dt4||X;/Z|K+I.Zlp^k vc*A" `U=(5-n]8e5bxbb.:jcCM9~x$Ir+8U@F}aq8:bj"A8YXZ-% ;OOV `fQ|)g^$9 A?4HcZ=E)@Ic"Jny6_qdm|`Wchsd[vM Oj|! +bs pLeT@VMDdw9Pq[avZPzsO54(cqN0a63J+<[Kam0/t2TyG).RI SnB+/!94pgD]#x)Xq|n>d9=Bl6d`Ycmp #;0Q{Ls e{`852G}\{. ^D-w:.7XiQ" 5F34DNHxaNnovr>?1CH>ly0=#+fnMi}zLBWme`tS "$5p~E7Om{$PwwuB\pfS4]; =9Sy< D|cdrm\MJL}S Xjf^1 AVR0@}"C&4KB !0?9*,-(C]&ke8USR'5|c4& % QF#Qidxyld9UFtJDS<lg =3GTLowbb? *]]F=XpQ:@D7)*S`:'WQ ")0A9+$NRto4 3X;%F,W4t2@TM 5xh|a \ltmUebF#H/Osx.d+v dr_->~!#'| &#mw-OX="% Wg$t %;-3LeG !2) 68GMGbe6P}qUVMA6!D^cL*0LA4R|ltm[IB[rGQ !!<jz~~}w}qFJr{rjkm='YYd_HU]TF@,5fptJC[S9"$@7##&$SvQ?Re{iykPUJ0Ed[/  ,Z`PXZ;">_S1% )-*&?chTRhzyE*KbDK`;$!.5KYNQV9(EyqTT^WZxttweloPqwK,?`o]Xkny  ->!* !' )B+ ! v^ 18%}~ +/}spvrsZTx 3>  %<;>0 6 %&%$2':NMGGEHGKLN[Q5''4??FPI%?UJJF8(7A<:DMDT[F# <TSRM8 !&0<Ij|[<<GONLSXf}e^][VSPJTVKLdY$' #E]a^hyg9#:a`[UD@@ (82$  (' (05FM@ +1) 69' <Uhouq^C'#17/)1% !  5)"44&    ! #AG:.0-!'=> '-7CZeU//bpu_USROO[vx}yjykwxqu{qenqc^]]\lqffm}qbqzp~~hnoXUdvyie~tfzkT]hcx~qaad_QSj{si_aQ@DY]SKC6($?XktX<@]fdWG>AMbmswqrh^hxngq~gS^rwcTNerf\hyuYFTpxWZrqwvlhpl]MB;3<L[_pqTN^tuieo{mbPTo{_Q]qN90>Xu|y|rWWnseUQcyxlv#  !   {xws}   #<DB5# !,:B@4,**'1<;1! 0IUPA;@C?- (CC$  "     *3(  (HR>    ,0%      "  ""!!   &-% '46*08=4)"',/6>?:58@EKQLU]`QEAACC=66BSVNDA2*.69=>4+'!#1;4.0<FLPMJJMUVK2"!.@HNPROB3,/7953>FA86@E:"%!0-  !"  &4=5) !!%%   #0,'"&/51'#+.(        &#%      %'! !'*&./-    0962(""&%! $3:?A@80," %.9<?@A6'$(,(()+0473//-5?HIB>53330)).3;AD@EI=4/11/" & !*225:@<2& #/1//064+!""-328?@80*,.."#'      "       #   *+""  !"         %0&  "'+,& (!  "&%!#%#'*        |vty}yvld`cbadenuzyuvy{}vuw}||~~|zwqpqniiebae_bmz{wsljifa]biijnqrlgaacelpsqjfgeijonmkfdbhkooklpppomedcgljc``hqxsmkgab^aadfgjigisvslfgjqtspppmiedfjgjhfcda_[]cad_^bcbagijg``dhgjkiknpnijklqttrqrx{pmhijmkkjkgkigfisvnjihgdfiqpmjoswxyx{xxvvvurjifefknmjgdfd]`emolqpppooopsqnmkprtttuwokfedgjmompsuurrookic_`feba_Y]]]YTMNNTVZY\]]de`[ZZ[`aaaaaeg``\[VUV\^dcc[WXTPLKJLRX\ZSPILPNIFACGFIGFDDEEFGEECA>DIPQGE>9422012,,58?98::73..-...+/./4776////1//-**,/-1274.((,./230)%(-5213886341-,),,..--()()(##')+..-%'&%(06855582...0/.-4?DC<:78<>@?=6.&',3278<:64991.*(&"$&)-/521/.-./,+/79640-'" *+&$$&$#$'(%"##$&(%$# '*15?CA<9:;98625<@C<30.+*/00-,'&(*(+.-,.24<>>882/+('),*-./,+)&)*+$!!%&&('',*+)% !#$$$'+'"#!          }{}}zzwvswyz}||zzxusroqptwtwwxv{{xwuqqlljlkmorqpnmnonsuvzzvvsnlmnrqsuqqostyussuqnljllooooonorrpnnnprusqnlkmnnnkjmkjihhilpomheddjmqppkkhjgikqnniiljkmnnprvsusnljkkjinmnkjloqtqnprtssqqtsssrvtsqqpqqptstpqsqqqtvwxtqmnnrssnolmrrruxy{~{yxz{}|z||{|wuqrqrwvyuqpopqtvzx|}|}{wtvqomoljjmlnlijkmppolnnmmqpookkgghmklmllimlnrtqronmonqsutxv{xvurttsutspqmmppnrstspmkmkmlkokllmqllgdabaefiihf`]`^_]__\^]`ba`[Z^_`_d`a`]]]^aadb`a^b`bbba^[ZZ[YZ[X\^[[\\ZYZY[]_`a__]]]_`_^WUOMOPQVVWWYWXXWWVWYXUUSSQPNNNRSUUQPPOPSSSVSXWYYXVXUXUY\_`^]]^`\^^]\XXSXX[^__^]\]][[YTRRTTWWTTSNRPPRTUZ]\aa_\[WZX[\_`bbaea_`^`]`a_\_acfdccbabbbdfdfccbdead`cbcccfddhjjgedcbbcbda`_`_\\\]bfgcbebdc`ab_bbcdda]_]a``a`eedcdeaa^`[a`aaaegfhgfegcbeb`bbbgghdecb`ddehjjhdeedb_]^\^__[]\\]\\ZXVXYWZ[Z^]`b_\^_`a_baccbba`b_```caa`\_``a_[\ZZZ[]YWYYXTSOOOQRTUXWXXRTQOLNLNQPVVYXWUTSTTVUY\]^[\][XUTSQQOSYXZXYWWXXYWXWTTVWVXUQQNPRRVU\XWXWZXZVXUSPQPOPORSTUUTVSQQQSSUWUWVTUURQRQTURUXVYYZYUUUVXVWW\ZZWWUWWXXY[_^`b``a_`a^]^\][[ZZYWZ]\]\ZVTQORUWXYXXUSRRTUW[Z_``bcfbecdcb_abedcfcefhdbbb_cddhhkllqqnoollihhdedheffecb_`_egggddcbc___abcffdfdb^_[[[^\^`]`^abddgcc^^[^cafggkkjifefcdcbfhfghfgdcdddbcdcdccceb_b`_`ba_a``]b_b^[[][\Z][\\ZZWWXUWXX[Z[[ZZXYY^_]]_[[Z\[\[[\]\\^]]]^`a_b_bcac`a]][Z]Z]`^]`\]]YXXWXXY[YVVXVXVVUTVZ\\_Z][ZZZ[[^__a`_^`__bdbcaa^_`_eceegbdb``\`^_`_dcdege_`^Z[[\bfggdccacaa`aaeccdacadcehfgeeba_]\]acgggihhhiijlgjgklmmqpsrpsrvsonmmonrqqpprorpptttrpomkljijljosqpsprplklonrrrvsttrssqwxyvxuuvvwvyywyvywvxyzx{yzzy{{{{zz{z{zxyyyy{{zvwsvtxvsurpprsutvttuvvwwwwyzzwxvuvvuuvvvxxxwwyzy{{y}{z{{}~~|~}||y{}}{{zxvyyywwuvuwuwuvwuswwzzxzwxuwtqtppnpssswtuuuttrsqpqqrustuz{{~|yuuyyz}~}~||}~|z|{{xyzwwxz|yxyyvxuutsuuxvytprprustvwxzxwvxvyzy}|}{}}                   #!#$$#" "!!!!"! #$#!"# !!$#""#"$!$"%###"$#"$&$%&$$$&#"##%$%$'%&)&)'+('))'(()**((('('))'()**(***(,)+,*++,**+,-/.10001/1/1../.0/-11-0100111220334222213131323434342334233334253233122222043443212/1-/./..001001311///...00212001/1--/.,--0.0022431210/..//0002121/01/121123220./.,..0/2-/...1/01/0/.01./-./,00121001001010/112242434423324433546625336476857858545121.1/1/022306320211220010/0001223513635536574656564548767878576766776878:77776:448669;:88876486475788989:9;8999;9;99::9<=:;><>=;;<=<@?@???>?AA?@>??@=?>ABCDCCFFEDGFFGDHGGFEDCDCDCDECECFCDDCCECCCABBEDBECCADBCAAA???A>?A@A@@BBACACAAA?A@B@A@?CA@@B@?@BBDABCCB@AABA@@??>?>????@@A>@=?>?@B?@ABA=?ACAABDDA@@B@B?AAA?BCBAAADBB?AD?A@?>???>B>@=?>==>>??AA@ABC?AA>?>==>@>>>@=A@@<><<><>=@>>?B@@>B?@A@@CABBB@DCDCEBECA@ABBADFDCEDCDDCDDCDEDEFCGDGCCCAECBCFCEFGGFGHEFDFGDHEEEFHHIHIHHGFGGFGIHHJKJJKJIKKLNMNPOOOONOPQNPPRQPRRQQQSQRQQPQRPQROONPQQPTQVTSRTQROPNSNOPRPRSQSSSQSRRSOTRRVRTVUWVUUUUUWVUUTUTUSTVUWTTTTSTURTRTTTSUSTSSRQTRRRQPSQRSTSVSTSRQPPONORQQQQQROOOOORPRSQQOQPOPNQRPSQTSRSSTRTRSSRTTWSUSVVWTTURRMQOPORPQQRNNQNONMMOMMMMNPMNPOOPNLPMMOLNOLNNNLNNLNPOPONMNMLKLKIMNMMNLOLMMKNLLMLMKMNMMNMKLMMLLLNKKLJJMKKKJKKIJLJLIIMLLJILJJINLNMOOMNMNNLONMOQRPQQRRPQQPQRSTPRTSRRQSSQQSRPRTSWTSTUSSQRTQQQRRSTRTQTQPRRRSTQTSPQQRORSQUTSUSRRSQSSSSSQTQQQSSVTWVVUUVWTVUVWXYXVYTWVVUWUYWXVVWWTYWUVUVWUUVVVTWUSXTUTUSWUWUVWVTTVUUWVVUWVXWWWWVWUUTUURTRRRRRSRURUSTUTSTUSSRRTRRSSTTSRSSQSRSRUSUUSURRSPSTRSSQSRRTRSUQUTSTQRRSSTTUTVUWVVVTVUVVWXXWXWVVTURTSSRTWSTUTRTQSSSQQQRPRNRQPPQQPPROMQPNQOORROQPRNOOOOPNQNOPOPOQSOPQQSRTRSSRQSQSRRSQRRRQSUSSRTQSPRQQQORQRSQSSROPNQOOPTQQRQQPNPNQPQRQSSRTRPPRRRSRSSTSTTSURSTSTSRRTSRVSUSVTVUWSUSUUWVURTUUSVSUSWTTVVSTTTRSTSSTUSTVUUSSRRUSTVSSTSSTRQOSRSTQTTURSSPSPPQRPRQTRUUQRSSRSQRQQQQRRTQRSQQQQPSQRQSOQRQQPQPNNPNOPORQNOPOROOOQQQQPTRSROOQQNPNOQONQRQPOOQOOPOPOQOOMNOMNMOPMNMOMOMNNMNMNNMNPMOPOOOMONNLOMNMNNNJMJMMMKMLKJJKIMKMLNPLKMIKLJJKJLKHMLLMMMNMKNKLKJJKLKJHIJJKHJIGHIIJGKJKJKKIKKILJJKIJIGKKKLLLLKKLIJLJKJJJJLKJJMLKMKLLONKMMNNMNMMOMMMOONOLMKNKMNMJPMLLMKNKLLLMMKKOLLLMKKLKLILKMKMKKMKMMMKMLLLKLLLMKLKONMLLJJIKIKJIJKIIKJKHHGFHFGHFEHGHDHGEEFFEDGEDEGGIEFFEEGEDGFEEFDCDDAEBECGCDCEDAEBCDDEEEEFBDEDBCEDBDFDDFFFCDEDBDGBECBDCBDBDBBBCACBDBBB@DBBABCDBEACBAC?ABCBAA?@A@AA@A??=B@@@@A?B=>@>AAA@AC?AB@AC@@B@CA@EB?C?BACABAC@@AB?A@?B>AA?B@BA?CAA?A?===?>?A???@>@=@>@>>?@@>A@@@A?>?>@>@A?>?@@B>??>???=?B@A=?@A@?@=@@=@;?>?AA@A@BBABBCAAA@BA@A@@BCBC?CABCAACBAB@@B@A?B?@@B@A@???=??A>A???=<?<==<?:;;;;9::;9;;=:=;;<<;;<==><==;;<<;;;=::;9<<;=;;><<=<=9;;9:::9;:9::::9:::9:;:7:8897999:8:797:9:8798888879766889797766976987766777776588686666867456546388857736434325223121001003/101.113/2/1010./21/0.02-1//..../-1/01.0/01//..//00//./-0.1-..2-/+.-,,-/-/.,,,.*,,./--.,--++--,--,.----//-/..0//1.1./1-/.1/.-...1.1/0/10/300.0.0//00./30/////.-1.1/0001/0/1..///00/0-/-,.+/--0-./0.0./0/.//-..-./,0.-/,//+/.,.0.--0+---++-,-.+.-++,)*+*))**)*)*(('((((&(&')%'(%((%&())'')$)''&&'%'(%'%'&&'$$%$&&&$$&%$%$&##$%$%%#%$&%$'%$&%#$%#&#&#"%$%#&"#"$""#!"!!" !                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              pyo/examples/snds/alum2.wav0000644000175000017500000021277212652732202015215 0ustar tiagotiagoRIFFWAVEfmt DXdataADAABBCBBBBBCBBACDBCBCBBBA@A@??>A9?1<h ^mNVhBv)@`& C[/P`ܢ;ߚ߯۰sT[,c S+4z%IC;ތzBI"'TetȄάѱaمԐ>Ӻ)tҽ_~mςڄAH!+Ӕ2J-LLrߌm7>6Sm|P @کo q & {2-{<>LP.KD p6--z(Do?w4@0XfY8<,U-E2!O8I>^'<H \ 1`2 &Ոiݞ܄sB+rw^(,D WRki,؍wיȼf0&+VS}du!S V[ 'mZw75 zԶ#[̩|[&ҡ{ }UA# s!v? CQ x-TR*({f[٠ ݞ mcKX: ­ R9 9Y7Pɹދ,n&(  \/Vkڍ6^ձ[Np4q͊sȋ aL oKӼ' >:_ w8*N  TzTLXo 5$!! (/ _LSV+d"\wц6گS,(f wJXE%,[3 s704#Bp]| } z@cD  lCM_ g h}@  |8mK"M$dr'c+c 9 1 w{ c%VX(. d*lt t wDk$Kb 3<TP/6ox|nIu2#k*#$a3NE 7Jj# t~Vzi)* _T #` %DX Sw~" >8\ j= J@g6]y@jD b)4kL  Z$ : ~dgF Q=|,EnkG G4 U8 aj3 -@9,- " } %p? + %H u{KV  `QKK 0Epm g)a -dl + l jcuW`Es w.5(  n \7C  K _p^`    & Z ~d w]3 C } _+ O@Wp{  x/.8-  b3} <U BWMc  6" <|1eDRwD = \ _ h j Dj60- 5  Sd +1b  ro ' ^f;S 7 * Vjpn[0 & N 3  P |>#'K:P' Z9 j ?~ `PW@ E+ G: F jXiMI FNV  z&~/Q @!e` cax}Ji(L<hZ ( l a,y/ } n  NQn8R D  Hnh ! 7  Ej/  $ 2 Mnb6 ~  kBnY xIio=q!r~Hn pC  l3 gQ ?bp 9Rx=?3  Ga// +@> qcTaMHXf< :Oh(r }= n J Q [d *  7|B>UXN  4.nnp$ b$eKv !F"{~tF92F|#   7c>=8tNENt "UV3 @ kq z /S7(2"d  CR' L P 0q1 ^ 9Z?YS`0:IF`C_#6 PD260[@X5`<v}T<mOcQ oS4X;|r7eNY~&:{lZ W"1e_mT5Dj,-rsQQ.Cn' kD +Q*(]#z!e l :NUG2N\jrk /eJ# >m~7sN$ V+,ycz [ 38s# #  'R<oS>dYFBR9H,(/)lJj}VnK !<?%@): (fQI<9]Rx*NaF ;tgG&.#|FTy#D1/?+|U0 HU* S1WZMbMlnkRO& a|LZPJailLSYd\Q2iqgK#4,yO)O9FIaK%$Epx7Jt6m8~TUg}tB|a ~(s#$WFt 6"=F)8(;~LJB] 79 9JW)wINsp)])F\]%7  ,5gnBf T/TLoZG8|*P>nd3{<?.b bZuPKa|R pea WZeM}%!@jMq9o;Hs'hW6&??8<K_wNy),Ue^~f#+_u\5vqN# $% Fw #^R  9sd ^&.|8G/px<fO~R2=D5 1fZ<"\(Pqw>-z(|m? Z 0<*j<cH0CP8I;T@^z=)h[bn'^-d_'F}%;j]RN43t)%^]E*$IA_GLZ8< g /B#]VxPT/kygiz4 >CTeF Tjnog"b"4:o2lyn=1KY3% +?(fvByBi."=G8adsY}cR|k:|]d3=jsj p' 1^4%?^xMo\DMiqZmq>C)&9#(YsAId. K"UeT>d&S$-,T+@CP"Pl{,67 |0?xe='/IKa{om3_.;'K_IfPC^p]L 6RWMZ7l? $8\q4<&^O_J\RoP@q2 zA5@{m3iR\aQ6wL@P6gyG0"<  vD=}nTtX<36TNU%@D7}psz47 ]Y&V^i3&&s^O.Om|t7'!m,lVC'Q?#oV?4y>%Hd0,IkRW0"nz>(b>L'ur`#v $ P^8 3Z ;/iG )k9N69EI8A10AXAs ba`I, bFDk a& (6KwedQ=Lh[7>>pmEx!R]M E}H 4<t}zn{Us)^>ts:8Qe(e|t~1!=&_kC x:0*Hg2!Ti#LB5dy09cy;Y#3"d 2j`zdA$ AELP7SuFc2 .^lb|J.>P3 of_oa08+^Fs/UV`AIV*(G{q>Q\wDI2UAe5iQs/>qH#<J!S8wZ.@hr= ,Oyw<$>5|hY86J=4' M!I ! <4#ZG @jvZ^>6cgfaa^PQ:O;^P6-2.Pq^5F%p,85P#3/2&:TH& ,Q==LHQH7YgVkvHLiwqgoJGeK0 /rHh1_^`ZMa)eoml? uuK8J8 $WHGJC` VOKK[\q~YMftsD0Hfzh,C^}tcQ?Rp**>nX ]:WJ9 5B21: yH !89892AcnT2&%3EB*'EXUC6kgmW4Bav 0RT*.K7.QG.0Xs|6l'CWoe/+.+$)RO, -IG}VnPznU9MTkN>J`M.2=02Vp xppw_GLA yc6DgwcBG_pn3[O. #%+QXI$ -'7QU9M~p[hcLhPd9Ch^J@- ;eoS1pJRkmM1+ /LD,2(l^m~kQBID!d2wibkmU2C6H|&AT_bC!1":amgN21Fgz}peaZORP% +CZ`Z^njl~sI( 2>8=KH1!/S\E4) 5Rhxl`PE" 3IOSPaqY?BSR6&J   "&  )+&2V{xqj|lQ, |~u`byzt~}umiUB80"{ "$*24CZfk\PXm~lOHB930. "$ 0LRRNPSWm ;M8zyg`ltpopaW[dbZMIWaXXmztiacigqzw:VjmyeNZxp^N\w|{plmodTH?5/84+{bV<  0KdhXIFMi  !9WeUIPxubH+%|w~w#  !1,$27<1#$2CLSUUL=4,&  ;_yyq]RWfgid^QB4.:D>83<<:DRTJD<5/3,vihocWRH@:62131=P[`_`l'@Vetukqwjhk\LNVWM:.0?EIQfvlT:-)'0GXYMGE>8Nbpzw^QTVTRLG;*ogebXKNWY_ecUC4("")089668-! ).8ESVX_mrswz!3ESY^cdju|  ,773215,stussoz~|tjd^QD@:."%(raUC7)""!$+9MY\^`^\hz "&.724=JD72:;?:4*-9CMQVamztmcYC9.)" pcYJABG?1 "$ &6FYjnpuzy)+/;IUeu (5GVkwwtsxzwhYRMF8,(+(&sc_\SLG<( !-4*  #*5<<:6@MUYdpz~}yphmv}wsv{wj[PMVfornj\L8/*$    2>GMYdposty !)8HV`_\Y[\`cjgb^[Z\UOPTRLA9+ }wuh\L@;9BDFA>=5-##-6:<?BGIMVckt||xulhd`^]`mxztmf`VF:61)()*,+*$ ,==>ISXYhy(057<CHMXjx{}vu{zokhhbcgqwvvuvyvpg^RE>9<6/+,$xqrsomnortsngYOG?:- $&/<K[l{ #+0.0.$&+,$ |uj^RF=74.-'(#! "')*-+2>L\gnu /?GMV^ky |vlaOE??80(! zvvmbZY[XQSTOGBB;84.-&!  1EZo#)6?FIFDCB<9>BEJJIHD@?84-+*1:@HOOICCAEGFB;=EOPRSQLFGD>:1+tlfbb`WH@70)  "##$ "%"!#(/69<@FKINOTT[doz '6DMX_h|  {vm^RJE;70(wof`XRQKIJHIHPUV\_dcc]UPSTRNH9+   +;GWfu  ##!"(/7=?B@CBCFHLMMLKQONIINPORRQRTTY[^a]YRKD;2*&! {yz|zusomnqrvxwx||{~| #&1>KVcuxtpkjjif\TOFE<6/&! ~wllmle\SROPQOIEC<:;><83/-+*&$! !*05427BHNKNLQQX^ejqsukkgmy#+2:@BEFILPUYZYW\\cee`YWX_flvy}{|ytpmkniicba`]ZSRF:,  "/559BM\iwwnfa[TPJID@;32.0)"      zpjb`^ZVVRPMJNNPKB;721'" #!""#%#""! &+/14<AFHNQRV^agknuwy| "'/559<AFIIKT^afknmollgeejnrtrqsoha\XPJDFBBA;2&   "(,07ACADKS[]cfhedddgb`^_[XRONOLD?>=:4,&zskbYPH=51)("  '/29>DLPVW[\_cku~ "#"&$$" #()*'(.279<<?AA><:8=?;<9::>=<:8421+)%&  zxsolljd`ZWUQNG>60*%" ),.35:>AFJOTXajpu{| "#(+./0001/+%      }{xtrsmkhfd`ZWWUWVURUUUQOSWVXY^^bciorw}}xphbZTLGD=87850,&$!   )0:CMVchtz  &+2:??CCDEBDDFGIKIGGDA>;:6992+%" }ysmib_^WQLJIHGFD?;9530,&%!#'&%  %.4:?GLX_ju{{xunfaXNH?73-'# yzwttwy} !-8EQ]is~ "&/19=@EIMPUY\`efhfeedfcefigec^TPHIMMIIC@<3+# xne_YQJD;3)#/8AGTYblx{pf\TGC6-$)3BQYalt| !$+,./33323/11022320..*%%  umc[OH@3,! }|zzvplfc`dbdfjimpoqnrtw!$-8=GMS\`iow||vvnlc[SNF?:2)&  &*49<BHJSU\]belosvy~~ztrhf^VPH@;62,$ {vqqooqrqvtxx| %-27=@@CDFGGIHGCFEEGGECCCB@?@?>>?BAAADEEFKKLOONQPOOJHFGDA>=;97641-+*$"    (,045=?DEHHMLRU[_dghhkhijjnqvvxyw{y}||~}ysjd\TLB>3-%  }zwrnkfda_``_`behjpuz|#*.69AHOTX[`ehpvy}{{~|}~}|zxurqmkidda`[\VUSQOJGEEBA?<:832,*('%!#  !(,138:BCKPTUZ\^bcghpsvx{}}upjb`YTKE<3*! ~yumkec]YXVUTQLJGEDDCDBADCCCECFFJKJNPRPTTZ^bgmt{%'.69?FIORVX]^adgkoptvz|y|~|}xsrnlihb_YTSMMGFDBB>>?==;:75110-)(((&%   "*/9AIPV[bflrw}~zxsojg`_ZVSLLIF?70'  {wrnhedaa_][_ZXXTPNMKNNOOPRSRUSVTWYZZ]`bgflqt{ #%')+-.227:<@DFIMQT\`elmt{~|{xvqkgd]]WSOOKHD>:62.*%" &,59>EKPRZ\aehlknpqrutrroorqruustusopnmmkgdc_^ZVSOIE?:5.)!zxtsqmmkikhhgfffdddeeghkkknptu{"$'/04:<@DJKOPVV[_`dihllprsuz|{xwpmkcaYVOJFA=81-($  #%,.47:?BFHGKKMQPTVUZ[\`_`c_c^a^_^^`^_][WVPOLKHC@?=:62.'# ~{vtqliefbc`_`^]Z\^Z]ZWUWXWY[]__babcfiloqw|  &-2:<DINT[aflrw}~xqkd]VQIB:2+" yxutrpnmjiffedcedghlmosux|~ #&,.4678:?@FGJLNRRUVY\_`acdehgiijihkihhecba]ZYURONNKGC>940+%# {vqmlhedca``^]\^\[[]Z]\^abbdcehhlnpsstuyz} "%,4;AGMSX^ejntx|}yqkc]UPGC:5.(# |xvuqqmmigfbcededcghgjknquvy| &&*,0355777:;??BABBECEECCECEDCCA?>=;88876241.,'$#  }{urqmplllkmllmopqswz{ %*/6;AFLQU\_ejmpvw{~ywtoldaYXPLD?62*$~~~}}|y{xzz|~ "&&)+,-1/1223766652/0/..+)&$# &-/8<CHMQT\`fglpttz{{zxtqnjhdc]XSQLHGB>940-%" yxrnkiec``][YYYXYXZW[[^^bbdfimnqvw~ "'(-10359:<@@BDEEJJIMLOPRPSRTTRUUTRRONLIEB@=:640,&% ~zxwttsoonlnmnnomqprttvwx{~ !'/38?FOSZ_gnsw{|xtnhc]YOLGA;6-+# {tpmke`^YTRLHFEC@??>:;99999<950(" ~|xyusuqqooonopruuxz| %+/5:?DJMQTXZ^cfeikillmnplmkjkjigebc_^[YVVRPMIGA@;740*($ ~xwuqnjgeb^\YWUTPMNKHHFFDCCD@BDBEEHIMPRYZacijrwz &-27;>EILKQRUWY\]]cbchgjiljjhidddcaa^[\WUSPKHD@>83-($ ! " ! ~~{y{vvutturssprqqpqqsuuyx}} "%'(/.044389:8;<;=;999867312.0,++&'"# }xurokiedc_^]^[\\\\_^`bedgjklosvz{ #(*.367:;=ABCEFGKJLLNQPRQSTTTSSQRQQPLKKJGBC>:760-)$" }}yywwvvuurtttuwxy{}} ""&''+*../.100/20/1../,*&(%#!! }{vupkjfca^[XTSQPLLLKHHIKJMKMPPTUZ\afkmtw| #&.16:?DHLOTWZ^^adehjlmmpooqpsprpqrqnpmljkfgdb`\ZYUQMJGB<871-)"! }yxqonkifedbbbab^`_]_]\^_`^abcdgeeijmosuy"%(,148<@DFHKMMNPOQNOONMLJHGCBB<<8511+)%  {zvtpllheeb__]^[ZYVYVYXZZ[]a`cgfloqty| !&-27;BGILPUXZ]^acbgegeghhhhihgheb`b_^[[YVUURNKJGEC?=995500()"! ||xvtqrpmnkljkllkmjmooppprtwux{{ ##(*,.3459:=@>ACCCEFFDDEDE??>=8632+*'"  "%*-367;?CEHKLOORTVWWWYXZWWWWUUSRRPLMIHEFBA==;87530,+'%" }|}|{zzxwzyxzyz}{~ "%+/45:=?CEGHILMNPOPQQQQNPOLKKHGEB?<;760/*&$" }~ !#)+-1288<<@AFFHKNOOQRTSTWWYY[\Y\Y\ZXZXWYWUTRPOLLLGEB??9843/0)(# ~zwwtsqppnnlllllkkmnonqrruvx|~ %+/47=BDHLORXV\]^cbgeeggggfgddaa^[\WUQONJGDA=8540,*&!  "%&)++.024778;<>=A@BCEFEIGJGKKJLNMLNKMOLNJMIHIFDC??;:663..)&$ |zxusspqsprpssuuvx|} !"'*.0338:=>BCDFHJLLONNPRQOOQNOLMLKIIGGDCA?=99330++'"    !$'(*-.0011244557588:9898875633/10.*+(''"%!    !!#$&'&++*.,-0.0./-/./.0/.0--./,./---,+-**(''(&#%   #%&&*,0004567899998:67674220.,+)&#!  #%'+./34:9<>@ACCDEIHJHIHIHIHGGIFFFFEDFBCAA@A>?==:;67540.-+)&%!  $&(,0266:;@?CCHGKKNMPQQTSUTVUUSSTQOOMLHHDCA=976/.*'#  %',-35:=>BFHIMPRUU[[\^a_cbceeeggfgfgfedebc`^]ZYXVQQOKHFDB>=974//,'%   $'..369=@BEJINPSSUVWY[Y\\\[]]\^\\[ZZWXSUPPNLKIEC@=;540,)$!  #$(*,/68:>ADEJLNPTTX\Z\]^`babcbdcdddcbaa_^]Z[XXTTRMLIFCA?:720*+%" "#)(..2367:;>=A@BCCECEEEFFEDDDECB?A@>>;9:855200-*(($$  "#%%((+../03558:;;>@A@EEEFHIHLJLMMLMMLJKJIHDFEDB@>:9741.,*&  #$(*+/215788:;>=>??@@AAAAA@@@>=;=998633/.-)&$$  "$))-02569<>@AACEHGIKJKKNMLMNLLMKKJJIJIFEEEEB@?=;;956201,+(&%"!  !!%'+,.02588:=<A?ACEEFHHGJIIIKIJJJHKJHHEECCA@@>><;884402/*+(##   !&(,.469<@CGILONTTWY[\]_aacdbegcebfdba_`]YZYSTNOLHFD?=:540,*'$  !#$',-.013679:<==>B?BCBCDDEDGGDGFDEFDFDFCCCCAA@@?<;:8674300,+)(&#   !&'**02467;=<BBDFFIIKIJNMMMOONNNNMNJJJJGFCAB>>98641/-+'$#   "%$'+*,.0/1035656667789887789968785736533321//.+.*+*()'&#""!   "$&&)+--/.1326378789<79:7989687654312/1./,++*''(#$    "#%'(**+.-/212245787969:998:887866462210.,+*)&#$"  !!"$%&')(*,+,-,----,,,*,**)''%$$ #  !##''()++/-011235656779:89:898978645220-/*+&%$!   "%"%#%%#(#&#%%"#$#!"    !!#%&&)),*,,-,./.-0/..0,.-,*,))(%%&!!    ! !                                    "!##&'(&&(*()*(*()(('%%'$%##      !" "!" "!!    ! !#"&#%'%&')''''&(&&'&&#&$#!!    !!"!#$%''&*&))**)***())()$&%#$$#  ! ""$"$#%&#&('%('&()')*&''(&&%''#%%$%##!"!!    "$"&(%**.+--0102122531424132221.../,.**('$#$ !   "!$&%((++*-/-/00024243545676677585674463443221/..-+*)(*%'##% "   !&%((+--00436679;:;;>>>?@AA@ACBC@BBBCBA?B?A=>=<::7664310.,+)&$$    !$"'')*+--./214546798:;;;>=>??@@>?B@?@????>;?;;<;:97733401,/+)*&&#"!   #%&(*-..3436889><>@@@CACACDDBDDDDBDCCCD@A?@>=>=;::777242/1.,,+)&&%$"!!   !""$%&'(*+.-0113546989:<:>>>?@AAACBCBADABDB@@B@?>=<;;966632/0/**'%'"!   !"$&%***--112446879:;=<>=?@???C@@@B@AAB@A>?@>?=>;9::87653412/..-**)'%%#$$       !!#$'''*(--,/.123455758898:;9;;<9;<<:::::999:6675542301..++*'''##!!    !""%&%)(*+--,./1131435556786899::889::889797856754544332000//,++*((%$#"!   !$%('(,+-./0013336477586968788747656332311//,+-**&'$%"!   !""&%&'(,)*--../////0133131233130211/01/...+,.,,,)**)(&%%&"""   "!%%('',+--/1/222333656567567486475323111-/,+**&'"# !    "!#%$&(')()*,*+,*,.,++*-+++,**)*)(()'((%%&"$"!!   ""!$"&%&#&'''((())(&(&&&%'$#$###"! "  !"!#!# $#"#"#"! !     !!!!!       !"#""%"#$###%##"#! "                                       !!    !##$"$$%$$%%%$#%%$%" # !      #"!""%!%""$$##$%%"#%#!""# !     !!    !!""$$&$%&'&&$'%'#%%&&$$$"#"       !!!# "!!!" "     !! $!###$#&%&&%'&&'%&&#%%#"#!##"" !   ! """#"&$#&%%#&%%%$(%#'#&$$$$"!!" "    !! #"#$ $%$%%$&%(#%'&%%$$%"#%$!## !        " #"###$$&%&&'&&%'&'(&$&&%$%$###!        !#!!""$$#"#$"#" #!      !      """##$##$#!&$"$##&"%"#!"""# !     "" !!       "                                                                                                                                              pyo/examples/snds/snd_5.aif0000644000175000017500000004201612652732202015137 0ustar tiagotiagoFORMDAIFFCOMM!@DSSNDC%+6<HOZajtx  rrfbXNI;;.'}m`QJ77&( *5EVev:Rr9W{'Hh3Mn0Td} !&(*#t^I+yX4]5g< h8^+IN g6 Z%u2]%Wy9w=g+ f=[R\ g<& 9m+OnBz~Y f/Ea\,S]HkJ] 4  k < o 2 q  p O %   I r L  Od&U KTl2p'nOaU&UiJrHypidv5Uy"k1~T},4YPYEg > d C c  I 'qNi qVH.uO [  @ D I .>Xzu{iU?|a~de^xq/7E\Orxw|j?TaHz9ljwވ*~TIܳܨ^Dޛn+fgK%"!*)`me~F  @ R  RVo~,"F m:~KxxEf >};Z9 s; s4 i  J ,OWv#N^u7~c_U%cS8LZ<ݖW۩QED׳>9խ&Թ+b[p'Ͽ\ktj1#ʝʙi]H΂ Њ~ґӸֱ8٣XyL'"]<~Q9~j8|s B{^-J O! !"y##$%(%%&&%%%%%%%%%%$$"###Y#,""}" !y! \ mG#L'.[l:u2F v Y # O %^cuHgGiuVG{< _"C6Y 5Ab=kXOd3u?&T A > u]qQb9l  !"#b$$%`%&#&''''(1(X(=($(9(@(!'''w'X' &&%%($$#""Z! (Ob@<:JH  C i|3kC7!Jr d|eX{2މM۴ ڞ+F֌%ԌV҆Ѷnd6o#}-ț&zg*P̽˿wMHrËK ?^GZܱ޽7  M|o6yYe=|kghj_\bft &Ce9HSzgb]p i!\"N#%#$%%&U'''(d()()r)))))))))<)(((+''F&&m%%$|##"h!! H.^\Y[l{{ p V@|~thAxE4~%vH fO4ߌ.ޮ݊G۶(ٛsFֲ*Տӝ_Ѫ bCʤa+ǸXƣ[ ܽ tؼ|\Uw &iȸSҘJ\h5Q߽fOa37 V ,XwbKOCI s!#B$&^'()*+++,A,-@-.;.....L---,,f++?***e*C*7))q((''&;%Z$$@$9$###]"! 0*2!<5(|Rl Q  PG{+i()(5hSZ &,([Ff )Ws  t Z 6JEYvfL2 !"H#+$$%&'(){*B++++++t+{+++,,[,,Y,+, ++Q**r)('&&W%%0$$$U#{"! djhK Od  v95|$t1ryY1C;_B~R  ) e d?c0R8v!FqK3)$d-w8:E-rVE` g  W ^x  o ?!"s#$%-%&'d'()*+,,-.A. .0.../{00 00[0/5.0--\,+++++P**D)(';%#"! %t  OvboZ)X^}tz>BvrayYi#a L3Tqd.!ߟ޸t .&][j5z/@=Ͻ϶<ʘyy{#97~\k*:&;\n‚-Ž?Ɓɚ˙3~-3@ߑ\0]EAGQ4sC|G lZTi   Jrz#EhML aw.Faxx}yv'?*5SK *ً۫G .זu֞J5QZ̋MD20@.ʖɯ0ܿS_ę:nĝlÄD^NJ̕J`Ֆ׬٦۴/!7=X!7XMr x "?t"V !"2##"";!!G !;"'""#$F$$##[! 4@'\A0D3'YN-J?[85r r 0 u ZvTyz$P>'}`v?r9N+3l:# 3$,~Q \. S ^ \bx~& !"$ %;&6'(*))j)*-**++K+x+++,,',-.----I,`+I*7)f('&&7&7&D%$$q$X#"J f|+iqts5 & (xj7f# Ial(P~d Tclo7ZFvl6hwrN#h$yB޲cݔܡ<]Yي2sׇָ/|#Yѳ((LC̒Xʠ({m(ƧųQdz3fňǤsǹ̂G9юYGܶw[=Gjshfp+ N tAL^Y(  [ ? !"Q"##R#!"s! |a#70X0ELi5 ^Abv  n , F 4 F w * }Obb ?u(AhyxJ/$m?IAGbU(Nqf$L$  I > , f-"o !"$ $$%&'t'(@))*+7+,--z--,,- ,,',-7--s-,,,m+v*(((&%%%P%2$c#p""p!X b8  jhY>$@bx x l\7~^IBO5$xe*H@ZI)Wn/=0w&ߦߐ*y1y۽ڬ ڠjةح 5դs3Ҕ{ѿη Ϡ̩̎ʰ7ɛ,ɛȽGȐJ $0.A͒|8G1X-R;19PPx?v K 2 48&jr98m& _ !=!"_"#Q#k"!l T/v+"b?_|{E02i|qYYb j | 1 [ED|eVkw~iNPv *j.m 4"/'8 2 ? I%(MYB %!.""#H$s%&;&&'()0))*++,r-$--x-.\..H---..----2,+/*O*~*)(R''[&%$v#""P!e 0(^54 I pZ'eh#\g."ltaTSM=)THFtH~vN]Lb\GfQJT/n[xސ`ݺܾ< !ڱ[eًס սӪ>ӼNҲC`a͢λh шI.CAҞԐbWYݵGvvRHS0E?6QK1ZwaXp  r38!6 gay\/@";^yT-{TkV[2tK  e3 b   e "lxfcu}'Db"[_@ 5VXB`Mg0TS&a3h@jnWy1artR P}Qb ' h a?6P `% 3!*!"#$$$%}&&m&&''((=(R(@(l((((|((((k(T( ''=&%% $J#"! N 3OtY|Z/3Z   2u;/E(5F/|)kGp:VsY"*ed6`"n)87 A@s%q܎Z܎ةؗ׉UWHSV}+ҨDbѡrgғRaԞԴ֍׭SؠٗU47ߛal6Kh1'J6q?l  u Z N:9x\& CFV,p4 / !j!!!W UV v#Ec :(w3lMDw0tp n q ^ . <  [GqTcX430#L?APAuZ6TH= {6X#RGi Z ; Axl6eHB'p > !"##$;$%%%&&':'b'()()0)T)X)d)z))H((((I''I'3'&%%%r$$ #L""!4 v(cYBy?TQ[dk | h !]o+7YG%nf1u y*b<3_eFZ[|;,3,QZ_j!a![$A]H[߶K^|F,(`EVԿԐӟӧHvәrӪ%GӆvӬ{Jv PڴP@- !,Az= u-/& :A4/nA07:X4tFaC,V3dQ?zc`*6h\qG}v&QH5  # !  5 2  ,X{M0`?H(Kb0HkJ A1~AWm]`1nd?AC 1ysV  G  yHAi u2< r !;!"+":"<"#/#d#^#v#$ #$ $M$4$$##t# #""^!!!a , l1OrEfE7Nrv > h `  ^unibv~ftR.4lz"kpbjhq/`*EeTB2|E ?y6$)v6y<b<޲ވL݁M9@v6ےDZٚؕڐHYyܵX{ܘ<'ݢf1xqF'w1EStBv}ZX_o=Sxt{" P : ; i j e  & ,l TOdPR3i7CsO]]3**3|x!B t4m ^ ;  v>#GibD;l zni$CC2UtEb{b# 9\Mf n ! A&@G :!=V\Qof0$TK-|"p&9=m)CmAaTc\!Qz[K!A}8-|[OQ 3Z\_K߬߮Ge8|Q$~ J5$J1TcJK:d}!$[(H(suJ9[ogodmd^Q{/Hp ovZ NqV-1[?iLDJ>;W'EZ- i&m$n  w L 3 R b   j(E M11w7EmuN.b;0-PygLI,}0[0b{ ^dI?; ~ N  4 " j <  n [ > (  2 3  f # g S H 4 $ m[3 v~t<%,!oh8u]h- WT[Hq Pt3,2 +JYzRBNCE^x8usd|5EZ^(t;WE.L$XP qcJTdY =7Q]QEl7&[2 j n 4 f q Qe&[{qws}nj~tQ,(A*Y8TO6(?ZH!WLG | P 1   i E #  { p N   ~ ]  u f W %y[J<vF({^;,haXS1'nZYRM)eM:&ncX># gA#~\>' b9rHvY9uIX!_F# &03Nu)!*L}2?BWj8N^p~ +Q~ -BLDPf~7JPSZelc\djww -7FGValnktsusrvx~{vnjh`^VVRMGDC;7-+"  }wrlga_VTMKEB<962.*("!  pyo/examples/snds/baseballmajeur_m.aif0000644000175000017500000174173212652732202017430 0ustar tiagotiagoFORMAIFFCOMM@DINST<MARKAPPLauFMSSNDx          $)))$    $..3...)$ $))$$ .8BHHH=3$.8=B=3) $3BHH=.  .8==83) $))$   )8BMRWWWRB.     $.883  $))3BMRM=$ $))))$$3BMMHBB===BHR\\WRH8.$$$$).8=8) .BMB)$3==8) $8Rfv{vlWB) $${)) $33$ Rv\B{v8a{aB) =f\3Bf{{fH) {vpp{ vkk{ $=Wlql\MB83.38BRfqq\H8..8BMWlvqa=)HalaH$.Ml{v\3 R{lH)3HM8=a{l={vM{lR=){W=.(.8BLa{).3.) .MqlWHH\{{.paav=RR8 pB 8af=Bv.3)$fB$l  vk{)Ml{lBv{v$33 .HRM=f\aR p3Bf{ =R\RB.$.83\GWv8{f33RfqvvvlW3.=HMMB. $$)${f\\fv 8Rlvv{{laR=$3M\\WRRB$RvqM{oaHB.zF2S= .Wq=\8.\W#eFAVz 8a=lfRB83$ $.3..8M{ IhmX>R.MaaR8$$.Mvv)R#(pRv{vfH\=3=Lf$\ qH83{DwwN3kB .f=lf){kp{.WlfH$)8Rqf=$BWWH3f(W{)v8(B\p W{a8 8a RBa){ppv{)RqvfBfV7',Ka MlvqffvW38R\aqDb0d}xE W[''PM 48#<K3\ffaL7'V(Rv(e,GX9\v3RaWB   )M{{={aLLWWLGW{Bt\Ral9|baaW|s'F'n). YiJ|3)a=fB[{ N I Xb9=fBt'A =B8.pFsE6EiA{$MlvfR3{faffkp{Rq=vWLk8a{8a8Bv\Db)\Rf8vf8R .f 8vlBv=4^}09) z(k RX&JO+b.j'tWM ]r]*R)$M*q)l 49/  /99/ RF"2`\8%)L `,,e8=l{\3=GBb@dES=vapp38Rafpk#ztt\ 3WRpR=L 4%{Bp=#=.S&+NB{  l8$.R{*I9\*/D]|iO(3aD^7,A[kqWOdK{ *WBlq.\a=qlW=WB9b Wpl%1(p{=,!|rw]WvGGX& /l{[0*g~q*(oZ;xLfaBV2Az3lS]l\z`f ON3VK{/OJ*){so=(V@?9n<f=f#=v =Wk3.L8{X adE`B\oF,'z8{l$kL( .8004lHq{=a=L.WaM83W4mbk2s2  R``GM* +Dz27rOK.D5wB3q]w*tozf83) 3Fn+#\\.`@6(3et#v96KThd"eyt[1}5b/v88  Rf`eoVF,e.#tF"7.{Ir|IB`J0ZP Y&D=#34Nf\l{{fR=8R]| 8R{l=3B4w4lWB..Bqq=aBeV[[`=af{lH33=HMRvND{*m|W(r@Fj i\GjV`3f{#P[ L$f/@'&I\3.R v\=# R3n]l=M%n'BHB'[Lv9|+@EE@@+I{q4b MvR.e269{WamTin49/f= k.`,sJ+!+EZis~~T6+@OiKP,P==lvM=BWvN]/ %D]r!OY5>v.Bl/w|9B\GGkMl{{{    9Xhhbw|9W33WI !m4f.$8Wff{4ISSD>9>DSbrIq =X!Sl8Lv=#R=\ffHezW=fv\=W  %9Xh]> *>IISbmrbI*R$'7 kpLe6?%4Sw&~,j['<=3M\\f{ Ir|]I*a.W#t2sn~<`tK,'<`8LRR=..3Gk)33){pkkk{ N]I8R=R BaqlaBva\\pvB 8.Rlvv\.B%IN>a=.$8WlW)fG=av/h|mS .H{a=$kz<A\Rat,,o3=vqR. =f/99*%/*   f=$3RfqlRf.zePAKj8L\\W3oFF 8fBq%/44* %>b|bD/ShrrN/*SrhD% 9b:OYO:&hI9//>SwS*  */* llq/* {H{Baff\B$ $B\llf\8v$))).8BBBBB=3.88.v\LLLRW\aaWLB3(#((.(#3Rk{.=M\WH) vp\G8(#(( z`K'"2P`ozzz3GRR\fkvvkaRRGBB33=BB=3.(...3338====LG=3333=GWaaafkaW=3.8=83##8333333=BBBBWWaaaf$.=HWf%%*4/%  */DSXS>*4Sb]I4% %   *44 {lf\M=$BWfflv{vvffff\= .===$ f=...=GLRR\WB3# 8Lp{v )B\{{faaaaaM3HbhII]r%I w%=a3G{pLBG8(L( f.% E5YYWB3M=mk[KB 3W.Wve3LG.A,P!@ S^Ra=.vM |mD %W2MdM,NaFEae%d3 JvdPRAJGlX-Tpq/+#]Ki9D/Ph.-n2MDaT0=VKKM1<3l= .%ieLR2\$8D69NL6s4L' '3A{5W`vxF]h)kpM=~g$T}\7w<%T{){'a^dXBJ)L= GakDV{r_A,@7W`iw3_:;d7td9\ki#c Bu=kh spJ tMLfV bY$ElO l=FM 8iuUuksD3OB .E `e 9 ut> T cj  ,es w(aOt&_ #  MHA vHk U"vBC%2'BFOd<8c$xzv`j 2 i`J Ue 6C k 9F  j-m.$aO Ag!m q_{^uTs R\9sI{5xc q'__G+ %}Ma m\2Qr+Q IEAW2LPXpq&?  e9.%m Xmd\ @t 99 _ 8 h{i< p,a,,3U4l L2 W<X*km! JQ#/@JEmuv>| ^uml ]R&0_\ys  |  4v-P  yICV5SN =L7m D !tsk )I+Cl~8d( _ 6,:Ny q*Wa!nIs: `4Shv*`: C1AjHp g=C7%B H b j3T b]0(@C {kW<  [  D=h}Apc YPh; }*9 dg# hQQXpMv%e>k"{5aB yE|w fh v <V =J, Wzq  oy3k!T8 * %=\ c m R9,IteT CSPl"r W35tL8 5t d5<,xN_1a0p   i >`b llo|u }zYasTgbLGbLowfxV_\mq0`2 en  Y N ^9- # t+;E#%dy\?!07Ap ZCr>X:h W \lh2 {  K F <)(1=| [ ] bI_A & . 8k E ^$6 v hw5z_eaML!.dFECM^;gm6^fSa+` R{G@IP0c  O 8 y2 hr,`w\Hn_' l## >Rp*4v9Qfm N y $[l0y_q + F {;0# E sJaS F zV9T 6o$  :7 .qf0W X]k " B9;a ntdrn@  +Ldb>Kf  C Mf^ ~ A }"|490 5Fvr)Q  ^ W 2% ?== #]e SAG l W  :`M:` Imk+76a?T8F 4^# wJq c y 6%lNzbV < c-LZ=!6!b P_X}Ubbm:PV{E'i^ Bp[ Yo|9\x7r9FK PBI@ _ O ! >4`V } #mAW >W:0P Ey ,Nn;m &L)0A"G  M  V   Y{#"B } @ bGb 3mR"hW[R,+|a ZK *TN g&x\h" g "GdJ5g.kpT$e9N5Zh_4{ VX.2t2e  yy  y ^4T=H]- E = W) ^ *L0%ZHYVp {/] 7p_$xܙAO}f 9mUD&]Yk% X iB  / =0 p yM  ?BYKcj2>T.}D)1 / ' ܳ9܅r b bN4!bh |tRtv rM q A qZzg vgjW+0I@u ks m!"  nhpGa Q( $TF:I eW(I ]HuQ:%nyZ}vG] GpvB%e a 3<Y>F~ b ;,m; ]hq1?U  G> `L N 2a f! 'm M{8 D&2)d(#DZNU \(r,+#<i3X * +!j d} !y,%X xCZrZg,X#֍ޑRx[~gڇGls1C T b *x VB>  Ssk  vo "PS Td [Q~aTަgp&G,VR%\#(I++($ uFLW ~qpH #9 I{u%rb&^#5REE5U ((Gf- . X @qTvC J]Ez@]qgBEeL '* u ^d2r^  / {_ { s d=xhmH] aCz\@f G*%`rp@ 0<k1 S Z 6 ,vP_.!>).qEJYt;Z(NT(E"pNn4 ISF Z . "`at1S?tzxb .     sm(uDD )ID0j8 J I&;J . } *> 5a #H.IO |; %)*($ 4iZPgdK \ R ' ;@!E !ר˳3Kg|e Q#%+$"k" FUh 9 < i|[~C9R _W9H NA.<" jh^:b 3 63vB  P#m TkzF\\ (%3=_(ێ3۲nI\1{0'|v6N{@&hL{ q a Um -  3 cGC~^v3\,Xc{%  .ZQ/QX #9UEw >S+ dFkat  s!;Hv 6i#m8bT2# N A$ WK*H)2B B  nW4\#&&$ n ~H(]F#'\'k$?'xb I  +e 4%TPU! M r@DE.# D C(H{s  ){[\v bpWe5 g  : ^ ^ D vLu[=  y,1.@V  * @IuRTIz!QE]HnF==%&B<M\+/d1+]r y:4"8ab *3]gam]9OLFdwc&cQ  u!/cN%P >  :Ds2t#l%p*%C"]R@j*~GhnSX ExiUf..\laH ;Wf=R8$29(rNt"|ntF` P0Wf\8#`~&Xvfj2f) S\f{)B.D{8$a)v \H */I]mh/qB.a{ |N%q.8)Yd@sJmW\]wN*9DD4999/ *D]rbvaqN]Oi:Xlv99%    *II% Enn@I*//*4bJdT:xXhOY>"W2gmtfWWP\1\<1x!^[t}!&in@55 |9**%flv{{f\qlWB=Hal8( WH49%f3RGvW{,ePnm* {v=)kBRB{Drh ==vB$3Mq\W\lvW\4DXX//ImbRBRfvf.a P2Aj.kf8zKFPezoVeAx@0J2AK`jjt`,A8v3B$aKAt .\W#z'",,xJ0&!!+@d//4D]w|mI >]rN  Nr|wbwb>Nw w % %// lH88MWlDXvfv/II4%4bN %4DbhX>%*>N]XD  %>>/v\fv{fB3f33.8Rkp=3BH{#z(a3Hav.F,#=t`[[e (( \=7_iHL`nwO@TR A2e8B MXI1 \ * [c&9Ybo" a|/e@eE]WuK(&JZLY-:  Lr`: y q+F%{h^<:h*T+=*?:7sG[d8*!,3H uX ZRqg^Z} zGa C@\v H | 6 &Q s IQ w~8'eV_ Z=a) d  ^s>{3p u.l $&%!J1 1jUq N >6a,Ak_9<<; O% s`[*l'N2p8@'&"LEp  Kt v mQ(Z>if aUp%)s'! VME Kv~ K|. n 188v537C&ۭAo\RhV>aL`~u U 1Ok ::!hPB n6  |3 u  4  c+&P?Uh/q )F2tj L ) l  r. CZ wQ֒-:֜٥܅DJ M'MKH1D?;60'= \- O)01?6860&{ "4|?L j  _PWq_oB6ܤ߷0!ё@`XOݴ'dǪȵϿ򺯵GtܨʮĴAAA+$Čк[2(N $:Cޜڜ̖ɍmɜ+ia\6NKS~߃2K[,{bAG=  Nn#H)0M59:D8Q40v,* ()s,S05w9gOIPsR#SMSQZNLJKMQZUXNYYTUPHo@8325g9?!DtIMVNLFH>|6}/B) #'!6$(,0477`4.$j vSvm'n;ajPuT5RLs)ػmԻ󻵻6do8ڤ1 VÆUgAPr2e*̛ұטܙz׷ӳiE&Kqƭ3ׄhH..ߍԹд1͒{߬rhb7X^3o 1 fc "%n')T)@'&2$##W#)"""#&K*06;?BDjDDCDGIL0NQ1SMT?SlQ6NM7L@K4IHIL0P&T}XNZ[[ZYxXrWRVAUVVVUTS9QoNK GFE2DUBA@V?>>>/=<:8Q53z20._*&";R@9 8wYMwBLK#9׼ŰV)䕧dή% ͒41l1ޝљF%OCBF:t^ֈպeȿ™%ίЮh e\O2!\?-?>X=;;':;P@C5EzGGGGGHyIKMOOO9NNOmPR2SUX^[.]_=_G][WX*TcOJgE#@=):8778V9;>*@AWAA=@>:61,(*#b{T R E5Q=,:Iw80܅6Ͻ];k׾zᾅN?FaľBnH >l詥Ӵ ӼftġuS2ͻf ҢI֬׉qٛnomVc.^VJ7.{NK>B_~KY  / qE WjKttsOo"p%J'))*Z+-Y./p/ -+)('='B'( (*U-26:+<-<<D;72,'#"<"B#C$N$$ #v#8"" xL3sT  ViV%YZ4tԹ Mյi֍+ՌԤ(5eb`UYYİPLeuƄQExg8GضM)w5Kwj|Kw)̯FxԐ׎ڇ2W"QX@ w l e acKP6,@y  GDXH$. "#q$?$$%i& &'R)&,b02n20.++-28>SABA?_<83. (%$%(N,/16XXW$UKTSRkOKXG CO?;50,l)%#!; c6i]Q) z ![^; ChCk߼@Dݹ݆L-Lٯ؟B׉փՑ:ЕoaȂ;ùŠ<`=³.RʿɾҽǼĻD ʼоw)w"6ؚ('RbX,tIrsz- \hjsIsUCX&~/ ""##{#$%$%J&['q(r)n*Z+#+{+,-0./01:1234{57F9:;<=>@VBSDKEFGxHKIHFC@<=< hP$W3\\%4 &nY"UKu !""#%1&'))*+8+,,++**+,-+-.!./#////0q1374B4f4#4q5677~78:^;==>?@<@??O?_?E>>=q<<:987654.21/-T+)@(&%!"Q{*V q  + [0lB+bO0)RI'r qF3V;6-Tv֜Թйt˹țŝ>Y9vbh˽۾ݿTK<ƙƔAtĻC+CÚƄwʽ=ь ֗/'t#DLp0sEhXe W o =Qnf!!!!"#$$$X$###l""B"!!!!"G"#H#$I$$$m$c$%E%& &'&o&'8''( (%(/(D(m(r('3&o&&&%&Q'\()*+-/1X22U23o4a5>560654321r0H/.-%,+-**+k+, ,w-T.6.-,+*o)'W%_# ^]:(e e  f3SF#GbFK9P-;c{_ipZ:$G܀$ݚNm\&ײ?ҝ́͡S*W0i_ NjËfKE|.Oizǯʎj?8< ȺɈʽbKbՌؚ۝m3zorfAcf > ^ Y  R  Q#_T # ) S#mz?* 7 !Z$/&K'()*+{++a*`) '&%!#! OD{N3!1"k#%s&'&'')s+G-O/264689:}::87667"7y7t7"66s6+55S44M33V210.+)(9&%$I#""""""! \D T'D\vGKs\eq=6G Ϟ(Ή5̯9˚sxˤ̯,Tѡ05 Іp̪q[6[M\9j4&t9yʓJ>u߬/ x.#%}[u(C3y&rvjnNH _4*&L= $>du,K^ BLl @OhZoH"%(N*1+-.y0C23u4845g679/:m;=>4?T@QA.AB]BCnCD"CCiBBA8@@Q@@@@F?s>N%A8DGKINGPRTVX^Y[=\%\]] ]0]^____z^]\bZuXWUTmRQQؤ&݁kTp@ߍ/ ?i݋tb׷d֗<؀JQDe , /N!&*.15N8;q=twz4{|'{zxvtrp<;o962-(#_m0 M( ZN-؀{|#l!j R c9og+~,Tn <M&-m3[8=< xW $' 1m;iDLTcZ`ejnn}r uw?xy(xwus+p lhd`C[VpPKD=70*%!4~0&5u 7  * i ' j %-($ xjԕzӽڍdC8tdhQ7D  AY"'q/B6> DJNfQT}VkWXXXW\UZROKF|Av;5/)&"  'iGʟLؚt92ݔ薲pݣ5«6}M?HBćh̪ cgKZ M (]2<E=MSZ_LcgkUnDprstetrpmjnfa[T}M7EV<4+"j{ cLBC`ߓ+zQZ C=r5%3C|GIWg?C ##,4c8-1+& 0 ^*Cc߼)W m6goI ݚOmrBOf/ˮ?g`ܺӼs2ea֍WaLt= (92 DJ3NRkU@WRXXWgTQZLG}A;!4k-& s ddDTR÷ٲwe6+F򤹣ǣe@+k` msL:VXӞVCX^EA` R, )3=FNU\aOemhjlfmXmmkifb]WQeJ)BS:1c(X2 [ۨ!Ļ YBGHˏ'n`R {I!$m%y%E$!y >](2&Jya@ '-48;B%HNSWZ\][kWRLFH?9S3,'!@D 'rՑlѱ\̱.̯ i٪*M~w+Vx[ǹȂO`f$ІAX#-8T S) :F%.8AJCQyW)[k^`bdvefOfiedMa]XQIAW8u/& "rH\Tļi"¾WJ8'͡ga3to !#'+ -^.;-+='": 6{2ZE?*}Q\#"[*119@G L~QPUY[\m[YdU~PJJCC=6+/)!" Bn5~@4ٴ<9)ճEdyɺ$ǟ4Γl_g`VAטعcRC] v v U$^,/4=FlN.TYE\^_`a:a?`` ^\Z7V(PIAW8(.t$|{940uvټ߾ZkȿaΝ~,K" |\m &*.10.0/.+& dt5 %`6 #+=2: AGmM7RVVY[[YUP}IB;@3,& /@ )Q $ٶsb] ŷlXҽĻ%0β=:J"a1 A 3dٵ in"B #)%&,5=qELRW8Z[k[ZYX VF>LRV`Y[\g[YdUPJIB:3"+{$ #}Ҽ6״۲a@ݼo- &ս|Zê-|7\ʨɜ~Fu~Gܽ*q\S %+0\5;AGMRVXYXVSgOIJEV@":50+(%+Fܩ[˚ȰGČÕÕĜƽZ\$_Nl #)s.y2 4G5%42@.;("VSt| C4\ &h w'1;'CYJ\PEU!X[a\b[YVRLM2G5@92+u$D Q;n?ʺ u:d*~đ,ŝ <ƏbǯǚCƨƔƳ̪Р՛~ Qu$I*0l5:?C:G+JMPdRRRQFNJF@u:^3-:& TM 8yNm2:ԟϏR4ĂĻ~Ƴrf'$f\ s#>)+-T01c1w/,'3  M $^U!"(T75,Y$/29qCKS]YE]:_#_]^Z`V`Q~KEV>71**$G eiĿSռ3TUǚ_ʎ)kk8"ON3;İ1d~yPđIĜ6 ԕf3* ^g O&,]16;t?C&FXIKNLMMM-KIeF4B<7 0*#W QFݚaӞϩE@#^v3UBJy(9' &2*o-0g0.*U# pVI )'#1?:CL0S4X\]!\Y+TNG}?@6.("% ?nnXg̑puLț̵RM؅ײTWь"(©AÚƞˏ҃PS%d-39H>AD~FqGHI-IGHGFEC&@=9l4\.~(!iZ9qC{[6i@*oz>΢hq۲߼s47!U'k+.K0R11%.)#l F[vd^ w!&'0M:CK R(W\9^j^6[WHPH?5g+2!F n]B _-Ղϔʓ;1ƨ6̑bWZ߈[Vߢۨ#ӄ?€Q ³1ݽjƨB u 'B.59:>B*D'DDC}A?i<974210 -+V(|%E!7 Z[HCBڍ/Ё̵ƞ{OTߝ!jlj)#*1/13Q331-("/ C9M.> (h1r: BwJ\QW\_f_^PZTcL&B6+V miWZwܽ׉Lvf'؅o^`vhf+”;4ڳи _'_߷5 l+"(|,0246T7`7775|3F0l-)&#.!wf`< 4<+9  TʎsrfWi W '=,.02553.( s ^9C\xKsP`/'08?EKXPU@XhYXUP:H@=2%_XqwW;qoY{3Gk0g΄|V0Zݸƿ|b7ڻ #%y*-x.6-?*'$N b~Q3w "$&(4)+)s) ( &o$:!Wk2*lEblS @ݾ  !"#&)J, ,*e$ ]=[rL Im$-55=CHLOQjQQNJCD<<2'Uh 8 <6n cv6 t>N΄e0uh z蘭4xʎ^eS, qz !6 J !(y 0$*e/369X;i<<<962-'!_8 5oT&0տ)Zߺ`?۲dHu N qM(M pXy@Gp@!1#$%)n-2Z7;?BDF ED1@mELJMONRKGsA;4-&A X(F*ǟȖʷͱI|cvV^/~aZ }* m{KD D,Vy}U#C*K19w@VEIKDJGC <5w-& xN(]( 1Fo7$|V]P߱ٛwvʣ%QF䪫"|4ȇҷeTsr'G< > <\&".6=CTGJWKwKIFB4>/:T63[0 ,($)h X{2ݚ(܅Z` /!coXhPp =H FH %"!KB ^9 4#*606n;Z?EBCiCEAq=81)Y!^ Ch ]7})jٛr Zì$`PEwlkҬfCq?m*mdp+-%-+39=?@o@"><:}8530W-^)&!ti// =piEv Igf`'OZ'4A:R 5n8!d""/2`+V% 4w Wb!$' '&$  .?QU_.me{[qFkG 00ֻ׷QݕNނ^ <K~Q b BaN^S gu,^h M ` U ! h  (_yJO%6x]M*oAeuLy?=b3j`oxFl @@ X%vgq!jn1gM }]9>rT R (Hm*&p$OU M : d " y\$@L8:4H @h 1 q `Kh lS>GPOrM3)$$3M\l{q\H.{<cA~qfP}}}c?w8OCir qgY7|_<nB M5,7DeB.%t  { Mz1a1xnnn'G l 0Y,;@KUjk S  Mx,\ 3x% l U : . H N  U i + I u /GU^bqc88l/X0Znsnnss_Ec R8aN@O|vAx$ ,sO:!!!r/k\B.##G4~kv9~8L`5hIDb5tLCTdk q c 6 Q u s  .L_x K  vv%^Fa S:h"U(L > q v \ .z7_"hIg)W#<iS3t!(y1^ThaSOs~T|{#6NbQ-(Gz45i= Dc]4#!%CutZ_~fCr!,6;;16;Pi#zH <)wiFQ{uW3oi@`LC?sx%)[1""1`a)?6V l  D N :  q /-tU6',Fe o ]{`s+hX]hrw|0diT@6!|9*X0iKzV"i6 &Ei7 f 8e~G `]ZjpW /N]N4 Ib @ns^@5T<A,0r*8voeo8k8D@&Nr/W#jVVzLlN: sdJ0h{\V~ZJJZsjR\*b]H{aLGLRRafW\fv3RMp=8vW\WV2]6{)\  a494)\tYN$kRB8G.=8 $BW\WMRHRv\ f3#.kRv{a3 HX&in@S 4wXHvaW\v34XXD*ffL.",v3]T,eeJ &!wbXNDD*H(+aL7{M"@]fV[x"Xt[A7~ w0'Fe(8GLR8`2nE %5;Vb&i` ' v x%D}#.bxOS$($X9861CIU,>^L[P$6zRd* HS~4.q4h*mO`B 7&6xfwr=fjA2P#R l{.(8\Gtn7f {n~7OSwrha3)+xntB (AjGj\\Wcg+vN Dx5XPDo'( ~r/ll3[#ax>\Gp _s4hK?IB( "; D,qz e@^t3`VP&+{fN@=NDW;j'04=\N!<85|p<=i URaNB6aeABmS/+ f'E& PF6n>o@" vALL I!vN{]0X!RKln=lywKfk{fenO]I7 &Ev@_7(9x1ab}YDA_2<F<|j+Ef\Gj,"XM)#Hl5-6 4 pgjA s ]l OW:4`JRflS=SFySmRM*'$bh^E. "L4A6XFt opp: 1 2 U.iXw)r} B]:ImI4"kk Hla8W  dla#p &@G-*#f!D]njEe 'O Sb`K|:+B2p m +\I[%t^.)y{|9RjL J=VZ2k=>:'oir*  YU?i{ZW Bgy c =f\dmhtI& P' S + >?l$OyT  5!:=r5iq$W[3.*zT*M"&a5^ 8 cRx%k9s,,aPBXW{  (D=A$!T$f+hNFW0C90j "N65:vKpH lvW. w.s8 eor;UHe[ 8#Kd )Q*.,3\ w4f b hDL"5K5qO/. @b)JQ&"ML6 mU MP5x&H 3~,gGL(|X )6 E  D vIG1&<xjqJG !^ u0>]9g  . 0B>:P_|3&A}, yA&V'ptf6r(5 fOk~.K;2?loKtR%:|Z) V ;k a#]M ~@l[ ~yGHHpa=a ?_I[O[v}q&u J[x(m} kr_Bfy &Inv$l [m rlD|m*\]?CXN\~P0~EOb IJo 89({W{h`RT R^S_ 3}KAWXU!9W xcw%pB nRK&iV~"[[Gt+ je.#6  [ ;Px$z M*tFw>g1kkOEITY - Q $pb| ) 8MH JOfy>$Tra`mZ*[VJB\4A4M6nU8)vU rc=|J8J!lz5 cK YA{ \W l :^cGlHd Ka_<[=R* |i]gM b ~_uY99hvt]]p H934*zMi ^{K  <\$KIfp  `pI  j43? ]b>L}i%n63d[MEq} #jS  > g h V m[' ! v A % CdKq+gXdLO jCCM#*0kD<sr*e}%sh## N F on,8,=J/  C*.8 N ~ lBs:a"r!? RB 1 ?E i/yi8 f  ~2# he(0 25+m  l [{pO "Uja4D0<"n w ?F1]" n D^ O8eQS4R>E~ff E"tU1dNzGM|]l;~{pz`M& XB\z'Z &[hG-L Tmc]Z.b(mK<y/9QveN1-[D.8B,CPjplc",0W'9 [i`PIhY &Ps+# Ku< q;\a SITep B*_M7r{L-hy$O{*+j.wwi?IA&|4=hKgM=PW3ctc<rj ][!VzP%8O AMHE)LUUX@Lx'fm7x.*Jt#0NhJn{W8=>]`!j%RQMul n  / tvC'x:^'=lB!r8i6/MK&Mw%Ds{ Ee-je WFL $ {XpDoOfU/1.KDB(  R( c\+uy3FSM0Rzg 2 awL&AJ8>GiW ) qoL96RJa  l'`W=Zu2i(@<$|S`F[.k9WlB*AH@ps-iE K/ma3pVx+0 Bp=(8Rf@hS@P.\Wzka>YO\3D@6f-yYtJXHEo.\zP@E`vq-(A[$#2k A",1m28X A  z2 f2 C ^ &  :]9$  a    K _ %6cCS:@X$h>0&ci48?u +JkIzgVM zXYUG3~PV,I:4]YgUan\ (>0S/lk g - HpB! Y Y!"#$%&&%$c#!!' mgr mr|B*W Wy8 J9l[GVkp(Pgv!yJw5e+IkFA%,TqG{ro=H<G/{  aj$}+y\S T m : T !"########b# ""L"("<"z"##M#W#8""V! fPJSqU{[@:C= 9  }M('! M=Pt}XGr=)|x<2'T| y|\zmJ,aYCSKGfB8*6++_xi6SDm_7a6t0PHfS?1 + u 5$4qG g !K"(# #$4$S$4###l#C#R#$S%%&' '\'a'&%$$ #!  8yE,s # Q _ ^ H2A0|~XH2,IX>9. McXR DD%$7P*v4cxq 9Q( TPkwY"" 5/b!ZwJ" Xb%Y_  @ * w`sS| D!!"#>#$%%y%%%%&-&&'#'='='M'q''''f'#&&&K%%_$#"! jTX\jm W F ; N 7:bu[+{, ZYofNN56ytIqz_?/G8T fcX!F_U;'FRXioT { ^ Z u ~)**@Zu }!_"7##$I$%%E%%%%%n%@% $$$%%i%%&-&[&`&-%%$ # "! 0SpQ`,#  2 y I [i>  *v`U\$ m,KZdZPENO!r&.C0Y}\ r 8G)|KKA'7Pt jt(?hEF3\5o  9Y`K ^!#.$I%!%&"&'%%%s%;%&%6%s%&'()x*,***y*)s('&%%$N##"k! |G=h s9 R -  D )q%V@rJ=L v~zW |h49}. 0hzv\2PcB 2=((GrP<cS3qqRlvW38gkZ;[aDt.5C@  JPL] !#)$r%&'(D(())E)))*<*++,,,- -%,,,C++a**K))T(('%$?" T) S  ~ 0 B*Jzg4&]&xX\ZkgI;ZEm&hK Q6EG[~D wOxMcU,IkVVQ-'xg491Ac NXe3 8gXu]1 "k$%'8()+2,,-%-m---.@./`0W1^2@22222y10//#.~--5,g+*)('&%!#"! ?| B$x4 BysgBhcd+{<(/brtQ$YNqE*z0dc:bLcit~t'*))1/xZeX9?ctama c}}K%2b"bU  8Azd "$*%&'())**+,.'/1D2456788L8Q8 7o6543[10H.y,*('%O#!+ < 5fafxqU(W !=O) v qp#y %~"eU . hWxBDu^tk.7A#M@q0ؤ42 β/ɜ8@å%o3EfxV ܙ%oL_q$e}b( l ~\C 5 " #g$&e')**+,),--T-.;...d-,+)'&e% #"!^Y zq,hH.3a>ܤ452QJX^5 v>f;)Y9}Uk 1 e   S g %~e9` } K#jc!/܊ܮݠ~6I)5tit< fqo!E%(,C/[2147"9b;>|A.CEGIIIII`IHIVXhZA[\g\]?]s]]]i\\ZY6WbUoS|QPTO9N LnJ>GDo@=>940l,)O&u# I& ~Kێ&מڱޜ|i}Bk=4cI.?) 1< 8  bjZ>izIu;)dsF ݾ^`%ƣK C0*ʞHРϤAELGIJKLL KKJJ.IIm;'7P3-.*A%"<9{|~ׄjYπ(G@FIsc%ۉԅf:R dt* Z%-0KA3j.|fogaտӭЕftͻE5͡Ψѵ#HӽZX˕OǀpeǀɗmϮ֒rf~ F, P  .sd #>%(/*-s047;?CGIKLMjMM[LL@KcJvIHH6GGF4EGD~D,DZDE-DC@7۾82Cة8;]C57;DTo" |6 ` <zi9#WZ:ٯk? *x'mР̵ɈB)kO2::9:3^Gp vs#'+Q.d0257:5=@BDF4GxH@HII-IQIIIeI#HHHH6GG}G?GFFF|EC@<6:/)#B'": +ֈNjg8YmOx?\pmOߢ=rnla.j rsXr?Ldh]8^5#hSM@k% GD#[A ޵܅y1,s/#cUІP{Iݼƻټ_ku˾m=xpa]0 =Ct#(|-D144\689;d=3?nBDGJ3LiNGOPQRLRRSRRfQQPOONNMLKJIuFC&>8u2-($| }1Ql iԐ=WW̺~#OGMxH%nsҷϸsP!m3 dN&> 8 - O m D ? N c ! 4X n #fxF6r j}jۨFJؚƔBK@ڶ$İʽЪ+ "w? - ~jk$)-143679<>A=CF$GIzJKL@LM7MNP!Q,QRzRRQQPOM`KJ{IG+D?:54k/7*'R# 8K@ B/SUZҿI6#ԯܽ`/ߘڱ1ϸΘvӞ{ ZTH`] ' /B : jG5jU0 m 3 g v<`ޫ9PЯЋәc׭֧.qˊmĭ$js ӳ8D'ޫ"EW 4| D%1* .269==<=?ADGJMQ2qv_[ }^O S  Aٛ!ёG8dϩ^ :&1.ÐǾeY܏gc!F  qJ &A-T38a;t<<`;9)7K54458;?CGKhNRVU6VW$USOgK4FB9>:51-:)'''(]))*+*U'G!u_٪҃t FPCOK|mt5.z ) uOsn  e&XfGr EcYmk<_!IoBs{Õ¤Č̺؅.dJM};xbtih wYJt"'{+.0121100/2./#0259g<@KCGcJMO O/MKG}C@7=3:85>2&/V-},-0--s-D-T-}-*&<4. SLeMZ R%@!X=TB}|=! #Z fxh@P# v }L<<8 yXO & R'7i߈?# o٥Ν"ƞ+©Ð~4{8֧ܔ[h/SiM$ c`88!Z#$w$N#!E>}x#H'.+B/<36:I=>?6??>;~730$- +()('8%%%1%&F&%i$$%"  +4|׉ߘ_\g8t2(8@f6N q  U W| NdF933m  c7V.فؤۘݾ \ϙq=ԻVêN0&ܽ2pM34; j 8> G^CL!&Q*.25799752E.U*'&%1$c#l""u#8$h%;%U$$D#"  `VQڍݥ4mUB:Axd{Cr]5  o+ K<'~J]c~oQXMqݾ^iO_4޵%!LЕˊ;HŷɈx1Wov pN* IP~;C8g(lۭEGVqUpLJ: B= <BD3!#&-(+--^./B.i,*''&`%%Z%&$$/#$/$%& &'&'%%d#!` | aJ`PxX y LX#[@f@  Q |dPY!,[g)VimRGQ}b6. i(0fcVh!EZZJ!z!8l R 2:_ly //\sQ h!""! h&!K"!!E !K!i! ^\} rD{BL$0 l b[jV ) O),WEB% . % U   j 1 =r))'@NvGy;Tgk9xqtj(C^6&98C߷%܏ً\׉VڂC:_ߢOq*c P^%m,Z6KQ SLdI!"#C#>""["k#W%E'*-///L//-///#.,+{)'%!;T?TxYCx! s U5N% DbWyc8)E! MjsIf׼ԪN6P{rxڒnS֍c (u^۷M"3/d^ C 78P W}O"f$&j'(m((((r(D(]()+u-:./`/.'-:,,+L*(h&%_#" 8cd  @  lL'x Y$[4/~,sDIh*$[6nm X~Oc\=l{ AXAn.ZXM'T܀Sqa>ڗ26[\m;G>WX9G 1 a> u8mBS!~#\$&<'G(I)@***+-++,-x.y/z//.E,|*))i)!((X( ''v&# ,< {  L  w 1  H\3U~Ex<=8<:V]>k\LRL8V7}a=<`HX~{%w|R< zKN݋ݥ}tSN;C^"Pg$ Tf^f O!#W$%'(b)+G,.P/0l000W0 /030b0 .-%+u*`**"*))))(&# :D uQ H  1 Z ; WBKa!*^w!.a>Sf`!kaSwR!r#+\::OzB|C{A8c 5t>Yazv]! FoAt  BC:SScn+~ c"$ &"(/)+k,-T-----^,,,,-,+*(>&&&z&z&Q%%$#!>^ E$UOO gW@]oV+kLu[Zv(uUo#aR1hYh5] Eh5ޫK{.KQ܊LVܸ]:Za ?&<3|E,Zw 8HF !"u#%' (h)Y)*,*P*j*t*o*P*"*)**))0(&u$#####v#""vX'"Mb| e*T^c2h8q3v RZ3 b^#%'a(w))E)^)@(( ''='R'(*()+)(S'%s$#."####v"!_ k8oP#n q Y\ a: g? )^c1}'\$; ~Skj@P@eC4!uF}}; VVjP61;Z##$vvqql?ZA=XTP#]IiX+*EPf q ^ @  hp>y- _B]&dd: X4=KU?z_T9U* W  -Ux1dMPH i0QFOIpWB3#(8W 4Sgb4/44/  9g:} FQ>htG)dFGW!UHcy v S O o X'=$O't-uHDcwwcI4/%  vR3L;+#e!N l " d  % .Z \"  8, |lyxzL-jAsEr]>pLVESW)u[<@I]4bDEDofCv*4:???4% gC[<-# K}0S=0 G 2 6 N bzIX8Ew*Ckl("&% j&M0MB BA"K`Kp)0=*TK(lIU# W %  q 4 0@E@5:55^Ft B/T;<f$>b{{lqlb\H3 )CRH$(F0 % 8 j  : W`KT/`SG@R7o}vtTD3-Eh|.k#j1iY?|wwmw|!YP-$^zr eWXK|0[O"DF{0K2 8 W g g { : Z  o G N+d "",1<Ke8> cP(-tZ,T%w$kPs  A @ * (1%$UwR*\hk;04.';IWG@?48K^r8<nT6 0JZTT_n'`G{/] c6=|ZvDm09rz8ZWm!ow5 R  ' {O ,P G{/l DTD??5lS9{kkkp$)  p3yFnO@5!mX9  W ` @ w  H`j}C{<i>f2&{70QPIW,nIl:CGj1xn^O0&JiP2pbh1Lac6K/j8u8dKGW@=w'- q d ` 8 iAt 88#tP6,i: 0JnnO+rI  { R .  o [ < Z 5 W k2tlf1dX.(KJ4#P}4("RKOw=z %>GZOI nj &("I{k߃D Jpt8e FPVA::Q5K>@>`m=CAop!Z%(**)'$!tm#^b=#M'+.01%0v.+(4$/ &G $9  " ? :|6C\uF' }  f YCO 8- 2PFg T Y SUa,JY<p%+A { $x.7!|ImO&ziّ{je׷\>Oyܩ$C-oޗ94HRXvn.ne6ROhy> G  -  "%+.@.-5)$b\$:FD 3yQA@)d`Zt~l)rwqoe4vg.g& tD Uj!%;'()*1*+-T/2~599@AfAk@@z@K@ACFJ MQP&R=SqSS QOMuKHFE(CB@>=b;:8G65C4\3372d1 /,X($4K (liz ,('Tͦ+̿"'` Ȩ¨/YE4QɵaRZwF™ÆǕ.N[M,e8Xd<  X@<fIq"7$N$I! % X=0f8Z'/342.*"%!u/&-Y132/)"4 < { l 0 G|8Vc8i\Sʽ~rǚ.̺iنl2263pRnk #%)._39 =ADFHHHHHIAJKL LLLLL6LLN=PSWZ7\^j^\YTNGAM;7t545|7j9;Zl MG;G:t{%2Ļ4}ɲbݰ®ϫǟV= A+ֵpfҶݸd>ZA0Ǥ˳qհUMtXP Z".gLrD 5"! *)ܩy bxS c"B!1[ )jjC.C~   "*cګZԤcDAPňėűǾȰӭvuHqI_E'A/0P!!&*-/z1 258=>B FJMOPPPOrNNOIP&QjRSTIT SSTTU;VXZ\^]\YxTNG@:m51//Q/z1D36s8G875w1,&  RT.RްۭBRMƳu׻ܸP ״ް®%Eua|۫Exmǿ/ ӿTe>nsګ߃6La Srj\g '  A h!o>Q}^ ʄ΄[EiZC mx% U|v`x bx*I~ d<  ";&Oi4*u9 )vgk;E's#8%''(9)@+-15:0>@Aq@?<:O88-9$;?E=K*PUZ\^<^y]\YnVR8MIE@o< 8B54G46s9g<@FCDDB>9>2+u$r\ ) A1tmnؕ<i,UѺa8^VzٹA;k}ݪԭlnMXlG>Z.m,pKHaqD Kpm6s~2UX . 5&` ZAXb(cxvǹ]   @dd\W1Ms  I#$#R #+ 'D !2B b$Vvߘ2A\\mu6HJ8hr7  Q!%;).3688V6E3A0.-,,.3"8?FKOR=SMSlRQOMQJHZF)DB?=H:9M889;=8>?><950+(%! 'm `33ilAIͽ۹Ҳ7S$ίjݳ+ 2ثPͦg;PhˀPn݆S:2Su-, C PE(5D _1Oao" Jxs 6ܙt,þ>/ ::h E8* {f}!$%1#{ T)h wZ$w%# `9p>>#l3Pv(j-_LF !  p& 5$|(r+-..K,4($!{ c% +3;DKKQ;V8y)9 w /5 0B: D #)T,],+Q(#/* l 5j s$* -.P+2$sz X}kCmFFlR52Q ~!~#%&&%#!nX$,]5?GNTIWXXUoQ=)7'0+ %!6"\ < X)`n'P]׳0nyϹλ۶H 0VŸ˽ ϮӞTq,RJnt c V V-}5z6 WD =cp k kKҝ˹[v7x . v  l&, ~"7$$#b hg7O @ ap]"#"'KjWsdP;bF ykvo  nj!#g##! b #(.6>SEJMMNNkLOHD6?+:O6:3K101236:?=@C+DEDKB*>|93-'"` o D7h 2G̥V>Tw N_ XΠ bޤWdsԿb™ŝh0aݠx [z Aob %w # n @ OqVayrH}vJ}@d=6߷B#0 q k3X=^ x$-Q* T 9+Z/< jD8_@T cD)$?@ ?><96^2O-)%"z - jm  ./m5(ݥ4ԴH*sѻ%״۴0]iΨ]騽u^>WWcpԀמޑXXv{ ) eE_  Rq{8 )7[; Q g<Iד~Njy\kj  < -A FE` "&#]/> %!'""""G t y :  f$),+-' Y02)|6 a%7efQAl@Z { Kz{"%'3&%!"z/Y")008?dDHJJI2FHB>h:^6310013j579;E<#dҼSRM%( z+ëڥrȪ8 ~&̪!ޑ/R^K="@ ikhe`$ox@F@77["  n . IG1)˳M><n _ ` IMzRDrf& ) E |F74d ]> s sI> 5"" h]Z V-[P 5ll\-k7t)5d Y 9#M&F'''%E"1r"(/B5<A=E8GHyGYDAM=b96+321N1w24\68z9:; :985g2;.+):'R%$D" ~ YLxJE"؀ĵ i ٳڴ̵\ByV5U'Qɫ;ï&ֲĴ)#[ʲ?4߼("&Nb^ |'n }\s1w l8);idJї϶$J&ݬЫ@!_꬙qhdAֱ#83Gmŵ¸yٿ.۷Mxq:d ryw> CUP7wdF "  \ O   [qgMԾҝRٵ|8m 5 >xB;&nI[ q .Zc8!#H$w%&''&$!K<U {c  ""!^ a gW/9/4]xG/  3aW ME"&z()Y(&$m!>~,!'$'),w.o/01 1?1S1^1h1^1S1h11211D03.,*(%+"#HD5^_ lFtjL`|>P֧;7o4նj92ߪY_ܮzN=w]Ҵڳٳ@~™Ǖ̖^յٖ #8^a^e|E*l3g 5jV5gX?s^mF63Yr o Rf!sn } A h_ ] L 1DLF?MP!#M$4$%%%@#!+ U  3q_ ) <73DG~ s  c9n  #q%Z&F&F%n#"( cWQ }!"#$|$%U%%%&z'3(%)0*F+k,X,,+*y(&# VKg ;UrVPkنֶY 3ɍGxV޽Ҷq!-验{TWExϷ߷!ZỌ#tD#чC[ڱ:z}>I@Al-  <#W/~%+`) [GB.    m / ? 6 RCI@ 2)# h,}Im ) d`^ Y"#%E%%$#3!,1 ~ Q/Y(,*_= v F|=G{W A1~ .  h I wsxK!DXOjf I9a8Br !"""! IOf' d ` WrO& bxtv:!Biv_ްۢةG0́˅"mƔRйeEⱮ \ĸҹzkº$)׺ƿ³+kUq^vm%\3==lNoBs" . " WV+J! 7n^+/h@A(hP 7 SW j+B$d>eOOKcOmJ+!6"f##"! APs-;7O=+ = 6 u ] D|#Ao ; ~ _ ~f"^0[{U m K j  O U z \41~, j y z lS&Gg- K j5bQ@gE] iP0(n؊yKAҼƳ`i:vDl4àdͶמD ҈ڇW R`9CCSet $ .c=*Amv !!U |~fKiH8<3 $^ a |'j+: 8[U;@@'@Dye[Wj|&  &iiJ [ "pME BnJ8*]BGo- 8WSB(OSO PUs W W 3 ) R WpKig#8]Ls<{kmVԟX׭E˅Cj)Xvrf8[aZѰӉ Q2IԴ3Nަ :V_,33)fw >  !C!!_xX!"B!'9~f/ 5 x T f#= r)BG;"7d @ = l]YG y6g}}bk(\Sd Q4 D v g R .#>B=-W{ B,c 72sg3.)-?<+[R\+`W=SnWvl ,Y9s@&t܊AJ ڍ~܏ݹ(|ڱrY IKް%SkB^_pbh=d#%[IoNG.?h*v8ND0D!(xIh!<O  `U 3s"p1+ 6 _6t- H {  1 ^ uk q  w \m|Bq?:/0m\B3[ WAy_&>\?!&OJrSX|Yc&ijeKt)c&;1! IR\8e5>Bj_&hXcJ~'V#fw}Z= Xr1ua4&A. , fFf 3 ! i < W ]5T}K(W\8yjUUjojZF1''''O+   h v ` K Q z G 4m {  ~ h  : ; d y y _  N / * * / / % lVD)papp rL`s ]{8 [2;:vk= -8GQapVQa$Mv:Yr}mI0*% gCuQ-oA'11"sE+S >SX]w Ex ,Kjkvm@2`8*]&i 3\lvqq9h&j-pX+^6Z Bk . g  * N c ! y  K u G { 9mx,3CMXM//l0x1@@' Tg/=t,JS M - ? fs>=Un/l "0SHko?Mk=yK^E|mSC9*{\B.8Lk9Sg0Ocs}sYO^s'U~#8Qaz>]v:^ &,!,1E_~#Lu M?@n2G4YUQ ] sFG W I @ -  8 q /]5^}6`yeZUj8G=#yZPF6" '<P`oyt`F's0]* q =  o A  i  >{-U^]#Ai]=-dNq)a=yjK,xns1U~~~o_UZjLkVQLGQ\QG\kpkupaV82Vu$C]| NJ2GVeCl ?I?/9?ImZ,t8pB>mdU\4^6#p 3 v  m @ ` = m :s1#u/=P"F`jtjeP1}J!b  /ImI {  : l R . #_ma [ shfzO*QJ0H a=P"xT+gXNIC/%%>Xw!T"6FKZo -V$>]|l]M>.uQ#yZF;'",6F_ 8\$X c&U#LkMIEnA8WDx"jp SOK#z . D + d ' j  f %hJje1 KW)qHaFZGgoL3h^8k HG EX a ` _ m 2F+Sa=KIfp/Ck#o&:l]X]XC.).>b5ZLu=q Nw|X \=`-t1I>(PxT:?Oc}nT04v=[A7"""nO+ExKR 9]!EcnKV|*,tL)T'a]YoagI"- 8 ^  U V qJyLL K,t9Y $  q u i ;   7 93 `\b@ZLkQP: } -G  ' e{3 Hk}gL,H.MD"W yv {*sQ "'TSa[<',,'1Po,+D\a(V3@C,}vK@AP:gWow{utcݥgC4$H݋IަߘGj(wZBbo(Zv?U e Dd atalxu g D V  8 G 8   #oN:z$ a S_E( PU E;)$*6.258k:?;N>?>>N=:73.)^#O :.I?^ dPJ`* 3?63^pёֻ V{a \]Y $(+2-082635466n6@543z10H.,+L)(('''\'&%%6$S#M"7!' 5w#OvX< jyzC<ԴtЕs%/gƸƽ $.3$z@Ĝg½ycȂ˕PZ7 UZ)2z`P| ` S;rI;* .0 XY'KNOJ px0!OIS xF%-Y6>FMS4W[^`axaaa`_(\XSMFw=3)q b>ؕϔ˹ȿ[g&aC_.պMrڜH W IDx {##*118=?JFLRXN]EasdgjiCjTjjEi|hGfdbt_\NXTP K%E@:4.(r"2 Q(Nhq_j_ܮ׷զ2DA%BHRλĽKXȂbАlX|XgP &3TDަtp,5%#7 4a<ݥܔs5ڜ۷]1Lr8 S>2|"2%(**,/+*"'%;" mI ^T9{bn`3(&09CLTsZ_c`eggAfeDca:^d^WHNfD68, Y1"߬cNoYqeͻ VO N Kd!#%U&(*,.02d456789:;=?BgEILPYSVYx[]+^"^^P]n[YW>T5PLGB<6/(!;V\e Ǥ"5Թ yy" A b$N_".Sߧ.{ 1a|~aIi׷'&K_IǤ̛'܏)V> { {[=L/5ނܔ]kعi 7d*tVN@ $ N<:86!2.i)5#3x- '-+ݥ؅ϽXɱ{ АP:WS  4%J*/-2n4a44820-:*&# Kt <~D/gތA#XɶNj:åC…̯ (a[.<_j (L4 }=p4 փEنwG%% Atl \ 09xڇނ mfMbx'3 =.EMjSXh[{\]E\[ZWvSOI`BN9/k$J *8&Е˚ƭƼٲɭeqŻOn@^Zk+Y W5"&'(*,M--.,./01I12O2@10/--,,,.U1%49=@CxEfF.EDAB?_<:O8B65%32E0,(4"zK FJ֗ӽTa5ssنg0)Hb "(-2U578752Z.*&" vJݾنҢiu5V5?Hć 0ʞ̆U_A }[vY80< D 7 J  w1oW89Eko_Nٯ׭Ԥ/֧kzU s9 }  !* W - d;|<܀ݥx$#K'2I@BB@>:74q1/.@-O,|+\)&"z,xvٵ'%ӣғEpյiTxT 3!'-269::9/62.*t%!he -P Iu7ҧμfrb'I̼6OW #:KSoӔ1z.e~ w J < 8%: F  1^#}ai؏Xյ*Le<O J86 -DrPݪt,a`AD'1:BI MQjSlT^TTxSQOJEz>m5+-qOo4gZ֧ҬμoŢcӵ=߫dk-cɧA='Wk !&")n+,,,H+++,-/000/-*(%%##l$X&*/49=@QAA?<9591/B-^,$+a*)(D%s!@kDHsaH0׷Թ7xަ .u uR!E'.-27U:=$==H;@73.)$w ;9H]ד~ <ἧԼsb~z!ˤKԯtڻަJ$&!B 6 y s & VaqH*N-Ms>f3?e *BJHC > % KE 8 S2cݥ6|e4|\Tx$/7?JEQJ MuOPQUQFPNKGOAW91/' ,ZGд]ǯžAŲg?6 ؤQG GIjW#&()**))*P+8,]-s.'.i.-+V(&z$h#3#$*&*.U26:^<==;i852O/p-+V*")5(>&$! A\elF6ի/k?m dK$)/Q48;=>= :7y32.i)$ T  ܤA~tǪLJu CHKKNM2N=NNNqMKHC=5,9!@7"ә8MRscjnpյݴ4 Fb$r(9*++*))+()Y*t+-m./ .-+)&$#$*&):-T16:c=> =;951.+*(('%# IuI={ތ=s"֧֧z]ܔX KW C$%)J.39=8@-AA@z=:D50+&"VL{ #9EVܙFL]b;bEW3E\4{΢ќHXK T64I [ m {  V RWSDj*!g۲&)GٖPh|N  |HURyi=Jr' "-7@ FqJMOO9N{MVKJqHdEuAW;4+!~ 8 ܸ2ƣ]λķTɦNGM֒'|t,AZ!&')*`*K)J'&z%%J&')+-O.K.i-, *"(w''),05]:>IAaBBr@=C94k/+(&$#q!b! L3߷٪.V'Xۼ;E5 +!%Z).127;?B9CCB@ <[72O,'="Gx _9.8טйZNVD-:z?ÐNTϤ@܊s' ^U`K<sI [ moڗfn%bN8Q89IEL@m]ޗ[-PFCeN :5'f1:B9GKN NNMLK?IGFD@':4M,"ur yՖɶ¤wϷwO>wR]6ak r #R% %~%$ #"<"-#$')}+-0..-m,M+-**,/V37<#@KCEfEfC@A;61r,l'$D!;u O~{INԟԐզۓK'I=#8&*o-15|9g=@2BwCCBC?<72-I(#rF (ISxVgѵ̛"Ǿœ©³e+ʣSyD/x* X@si+`+' ["@AҘv ~\nb~  (@\HfܳT+9T$7Lb%0g: B/HLOPPsONMK:HEfAf<<5-}# ݥԴֺ͂ӷsа" 橋̯E BpT) |%tkeu. #&()5)))*j+.16:?CGHHFC?94R.)%!' y?M֬Ֆ֜8o #'*,.0257:^<>m?!>=:+6^1-(/#v$|C6 %^@EZF2Lpĵå$ $CRlï^ű#qڶfK)} _9U $ 2I$i4li η̋:#ՠN;RJaO oRjMڦA@0y X*4B=MDJHN=PQQ OM[JG B=7SC}HKMN)L~HC=6/)!" <O_J*%Fe==v[ J%!&V*",-...o.@.U./01X11*/-*'B#)`#  j ccT3ۨ!m̿VoSĻo(|S; V dAeX<v& 8,8I!f?؟7ԯmܮނzAT\#K"ӞѫmkVGo  9$.d7,>E=J)MO|POgMJFA<5-$~{  #t¤<ËƏХ׉,NkNOs l!P&o+2/f36i9=bAaEIMQSCT0SQKM[GA9]1|)"p(+ @vi sILt|O F !_  + !'!"`#C$4%!&-'G(X):)))s(D&[# cn :kc,ՂϏ<Ř+{z#uHT ұعO9 q z R R '  p\v(wN.7d5awMm#VKZ6ZՇ5VyF1 !1(08>CH@KLZL;JHEG@;~5b.& ==bߓ kc*XV̯́}К2ֶ#}4T~IM "#)J/5;6?CsFIMP:SCUX4YxY~XU'PKSDy<4a,C$X >+|sxH('MBC=} "%)Y,/2!345*54M31D., ($ ByGYޜ)ėÆàćFEЪgBdw3?SahB H { W5vPX p#uzm^ R t#8852`47 z&.U5:?;BEfGGGE8Bb>:04.y' q(i\ڶٺ.F0[<ӨԕڂC T8}%a\nfaaA g{!P(/49=ADGJNPSXTTSQMk8XqkK,]tH:50g*$^ Z /WwD|CM]:_1*mc']`%ߓד?հ,ٖ, E{ %U*`/37;o>A{C!CCiBw@? <:7<431 .;+)+')%n#""(!"("#g$$$$$#"!;sj.F+ -L=9?ec]-@_UkqNz=fR& |% 44HuZ;FUA+I*M(FRX4 V;X Dh9WMc\5GIJ<; v 3 0*/()W ].jdX"7$'W)+-/1221c.+f'8"y Cn\%/_~6h]m8e]*E# &ߍݐsڗPܤޡaM CG& "u$&2'f((X(b(D(''&%%y%_%%&(),.y03[5m78G88765 371I/G-0+ (&V# G #aj'`4roZ*KW߱Gڦ/Nwփ٠oXAfse\R0e3v*,L>0*b#e LRkS+?b[x_AadQ7o{\5U s^Af "f#C#{#$%&A''&%y$" Lm~D  r W $ ? \@ z c &vjXAxDM8ZgBxu+ Y M~$pyL T!Z"$'3),/2J47 89:9948=7531/-+)(&$!dH 5  FI98v\9EۼٯT A~5дR vѫ҈vNO~֧֢_+!_׉؅Aނ2OLf!]`R gMR{_Af* v8= KGL3-#tO?4V'W 9p d%`fBE9(ZsP= KAi j _Z$$_xJs*-*Q ? s Q R q 3 )  `dGn #%1'=)*+,-O---}-,b+k*6('%@#>!!8}|  y : -}!W7qL@IqܮU!wؾEXa[PDXϏ<ͱ5m̋T`ϊLԕ"kٺܙ0a`-4IdeFJiMZQ W m w / g uW M Z "h[ b >p$XX){#U&b  ' O  ; y ~ _ E ; ;  : B%9WYIq\frit+o` $  ; u  *~p>UvwJ@^lGc{^  `  J Y go(D~0::Fx` ;Ybzۨr؀B׭ׄמ #M{سbiݾ{NQ }1Hwi,\6hUL3F s<OUL l  Z   E=x'zb{{gM }0g]>k3J> a  o V Q [ V < - '  _ ! } S / { 8<~'?]Lo^0wN% N: y=S:YxmT?::?^@Zoty_;D9W1&3<0?aVJ?XBE/(&mYfT*=Fi|4vM$ )vX_jW*QT|BqcJA. EoY' =9|+ `yY$ /%x @Z_jGpGKI>gSW"!N a [ [e0#Er/8kGAL`$MaglllgaWgh&~,t=aphiU#=LQL=(-G\k{u8jU1s&%{VD[Ehp ?w"n \6m6metޡTݠvgXHCRlݚ%};ߘQ) R/ *d"L|)Xa9%,L 560P<R;[fk1mM:izfB <UgF%5h5 1 D HVy\.d*i}mcT5]MCb^!~ G$qXKG v r  z  B G ) u y  / { b W \ v   q C pB~:wj5mlu$GesrLCZa- GێOٵ*ة)׼V֬sE+&0Jsֻמ.ّc6 ݴޗtAnVM]ijp|fI:;V*To- C h \ 6>%;G>8vqW#D`3l  I Y 0b9WK >Wu4 VsI 3  utY*~m-~ #G ~i]G7!߱ަݥܤۼ:ٛ؏#K"֬֜ֈn_J@6@OsֱP׷)؟ّ ڍ"V݁5~zvX5 xo(]9}m#c 8 :UVH `39iu  D } T %-1|"J}$< Bz3MHud% v A  km.*{u#2`$W9cd"A`\MqO'  39XMftT&I \  z  % RB:bw\G&mB~2T(Ur 1Yفع'n:Դ3V ҷҷLәg4՛֍׷f 2WMha6 i~BBz }< fwy_i"8L 0 x h I )\Jw>auJ{  f]x*(`hC;1e\IJVWst{k C  J u !E R A ;  ^ ? /    b .Bj0l6%\{QBgiۘ^4#" _TА>ϸϳ9Е^U[Ԁՠ;ײ؀SEFQqޡJ(N}#=c!e7 W P6F.{q }!"u#)#$%&%%%%&%%%J$$S##>"!!1 4\JGQJm43 ,%@ ^$owR,, h+&9]J8}F tB  < \ Xh> { B     G b |9 M ' & P*^9"0Svc9ްݪܮۭڦ٥خר֧պ`y@! 1iҬGӞ=ԕIզփzؕ%ٯ?ۄܸ]ްo-(b vz pO-$2%81  d*EF3%yB{X T !~"("#$$$%J%%&&&%%%$##\"!!; |{~N2~J1 cl o g:1nmqz)~of9 } ! 1iG|nep6G W m y ;'b~EwS9  B   - ; ^ $QZ5_`uox+Ng߼ޫ݋QٯRՂ)чXfΉ5̵̠̋̑!T͒AΘzХYӳԤզ֬߼"6Y=|Aw T 1 / dQ3xQ> !!!"k##$r% %&F&'q'(9(()!((''8&j%$##R""7!!1 3jX{.Qy} ) d 5A%>\!pkw8C %*:mEA|E^6  5 Z o xKCXXM)G I { W   - 6 } / b GP*7R}XB<+ f6xm{߱,59.ԟQЪpU^́MBˏ9̑sΘQѰҬӽ7kًڜۨܩݚތy`RNJ`"=Cc=\  6 N4^{%eQH  m !U!"#$I%%&'(I))*+2+,C,,,,9++*K)Y(X'f&%%!$w## " %?xGc! K 1\l^;kp1?wpt'xX { z & r Wo6H&Hm c)C*M2qܸ"!PՌәїϩ̆aʎ< Tμ.ьD;׼aفٿNس8ӄ҈oҝHcֻ8t4)\6/ /7 ' W!%'R(((N'%#! Ibg "%E(X+.25>8:6Y666543<0-*t&"f. Ov2-$ ;* g?$@ܩ5ՂeёU ZϏR ~2WԪԹԕCӽq}9G)ͱ>܏D.}dowpsD3M4c C(8i<8wljZ UNF~8N\w MS+ |$%%/77=vBwFJNRVAY@[\\NZUPH@8G/f& A =:j%rFDœc 0ĂK!]І܊S-(1:YAaGKDN OXO]N3KHD@ :50+'$w! ?q !"#$%%s%%%&&V&&`%$#R U AG8r !8ohK9 ) ?1 r(-փVSPrmXݹWLҘ, Eoҧӭԋի,+Rj_*`އ.L2ܔM݋:ޗ߃78r v8k+a_ R I  + @  ! c - qLܽڇ2(17G+N3SgVWVuSOJE >81D*$Du[rwx'GGq'p|Y R:Sf $')d*)('3$"#i( D%&MKO_Թ|ݚݐqH)ݐ::N2Q#(KH#TB HrJ\BnyBqj }]SL/%I  Z;   WNۉ9zGM#b.P6d;?BEH_JMPSUVGOTXZZ7WSvNGA92+% Iz N 2XeMfZT EO y3W (%,2y69:^:5851r,l& = f,zA\C5DFlILPRzS9ROJ>C;3F*U!y v"_3fM4];)׭?̋AzՂxytk8q X:&1<`EaLQU6VuURNWI C/CGK/M[NPOQSTTQNIB;2y)!!f I+o_m?X ܀:ƞȂ> ֈBIF )-#-7@H,MQTIUPTROK:F@A92+$(w 9 v   e - i 5C=Io E#)/<3689874R0+&2 <߈ۄԤѫWʙʽ3׎ڦMdtf٠خ)\܅YpyocA߱5$ёϏ6͒ͻК/uߘ|.k=Wtj{NXk G} (_r 8  +Yg}AvVsMj fK%L w 8c ++B3:%>BEHJLNQRSQ`MIpC=5,$m^ b~s,m\gES_+܏ Ё̿˳oݥL l"[+p43<BHtLOQRzQPNqK|GB=H6/G'O{ '@(wY?M@vZShsMX#V8  &e+u/3j56641,' : .3"ֶTǚRȦʽY)Ղ٥jt"ڍٯo2FY܅,/v}"6Slޑ۲ӭ|ׄfKU"t8 M^&i__Jhhm0B(t)=l 3 i\14U=g3!$m%# ` O4S9}m %}yއ"I$ ,S5|DIMP^R8S.SSXRaPsMIzD1=5-D$r CW   E^ ?]$(g  `s!'{,14k6s763K.(r! N?Y` ֧ӣ͂?40uԟDN=AKhЯgо ߃ASEEqQ:z"&ٛفEC+vmZ LWgzEc!iHP{ % X  "  d  @k@ Sv6zX$08?6DGJLN#OQ RR-PNIC=35-&ARC !DA5Z.9jpt/"!Nj,oAbU85!*3F:AF IpKLMNN.MMeLEJWG5B<5-%U ! {'l" u\wJc vSL#(-1X3430+%I[mC H0KIT׉A'C!GLEQPVZ]0]ZVU6N#Ef;d1:( `  1p>;jMC+FAz#l̯-^ӏسL#C8 Z#-5;?BgDoFHHIJKLKhI D>7.%k W 8+2 :^LR.ۢګܔi&Ehw: b-"(w,/p03/ ,'q!L_),Cj :%9L~]0AԹ~M)4Uſ̽KJpzf{#{A'YI'<`(]436tq|A$@z*g t*ku)^( s9k@d: O   { O %"*<7:9:;=?@@?x<8a3-'" t>!%1(>*F*)s&"Bj /=o1L.E$9) . 9Qf ./dPFd):QvSżÐYg3ѽǾ=]"ÚƳKAK!فLx$$3v_9*79[Ybx9P=9>5> V*BF(Y; 7hK#<Wo/ s '  ~"#" A oH]Cݴ*] %,/5= BSEGHEGmFDDB@Q<`7,0*"zS 4 ?...jv-|АҵT6…xА׭ 3$*Z.!//.,+)s'&') ,b0>36899|75]2d/-m,+,M-/f011.+& 3 }(P(܏ٯמփsד݁OL.kfoA%]< w#}:  F 8 %ةӏZàpcӿ98۽o̾?QǕeQ5ҬV.(M4 3' U M v Z-N)Rp{8\J9d . J\xrA+  &<,2U6&8851^*P!dp I x Z=B*~4G;Z?BCxC A?>N===<:50(![ J #R#l ^$95>&J͍Zο]t>74RT   #8#"k 0@C#)5.37:=>> ==;U841-(#k .J)ZYw=3d>ް1ԋѦG͇r%t)z޵HqD|S[IO7n?t؟իҝzX+ 0ǻ޺ܹܺV'ͱЋQؕ݋4ua|}+fwe  7  5 0,6 $ci|o  1 K \I6GLU:^(@U!%),$-c,*U%  V0 pu%  #)29?_BDCA?;852/-%*F'{$"#6Iu-!@$D&(4('%Z!}C^BSa{ԐХTƔIȰ̺Y kv Y 4h"(%-39q>CH!KwMNNLJFB>^:51-*&# | iplb=S!ܳؤԪțŷ tGvʞ̥!W0)' =\7y-N;?`؏ӽЋυ-ϳg*҃ӄԟ:?ۢ ^ߢF9o?loYO^Kb k3Ggs @ #yBpp[@h0 wq|XfXDUSX/%swG 8ݚ?X u,8fAHLN\MuJFbA;,5I/*&j# b| !"$&`')+*K+(++*)'$!7~ dw7!ԋπv Čz cܞ'Bf($Enp !d'f,048689:s:: 9764#20).6,>*`(&$" )G<ib W  }[:hvΉ J\ӭE{sXײիӔѡΘ͍͡`ϙ%{׼]B|޵ %Jx ND~ "`)?GQ%i~meEEx_p*Wgc3 pXc <^h'Gv:|Sx f  & S!',C/[0-(!! ;At7 3(6}AIzMNLF?d6J,M"[`/ v 7"k'.*~,/,g+V)5&o#q -^XN@ Y"$%y%"]k W|;9ؾզ=z o%w  u<߈݆{WXO- ^tB@]aVZ/QoiT \ ~ AfmG t4u7ZVޡ ޫ(|a~c^*!ֈQЋK̑WʞK2,Ɉ;^Ǿ)ƨW4TʲNϙVӳӞӄӔg%K 4qBc;R ::]48Glmb l&$_3#  ; lp J )jY? #yD FZ+>bp}p 3x 8#&)E*')i'#R ,L5y   '"&7(>)+)+(N&$"  !"`""" kD} ] < @WUf Pm?,=Tx0cMQL;y.E\ ZB7yxHI&rvHR9Sm0MBfjڡxۘ-8G8ۭJ=Ԛ[sRZ?ߘr6 c%y$9!L N@ rv)1 XV l(r/,M =$L F f  S vs)px[ w_M br1=8jp:+yg~ <>%c s RY5y  8A6[b^1dhtfXlXW Q F  M#G6h  B~F_7 $ r " ^b/  - O I MZ{t=Zl\(WescdJ=m V*Qt8h<k<FbWyob#4PAi# qE;~PkP=|';+zfbةJ aAY$'5_@0%iG;s~I oxej j 2cf h/  f  A  H~ &XL+}wnd4w O lQ-o4 (0 { }F \e9MX '=x 6 TB 66 ~U|_   AmGI 5;9n4 ^ NT  QL M^ ZHuY[ pNKM96,NoC"@r?mJ^7v~GJ%jmeBimdKoZ.t.IW<@;lvN.t2*LR|gAZZ'F]7M8&&S5~DI0r7-iVew `ID\BWV~/MwvdB8wNhI+oK5wT.t:9%CS$N OO548Xs> uu */ T 9W\ hdX a% # ](   2 z   ' ; +  i c M yC+A& /Y ) ^ i F r& S U(o<B$ %  ' I w yh !KVFF`` 1XbT1#)*\l !&j=DYeR_A+m* RX\1o@rlaA= X9.|Ta}?Ve9|u1%MYBJ [ENxtZ&%.\ )= jo qgh !yN4Ps ,c ia B  zk1 ! +  < K  ' F [  l X% h  ,XYV =+R-D&    C / y 7 v q a % uFP iu%/ 7ip@ q q&_P\Fqcc\;G|!DljYYA$xc%]\64zo``zet<0jv*D(7Z3kKYmgxKxs$awM,Oe~,UW4g_HO.jh%pG`ciAiZ( { )k` W r * < DFm+-LG( < M   F lmJU#3===(~&4  ! h   w y F # xz|U + !;! fm SPa3eE`> " +6 L%kL`s@;nZ4@l. Z  K = S  NXTO *   { Z@2vwGKߝT]ܸ=ۼ<ڻ&mvA$,mMƸqȵʉϮ ޫ&Ss~Xm32.[4(wXIl8MX0)ru;[  c : KT44g C ~!bgi 7{50#*޵qI &) )1:7;'=>|><:x75S3A11%000/.-D+B(&#!dK "&-)Y,.1//.,(#8 ^ݪׄ&nYcZ2bTTo]:e udH"&K*1.d26: ;72-m'!^B!%(*++{* 'v#d e;} LٺֶhQ}ʨʨ˩r+ͻc̛aŝX1>;m wA͍_<7?%YMXMK1k~QS'G4??Ka FCJM p8f E  o ̪BI;ޫ&. o#-6dm;85]20/....y-,+k)(D&%$###W$S%')+,-%,*'#NHoؤ@&ɍǐ8rBaԀTn.QRP%#'3 D]m^!&+05:^?CHMRLVeY\>]^]\YTOwI[B;5w/u*"%"L > I!#%')((%'{%# 6+ ^<w:}VΘzАӭՑ׷2 ?l-c]֜)'ЯϞ9ѡxٵH[O[v5*Gq{:Z*8^z+Dw~ozEhCT+V v M6lk2ЪȖƽɗHAuQ8#R.8u?DG+GF]C@=g9q5]1.,+G(%#R  m#2F!#$$#!o#-YIێ4-ŘKߍte2 v8f= #l&A)+.2~6:?DIOT:Y ]c`c`dddMb`l]+Y+TOgIC=72+,'"B8AI   .'`߱u؟q؟4E.J|'sW\mBqbn?xt?Cz"ڱڡPܮ݋ޗ3vUS*fi%P݁ۓ5?\F n9 y`JKqI>Ȼ:8܀!+\38;823Q-h& ?O % D f|fO!~""! u:=*`JnxFвTW R m$'*P, --h-c-5,,,-s.036:x>|BGLQW8\S`dgimiig`aJ_i&XWbWC("1d {& .S "$ XݐnwؾWM؀%ّ5iڇڇYّfAֱ֬ڶ܊}I2kpv?AG>!Na4x;yqXXdž 1T0qZ&K-+2E6 9 ;~=g>?n><9w4/B(!  bVk  S S y}5P H N'< >3յc[żк{WnB֬Z Ms$N*o.13456!68Q: m@jABCiCOBBBCEDtF]I-LPESWgZ`\^A^]\Y@UyPKXD=6E.d&72 k^R7BgpOmKb/._G@VI Eb/; _sqZ*rS4Դҝд5}Ψb҈']Kްo-=K]EF]8ZL0(R'dd.oc'ZRӽČ\ M~ "%).o38;<<83e,]$I0 O 5 9W?2;*Q<ň®<,žxǕ]7(A \5h!&")!*,b-/26E:h>BEGHyH!FECA{@ABBDHK?N=PRkSMSbRPNkKHED@<-71D*#> btn6:Q*}u 9M  1 V  kuuO =g=٪֒Ӟд{;R_ōu,ҝNT܀c#T5_bg UM41#-PR|H8`> C~ߢQ}̸0!"֢KLjG!o%)Y._38<#6/'gu \ n ; " a4 2'xN@r~P6 @Eeėˏi_#"Q(,/14{7<(@EJNQARRP&MI-EpBm@@-ACEHKNOPJONKIFB?;7"1+%' R&߷_߃L tchTdG \ut81mbXgqlC/9qo  x Dއ:ч͂T8ž Lҝ4ay^  k7Jlv=a{8Q_Tɱ껂ټ~π<$ D"`(.4#799$651/*#AZ 9AHf6<g}yʨ ĂW)tް O1 #'k,X2:%B4JPUXYXTOJEAq>r<= >I@'BCD6CBA)?=;198L642.K)O#x !KGU UZP8h7 zSu| % x<!lW iLLNLڶsͦȦ'6l:DRJC:]\[E?n 6z_stŧҸa˹dMxOvq M fq]&Q,25m6043/)"#w ; 38(uSM_:ߍ\6͂ANWϳYa2^ f y!&*07?iGhNUY\*\mZWRkMjHDA??T?@7@@@>N;853A1?/..;-%+L(X$%! FpN2yݪݴ(o U3y!"$*%Z&'(%(I'&z$m!j4Y) O 'Q=JHHדӳЕe&5ЕK.;v Ain2V2tVt ?V8Vsi'ֶț+gp! RS!%'( &V"Q ! ? $dm 'Ӟ ޗP#6m܏dд ȫƞű~y;ėêVĜroJo2 ( f#*e2:sBJ>P}U WXcW)TIPOKGCAa??>>>4=W;9630q-+-)+'&"$h! WBlNk9fTk"Y4ab!#%'f()*)}(*&"# -zW  _v+V?6c> 1vհӸғ6y#ge)u~%K?GNr#`GJlՂʨn\ֶ&l #&))(9%Z!KY { abr@ۢ|ё9x~jEE?Ϥ>ȵ ǐ)Ə_œh4Rz 4")149]AI-OTWY6XVSlOKGDBg@F>m<:86i30>,)'q%$/#M"! hf B] @GcC0.:.0' 8 #&o(+,-.-T+)'R$X!@BrC#N J *1 &e 1#!Tܤoڇٖr]N]ٖ܏ޫ)bX/`^f C X[6Lh."6#ߢ9, <16n % (,--,(w#w zX 4k/~IR0MёԤb{oa@߱ХXŃl*fS_0] ;%&,3K:AGMAQ"SlT0SQNKHEGB4?T<:^82530.+(>%$D#$"f!! / - EYV; - c#'8*",w...-,S*'R$: -6  BuF}r+Xm"n*q׼KeM7cjwBo! t8dec}(:'سч+4: WXa!%(S+,-c,9)d$ (?| ؏ 2׭L(_N߃FЋ.p™¼0ٻh~Ro %ә.{.[*$I*18?iEKSORT0TISPMoIEB%>;o86&31r.,b)'a%@#{"! hCG+ rN(vXR*d H%#'a*~-0/L01|1r0/,*e'$!_BND OwH'ae:LګC+փײ]Zl_C&kF cf(Qk%3~R*ʲ>]Y ##$&),M.6..,+'f! 0rRo^ʓfΨ-)[SIt M<ڼu6ІM   &,3 9w?EJN)PQ~QOSLxHD@A;841.,|*1(%$"!t c T ^ c M2 0 V4x)tJ^1)Vyeq Pf\"7%(+-.//z.,*(% !3 n bUbJNHkcx ?#0܀,OڗozݠtkMP ma(?(ͫz̑ v,U zK +$(,$/-13595r4M1w,& e )4) ֢Iw6 ۝pNڂՂīӻ`OD{ɈqخKB=!K(D.4:@FCJNPR#QP:M[IE@';6+1-*(I&-$:"[ nMe~%7 gE1:<#T L#'M*-0C2 3233z21D/-,)}&"`  wkj&?UV:؅,O;]QtF8CZ  ?9? $'*-/01X11^0/--c+8(&7# (7]<D l3qGDucؾרt39}>x߈/PJ0<e R N b";E6d%\$ғյoJu3 .SY ^#&)E+u-I./#.,)@$*vUqYeܽ؅ԅOG֗ڦDNԯΨȌ׽ѹҷ%¶gxպ߿àXb=S$c).3V7`;,>B4EG?HtHGEB?0;d7t30. ,9**)n(('.&$#b! S1 eQ.9 ARD FbHHHoG0DA>I:c630$-,X+V**)x('&$*!KS n#ri.P*l_b * #%'f(S(((9'&%$#"7 mu:? 5Y{2tmߓޡ44 V;X8)DLJqHsG 57.j,̯ p82b!$?&(+,-D,b)% Z ӳ%95m@ތ]žB!ڿ¤ŝѵߢO$N#C*/4v8u<DFHUIHG DA==v965311?12d345542/k+'"| K  F-} KwVX Z1!"$$$$4#q"!! +lspO f Qi\XOp0܊oڶYOڡ6*y :uIn6eJ=Mfp?PF xi2#3* Rgp}Ej"2%( )&(N% o _tTp3kqEדZؚg \F}r:6тa݆ P \h )x06;6>A{C@DUDDDeCxB@Q>D;97K5g4)345 6J78998f62Z-("(5 + Kr.t#YQ M )/f'k\t5 Wj;w A *<@q ]gkt۷f Թlף]uݾHfiiy X?\5 Ha 7g k*#$~t:ZGWy@wJm/o!&*P,-?+'!i RN#0*MGNX"xPbe4GG5]ėΨ Z)2s9@DGHHG DA><9766O6x7y9/;;=$>?@@?><:7o3/+'k#>Cm K[L3W)N#* 6qZF:?tpzu ?]/k 6-~+ C*6F`عٖx`QMD6(.^fE8 e|J*3\|#<JT)\;s|3Ozp>o^ĂÐż҃=s @ #C$S$N##\#g#$%i&&F%#  e m\!eGF {p՛ ʞűMܸ۹ q,ʭii%{1X$?)/<38B< ?A BB>A{?=;Z86}43`23597;~?@BFHIKLKIFB=.711+#%~ 3 Y F1B~z=Gf FoT 2B y m+'(k2 9b h9߬ڶ/Wk*E۲Md{N "P_~ U#Pblo/a&|8Ho ܤ"yBKдeQ &A)+,$*(]%!/A { =OTN3x`%K\} ZƙđÚÚđpzֱڻ\Yr[x`#l(- 03577<6543211I11%12~35g769);,=)?@BCDDUC&@>:61,'"2X *s,3xjaBCn(TOwc0e%@J]UW 6#7-"5C='{u7~K߈#$&~1 ]UnnAK=ubY!yEvG'0g.2h>EA U   >Z M u .KH6$CaYc>K $>BRRLiBb * ,r1]!"B##$$4$4$*$$$%$h$%&%d%&&')'(w))**K***+(+(**y)('a%#!dJ4KT l  ! _5/fj<dASPv^>}!A#ExEA(LzXdA|i,Aj.> XaZnF;#_1 ;MxI.1PfLZ"1  3^ lC R W 5}%   J E F 5qzI ld d&Os}i5hv#6  O  WB[ D !  o8fM/7+S\[_> />4a<x~y Iyvx~S V~^e65ݹݯ}6 +mH jYlneVPk%nOJYa)Po!1qNFtFT9gAZ*e =#f Fcb++V9=b rSk E #TY| 4T# m c)219>?ACDPCnAv>:7130-+*1)^)i*Z,.;03A58;i=@ABBB/@>hU"`[lrTZ1YiP&Owۨ, X F&3={EK4NPQPMJ3FSB?=C:8\591-D(D"p q?eF 4 8+incќɗ׽zεau)\|~Mp3"*18p=A\CDDDB@u=:74G1h/2-,,-^.0R258;> @ABgBXA3>;@6n0*<#\ R>O݋1ps M  _<\bj ^)MR!y$*&'#'q'.&j%@#l VPLbaӄƽo"%mȽ+ǯ,Ծר#qvG.\K;X*+#  Q^;Z1Ux؀؏+ۭݚ߷, oF_=JSNl&mCK1 *".7?6DGI(HGEA=88420-+u(w%!El z { ||s ) ` HS?ګ՛CNaw4 5WP4vt(_[R&h+QJF{X| *x]RXH&4hK* %N Wyp 6  7=ݐoM? c+4;Z?@@?=:62d.+)(m&u#b\ h9;E72U-)% !]A 5"#$ #"Q d `ei' ޵)uܤݪKg<P 8==!$&'(m'&<# u o   Bh kw&4ߍy׎>ɜđ82I˅Vu׎Z*3M; 48RF}nw)WP&Ama48w]0"(x!a40[6plDd  VRrUi1O ߘDLk kh%E09?BDCC@BAv?=;P8641w,&S QncG**(Dӏ&SŃq  !i'q,1S5S8<2?0AD EF4EDB|?~;73u.*P&2" muq !"#"!;~i :kVDAk?jg.  :II$"%'):))(' $!N @?L5S'rk6 KێH͂ʭIGĦq¸€Ńdž̥Ϯֶڂ?bo|D X_eM>\dK2NC km'e\{ w"""( k <  ( BA(ګN]~'$*A28;;<={>4??@[?>^;95r0*,"(/ [G`OGc9iP.Lwؕ"dėǐ} PF K$N*o/369:' l #  d9>]]pgHƉô>^ƉsКԕ Der;$&-488;E<==M=>N?0@jAC:CCEA)=83<-(#Mi!!!;yNj $ 0r$Iߘ*:ߧ|r9\"T *$/tb !U e zL ]:#cP E k!`CڻcPIŧĂêRôƨ˅ΉՌ]M.Js!0.& 54 \W^hߢ^>Ris9~kߝrCGۨۼߧoY ="`%)5,l/37<@DH'J{KmJHD@<:5w0+-&"F ` St;+o 2b "TpE"B[ N >A/&A!XNc KN 2/ұϸb;sbc9ecԹWixo(Um R~ O3]6]k'V#NJ3"D   \kWGB#u4W=U.f[$ xW B-lI]y N #{'#+k0859=b@VBBB9@><2840,)&$ JL 1cVa|5}fPj.| a4qlH9.R~jE+ 54$)O._269;<=l=W<<#;E:m9875930M-)s%y!K<e0j -w2gzAV8UiS_c 9}D|f d[MUn_@hN֧0΄/ňŃL3̆ќәտ!8*dbz:v+QD\8K+G~v1; @  SKu`y_8vsM-=aaLw & \, ; bFmQb!~"#$X$$$$4#{"!!K! ?Mnh MGlB,6h\)p(`N2PVe.{XI1  & ` Y@y;#  < 6KZ( 4lU0gi߼޵ݴ O٥\׷,֢զDԴԋllԋԴDՑEV؟X ڱK܊>ތE p*}f.5d2a_2G1z 3 @ M &~8U{%JoaD T}T&4BeQ2n&c`VQ`uzkG 2QL7-(  #(Z0l G j + ? [xlQtK'','dwbXS]mmbNlWd/$2Em%q]H.pfafpkQ8((G}t(`A1r C=Fi&w4fB['6^gu6Y0q> z26i5rSCCg0Ku>|%}ic_t G /TjvoB w " B m1MZf{ SmhN:4:::*% *4Dc6Ke"nE;;;Spm)-tP1Ay8// ^wrww  o 6 5 l M $p7FD (1& MLz,Z pex (j7,e=wy\H:` p=%r&EJ;wS9/*%C`#oUUi7V |2sw sW o^C8P&8ZD *?N| nVX|^;-RTuSD1( ) % ! ' )y-M  m !!;!i!!"""#H#######R""G!!, c 0 $P"n/H7<lw@J&DQK"^  =   BKxT*Sl)2;VTT' * P-e46'"~iZOTix~~sO&h/W) )CW{gRH8[ a!43'+XmXLF+&S7߬@ޡrN ݯ݁R $>HXbbl|ݕhy(^&\_8a%kje[K"!&hb$X ?};Q9i,VG3]||rI88eA,sOS%=Lh,iG/C<1 {-y5ݥ9ܩpL=-ۼۼۼۨێyeA"Aۄ\]ް߃`C4+'3>JUf|w_A 4d5? 8  {"a3NUQ. k !!"#$r%1%%%%%%y%E%%$$$%%+%!$$$4##$"!! M S h!!!"L"""L!!, Yl{dXqvst  S zFk'n3A'FG#Jv\Wg\-,?I\z Gߓ?ݪ$ܮLۓFڒi? ن4خخخسؾN٠c6ۼVݪm1Iy&Kp5t S .#Ms) O!U"("#8##$$*$X$$$$%%6%E%&$$$X$##)""z"7" !!!""-"[""##l#$ $/$I$X$^$?$##H""k"!!!P! OB<` K0/=Pir v o _ I .#1Tb pA;#Lz`7Q)lhsaY64Y1_~o"}-6J>a\"i%lp@g jhy}'mM܊\VQQGBۢZڱs5٪ًًّ٥ٿ?ڂ1ۓ܅$ަ߈zvS+tpq:Pp{|xz8` ; &6GXOF7.*&-=h> D! !""V"k"p"z""#.#{#$$^$$r$?$##C""!~! !K!""z"#$/$%&%~%%%%%~%1$$c$###v#b#8""k! ]V,Cp >sxD mR`2&cy-ek2t6IgHCHgDim6q xK3p\ P}4W{c\uU ^%gkiW+h7o;c#߈mqܞ8ۓUڜsTE?T}ګ,ۼ:VԤ`!β̯͡`x6ZɻAˊ]OZpХWՖ\Aܽ:g&dRE.+#   R/\\  !P!"("["f"`"f"`"G"!!"("["B!!Z :U3e|T &bb^u" C  !$r')+-/1h3j5r7A89:::c:97~5w3<0.o+)&&z#!6Q} dO~ >߷=ٿخعIi ef,+  <dX}m!!"#$/$$$$S##! g-S `Da < 3 2  jfjJ NZ5۲9WϽͻt@?{[y}O5OČŬƄ{ȂɈʞϳЋTԟՇn[BڗoVRY_kzBP*x9R3XsoL*JP#G[:N=qIU_2 m @ < Rw\}no m!!""z""V!!Z! 0M]V G  Wf .  AE>!$:&Q(9)+,./1234{444.3-1/#,X)O&-#e y B_6טgcΎɈǐY)f=½Ţx 3=JQ  #'* ,.024=56x77F76O5/31/-+(w%#\ kA#| KSd4#gpZsNz4y0CEګ3զ-η̵&Ǿyġ]…f…MNɶ|#Ё)*+p,.'/01c1|1N0/.U,9)&$!isk 8. \ ,ؕIz˅˚I͍πFަpz(B C"%(]*- .0263j4844483V20C.1+)&$/!;8S vIU<5jT];qWqIwX)p :># t qߘݠۢٵgsͻ̿d|mȦ ɒ"{X+μυM RՇ*Tyܙ߬zWXC>x`=*0KQ928 [[iI=`7o,Pe) Fiw@ rU9 D S "-#W$c%_&A&'W''''G&&&'G'(*(S(9''&&'%!#"!Z Tg4g %\o<3^f !X6 Y"%1'M)Y+B-.0246s78-8#76}42U/,*'M$!/ 5<!%d:G+0˾v[ֈݯl3#[9 $X ^$D'*-082Z4857K8a9 9987642O/,*')$4!@-, F`!O!vK0K84?1M ?Xm||9^%7?[ޗ`ٵ_ԴIϮ1˩7[ʣ.ˏw!IҝS֧XڦPw<V@u~tp|.?wJxJDL&:gG-\Hn=K` * "9 5!#%;&(h)*+,,,,,M+++\**y*,**)('%$" '<%R2x M + 6UdT )4aP"<$'.),H.1I469w;i<=3=W= Y" #$&''R(|)}*,*~**+#+B+L+f++++\*~)d(]'f&A$"k Os @) . ^n3A%D/[ iv!6$(+a.y1|4{7~:5c>>>=<;86E30-*e&Q!JL v6.eמA.ŧô:+#2ȫMK+ e $)}.126Y9w<>N@QABCBA@o><:85S2!.o*y&e"LU sVCN$(oZPx%JF>bb*7@%TorQ5# CҷmC2'+I˚3ʞʉʨk̥i<2Mт$՛,ڇG  T_)/V~4ZeR8/okH]9QOms]aDqF\CT  U >4!_#q%i')(* +k,-.'.t......P.---,+\)(X&$" m{j>y &K\V,EkB hq~ m#v&*F-04M7;=?Z@[@A @@7?!=<#:I8253F0,X'"e 9zK:N]ku ŘþkepveXѵEێWYkwtkM D %+G0)4v8:=W?@@AB BA@?>=8;K852-)i$ 0h NTx%ߘ}c^cYނopOe$ dP\=o@Hߍ`)ʙFɜn; 6ɒ'TΘ^ԋ<ةJ ߢpdx]pAR)SJd^5h4a~m>>S=<;y98\642/2+(D#9%HvӳQ˟ƙÐþD!7ǚ0![a 6"#(r-01|5S8; <>4>?E?&>=?d?i?>:<;i976!432/,l($NHrty!5ϔuĻÚ4|5,[Ǫ&Ϟ<׷CI -l$h)^.126:<>?@`@o??=<;:D8640-D)J% h l q@\!~ ޫ޵P߈߱#l}|Ga\f a"߈ݠ?׉Jv2"s&:͡F А%ќ҈(ԾK ROFkQO2[ejj( \f==VJ]QtU,C)RcUs{K  W J > z" !"#%&7'B((())((%'G&`%%;$$D##$""" So8^XBP 0 | 46 :XQ{ #q&(w*-0/1345N5X54{321 /-,)'# x% UdۢoGksq sь~$u hw %)i-1h47,9 :s;i;;;:976430-*<&"Gu Mq*C 6Sv3\KkTEO/їH:mC9%-oF8~b/Oi/N;kB(Q]zg cE(J(+ U b;3TQ !t"#l#$N$$%J%%&&o&&&7%i$c#>! MJ]vMn6?8q ?D i yX$o { Wvu "% '{*1-%0245666@5I4 20.,*(&u#  "}|kQ)džĂGT}K”%Kϔێ2 w& $)E-}15>8;i=?@@?>*~)vqMXP2"3q]#  GoE !1"""""""L"!!!P!1! } <r bVP;~,| 6 j |qCCT  JJf }"$'3),).1^355655431/u,*`'%;"Q/ URZ"-GqǴ?PQi+̿©x݆np7$w(w,/221579;tm@7ABC+C^CB>@>:62-}($ 0D| ?r%)oO>>!L y) 9mJ$X>0>:;C''|X>~Ԫ֗RAxse\60%pޡܽ%׷֜զ+ט؏ٯ=ߝutr\'Xtf& I Y  3{ZS 9O'B"t zh"T Ek>  !"#8#l#M#)#.#.#""-! x  5 ! v.Us L?8kVo35  y"',l04k7:=@ BDFGGGG0F$C@j;614+a%EE @29ԅ͗8oT!ɱò޴IT c!P%!" w\t"',/358:<===R;9630,q($ oq Z>1lv\W\\H 8O.#]v_RڇanԚ%ϩΝFќә3ګ$߃&=!$IT4IiX!0yƞĂUP¤ŬǾ̑aoS.M.H^C {  K \h t,x_# %~)=%z l9~  T!"#$%%E%U%i%%&F&&&&&&-%$#"k aL. @ hc)< 1 pB%,28=BbFHiIJKwKKmJRHFD"@<71*# Q; ^M۷;о=1VM" Y?ŝˮ'خ!R: 9 kH#'W*-5.//u.-x+*Z(&$"!'8Uv%GMH-O \  IfTI/sד?eКυAͱ͇͂ea2=i5#nk?-q!ASҍL/@ƣOLN] ?ʣpѰ8ڇy*Z{_`]KKI.`O] 3@uzf c >*-b s!i"("#M#$%&e&'#'='.&&$#   JB"5D[D p$GS ])ks]# #$%):-01m59=$@`CE-FMFlEpCx@<83.)# S t֢yrʉxENϸԀKYݐ{Y m fCH $%94%>Ye "%+'f)i*+,+*(&e#{ :-3 ) 0Oތڒ0̺͒w͍b6Cx4Z{^1pg cr/(6JE)8g)L*מԋёir* XͱlZԹטh/%CRB~fo h } $QK | u_y/"H}6 j CZ#-8P!`nhyIL s"$|&&'&&K%$#g" ]$ =UfU92 ,#(- 03[57y9:};=>@jB*CDEzEGDA=81)xV RW+2.MRsEb|"c+}f2geZ) n? !'#&e(+ -:/B1 24\5r66T6:542/,($ DmH E4 jD$ g4ݹ܀٪#x =}nZ̺( Iؤ#iPda8EZtF'jkh@73%0[D ! * v<t# =6SNJZ`6+mrn eak+  u3<=2 fCgBeT4 # 7 @ @ 7 4Qy6si m:I  i  bZ5|9u y|qf,E4,J3 W|IR(%x;uRqb9('J?YAQH mr^*|>Lt!|\"xl[y:pZ%{RBMk ޜ݁uۉ:0ڍ܀R?UEW_AttK<`N%_(`#h/ xVu}1 * * rz;G 5YS-[u-~bh9bUG/~5HWK  s [ 6pC|Zr - K 6!tG UEscuJ B Y N @ h'%ZS G Dn$<9?;,l`re|Bs8#~!PM,uC[K%Q>lAf F2 z0  DBI6Ex'vV;2c?wwmZ#SfzAR%Vڗף֒Nް`FIY-np9[D _ {:pp M B q  D]I q '  Mb8(>3-L )  v i: % _ lFw !"7!K 9B^ Y [ 7 qAgJ" WA '+.00.+'M!"#^ @7 H Z @d }0i}#ֻ٪ ޑR% t I:I!n O+Ir|#H&),.E/(/2.~-+(&`#!DR4, fjSRKhl`<ӳέÉIŚ̵̿C˚@ȖǾǴ*w@i_0|m@ʉXβтԪۭ@ZJoaOlm + }  ; + * Q#-v6M+9/O,3H9-M; 5h%@),..- )&#e JVG 71[n dN$S,49b<=<:Y7,3z/+'# QOI1esH { .s 51IIT<܅MߘcYh=lm,3RIzE =K0 +w#&)- /13z4W4433'2!10/.-+*)d( &%%$^### "`!!\ ' q=z8og<ҧЯͶ̵˾ɬ|HË8J޿J,uň\O)Uyk3{Թ?տ֍׼C9߬DnK\&JFrmNY #M XN-waiZi`3a.ShX )*+,|-:-./Q/0v1D2+324k579;=>*>>>=<;9>7e54821I/f,)&"!'6I qk\RAWȂQ+ćUpM˟˾ˤvG8R\fk˅˟Cw̥Y M )փ -U@2j[X!L\~2^/ZP 8n^ Y?686@)Y dDt '7~ <:| ]fi|Y'R0b6: :85g1.1+{)((r('%Z#$ =s!'.5;P>?=82 ) y  E ! _o*KXMLV40De|Rm S Y %HW]!$r'q*U-/k1358G;>DAEaHdJKKJHZEfA>c:7532~0/-,*~'$!+1 6sߢLCփ]p#LРY~҈z2ȇHƣuƭWcɱI͡2Ҭ{_ank?ZzBSb1=dIo xerj^gZLW{ %X}Hq!C5 -z@OYp8 9 I3g&tX)0$34320W-?*(('''&$" =p!i&-}4;U?A@`X q c# UQq4*qc8߷|Q.#]XU."'f+/k2_47`9)p:g|HN!60()? -&,/AWDFGLPYTVpWRVTQMIQEaB?>:===v<;:O8=520C-+)'%d"pM!Y].HIinLD)Ҭ^.ͻCn^ǹS΄ӄۓܸݴޡP(-#upKd_D ,v0X\?:K(RvP=Y;r4 ۲ڶݾ j"`%&%n#!!!!"u#M##H! #)18V>:AB@;4k+"Y u - 3T QZ29lHCXMտ c׼cܮނۭ(K} xMp>!''8-2y76;>*@CFJO4RUW{WVTDPLHyDA@"??@K@AvAv@?<96d3"/,)&'"Q K \Lk.:Ep$VogdSlpKi)GwΎ?R׎I?UAT2L!j=Re1j!w8'|5'D6m,2)Tdۭ!e 94~ۼt[ QTI(v!)J19M>BA>8/`%~ ' WA(-;rަҢК,$T}ܩbߝ1 e\{?b%6+06d;6?sCGLJPT}WYZ2Y_W)SOmJF]B@??@ABCD CB ?'"e MV +S[}܊ڒzֈ:ԐP,=6ؾۨ޻.[W|Tt ie: RTAP} G{d;@E&Sz\\(lڻ=;ԴݐE#.!szێګEdN~ܸ~т4 C7a{B3Rv;  D %.@5;U=<[70'=5 LPzNz=sՌ7ZUQJn؟=_~ M(5d5 & +17N>c?i@BgCxCCnA?<84a/G)#}Q _l0j/i{`0@0>\yڱ٠]ً^8 H3k8w * 6 $I]j%iEܙ/ҢT6Ռۢ%,cܔ 36Y:>4BGDKOSqVYZZYWTcOJE2?:6J2~/-+*)'%"M\a KF}2^pC[" NVTd4[{f* ,p  wf6Q_[$ $zp zܮCK֧t=ٖ|خVqpEڂA"_L6#@i4xacܸX%uh["~>  b _!Mc] *Z3(TkHD>d(ܤ|ZIR.zP І,Ԫ׷ݠv`c $+f0v35544.43457:D=>@jCFI[KM-NfO%O9NLJHFB=83.*1&V#$ k^3= [$^8mlDMU&aR-OW r5}K)@^{<64'lD BL\@a{#;]7߷8T5}@Cyڍ܀~L2,N2wخԴד|9; _xS!,!!~_ Fq? V *vu PBW *M4ɻȠȿ˾7WԚ տ֬N܅ތ;߷xnOmj##*0M466767,66778:;=g?@QA8ABBgBBgA@={:O62.*1&"p4Yop ?:0eG-$},i C]B AZQ4x';%\k#jm +e.I+|.j,۷ܮ!<.__Pr>9 <`h/ڶՂGC\np )H"$m$#%#DW+KQ GF ))}~bȑ+ćǟ OۄDh_Z[  (.3579|:;6;<(<====<;:x9 76420.,g)'R$![I y gWCA+| k F tC;)w !"z""(!i ON8hAh K >O!@""shWm&A%WteRB {L!EQCO؏Wg,x hd"<  5 5 a r݋ ̑sBUjBïŬ/ 0{ۼU!9WCD '\,035799:^;E<==>|>r=<#976481-*tM@{C)= oe.9;_ y!U !o"#$%i%%%O$#"- h\&our T`6 .Wv6|cEUP%vGpX KND6.& 1 4W֗Y¸=ʉҝ܅C= c$&A%"e5dL$.f @Sxf Ԫ͗1sնwuȷsR3X???><950+\%)j DxpKVz[JB :T #&)n+-/022222s108.@+(%"i2   w69R!`> ٺSۢPp :jpTKA  u B uw'F̑ޑR cK$(*U)n& 8 N*y/anSN#>ޗs'-츓+ޫXŮ pTڒh 3w! EF] f#>'+(-03<6+9C>%=\;85r1 ,&o ! I5D3pU?Y^,?r߬maSWM]& miw { J }q؊L5!o +!&))'k#{#I J)9JP,E vqmGǧasyοZXy 8v"%!')*+L,$-/2U5S8G:=>?J?=M948,$?TXܩp)QzPJ ~~ "%!'),C.147:<>N?6?6>;72,%.bRpt-yPd7UR4 q h  ^Gw_02b&h8V# # _P#'*,*)'%J# !!p)rm*XKVm6u\i,ӭnu0ˣL!ù̋Iݹ# {mP"'+.!///V-,4*1(&"$#$%$%& %$##>"!~5 tp?( ͜΄Яr9\ 3_ &<+-/u2579;;<<<<;i::9M876d43"0.*o& %J 7Nڗ*hd٠NHj6{: ) ~ 8gq-h o L(u-;&{1;O&ёEOi. 3p$)T,-,+):'a%#" t  ,&?BM4zq(ףдxaȰeb-0òsȇٖN*i *~#v(-02331^.+-'f# c5bm&1(Z7q D+wh)ݕcќќ%خqi ) 05:>I@BCCCCCCYBA@><:8L52/,/($ dX Z]V !w E')tey: zrE;  N :^[rf&\#S`9NB3.+ÆS4 $*/3554371.P+ '."fP]5? [rNXޜٿ͂SRʬﭯbNІX'hCP#)-1%3K33Q1.+p'#E?1"+.sU :ogTeX [>ڦײ؟ޡWQ r (06&:>A{C@D"DjDyD~DoDCnBgA)?=;;8-40,( #H{ B85'׎P#ܤ1ZP6Y \  <SB4* ZLh\= Iİ-Ϯްzxʽ`˕Ө28 bA }&,1I46}652E.*P% ;c:U V{X }Y}YuX`qTY #+1r6:=?s@<@@@@@K??O>=l;9630+'G"1 ~`B.CXD T.ڻ6DX>p 8 IUA<EL? :cv!9O-zD"ȑǚ̺6Ck").2&444B21//2,)&!i!MY_pQ.lޜQnnޫi/usqѸֱݯ6v Oq#1@"s6#)d-1N3j4#3z1|.+'##9 *Sah OqG2G.r[K] !(-c15r82:0;<=>?J??x?J? >=< 963/+#& / bC#ؕ׼מ8ٺ1g)2O)w ")d |1AQ<srs  =DYzKNVq(;9h#Θ\?'}0o d^#*/(3'566n5 3A1D.+'#)J TZ(޻=6^콣[S첪Odڜ: :#8)s.257"652!.*&"gwIAb } l])EoޑYLs, >"&Q)d,.02468:<>|?@AfA.@<>|;840+&!_ TفVׄ؀=bxSx??b 'OVv>  Gg;5`S& Up"'dKӣ 4ț7 + 7&-Y2608=8753A0H,)$M 0ego7^֗!™xF Tb#_:ٖ^hiI.t#)O-023<2n0-*'% #!!"V#%+&())}) '%E!(- 5Gz!YXPۨܙ#!5Knj hW #.& )T-048z<7?CJFH@IIIeHEB?:50 *#"Wifms#j݆Z9X:ۉ}߼HSAjmg  :+t !'! xSo f$#60t{W-rJ<^Z9ۘ&,03431/ +(h$ ~ 81E%EE7|G ."(z(Js2dh™ʙ ۢVA+ )!1$N&z''&%$D#b#3#%1'f*Z-1479::9|73/#)#[ [C`ڗ,dw9a* ln")/6;AEILNOP O]MKGC=8-1*#K ]e*McO/Mߢ*% *(ϳ^ [P2Z 5!;"#$ #" 14BC2Q30 3Wm4-ŝXǽ'zio9I#(**++)'%#"!d % o8'zNTڂёŹZgͩϳ!1ê4~ܮo +t "($X'+05;6@'D6GHHGEB>|93-& DA8e]F/N6J \"+=3::@EJLNO4NMKIAFBN=9/3.Z(#yx wjl(XJt߼4 ĵ#:ǐx=DtpG  bhA r3y v )o6b<ۓ`k#՛ȿŠ6Fu .!U$'=(w(w'G$ }& SXSs 3 vc+ M?FzֺM󶯶gP.dİԟ%('4 $)E/B5;AE-GIkII`GEC?<83/+L&"r O1  _"m'\ E#&),.02+3456766Y5>31/-*,'# yJ 3eI(>e%Q:ćlE)+z@Ֆbq`nv F, : vo/T z }  J  ht?[yA5pFU˳QŠİc͜S @ }e^{nw > - 8e9k3ІJAgĻ€ P)s5*/N݋9llU5ct\Y E (r/6;,?!B9DF$GGsGmG%FEDA>:63"/[+'$ f` TiT\X'bf_.`@? 5;!"#$#"!!6 Y 5 5 m !"#$#" 8 1mE5|޵<4ҝH9ʞɍE̠ekڒ()ޡWJ8. M " -  N%=hh]2p9Im͍π҃x,p^( s 1Uq$ :K6 (z& 08?@'@V@2?>?<[:586@4k2i0.-+)x'&7%!$m$%$:$$$#!4 bU2J O|,HWJo?<  M 5.ON7Du9ndIݠ݋mEߘ߈ޗbܳ88m0 9,Cd2H2/Nr8Ef 6 n3ݠ%,ٺݾGk,/u n tV6\ yLnD# wwNtFkSG2߼QC=e.T.X uu9B]' w1"[%(*,.d/Q/0M01233o221I0/.--^--%-.0C2 35C6E6i5b3A0.,]'#6] r6bRp_r{~,f[OnWgkOKo;[dAi;N/) +*DZBh$-V^+gb+4Mp+K grHgN8w E!$ nO!"$%%1%&'f(h)+k- .i/2/0>01c1112123u4.45b56!5531/- )&A"+D%6 E m9b~!E<Gq"SDիE<ׄ=ةنEeްp*O;B]p 4n{=*5 [|*,SuHgIE "'gS(-PK"" O'Z>Ul]9w+MOGX/?5 |?2oN JES-Zx Ro = xh~SU|!#& (9*A,$-/01X1r10W/G.,*)'k&%1$%%&'()Y))x('&%+#!qx1 .s{r\o*52eh׷ԟA*˹˾̑!͜Ψa4 ҘLgXՇՠ֧ײs|Pu \_]^6xntQMc;xn0&A$EM\/^~W8o7Ii4 U9=`3VI T {p  <K6B9f8Ba.=2#T p  3  M K JMgV:!#&A(*,. .y. ,+Q)Y'$"!6 Y % c !!!@!P!K! M$"Vf@  `|tidZWX =,g۷kֱ[(`͒X˟=`~+ȑSDȇ;P.I׼ (iz=9Otr~L0V06 8 3   ) ' \6'=6mZ{U h  lS|>4^ d B'"d{|F 9BARa3/T}!DK*<$ V <mNwElxm~oC "z#$%Z%1$:" w8wMa ^{}P # q  oH*E$,C`k Ӹќ̛GAs/ǀ EhlŠ”oRx˾xҷӽԚ^ ֻoMّ<SH}/Zjam4NJ 3c68vUU Yt~66  w  Cu:D * bz h \ g ~ 4tSD:|W #p 3 : i Tm f =  _ 6 uZm1* sf?jGzk]]V @ z mx{MuMZBkS.Bvd_LC# [ s w ZT.B"JCIXCܽڻةֈ\KКVPń˕ʷƽ1ǯȌ0ɗ<ʨ8̖^ Ψ\vBڒN |? ,hctrU 5 y u  a   a MDC{\   u r ikm 2d/ = f> S6wm63PZ$ xss S  oQ3k@t}Sa7"`k\IY Xccq@n' t W z:F!akBR\.ogT`vuEX\F5IrH7'~O9Gtֻ?ԚRԀ յi׼Mؤؾ8j٠oܽM>܏m2q~gMe2puuzWW>?'L  } 6  Q ` e n]g)VVK1#g%XrN\3VLW 6O3<,u M \ |io\C>/9q +  M$/RNS7@D>BtYb 8 ` y >~~oF }feoJ*Vy%]YOmCX/%Xc "jx_2)Ix3W,={pR=G{"~E^vu*iN'q8;#%$fڻxێRߍ1aٺۨk 91|0b6oR9`eGbEVMSXXd !  j G tox} LoK<6Ae8QWW-i=Qu]=Q$s I?\.I6Ka6 f8]:wl2/KS ; E j r l  u, >u_I h }J> j -!9>f *w=^NS4bsoEoQJUbh0$'^|)By8v"YHD7;Etp_Z z-dM^Z+OZ"ec476gi$'= NF vI - 6  bx 1/n   Z, 1] N YoS(/Rx eQP*I`4Z'B Wmk_Il,H;.=z+e!H) TTpX U6goP"LXkSjcg\\Y]ImJ* ,aK|&LMq=w@c]@ +V` ^ UrJ . Z@ JsA N AWMjz"Q FF 7 R / B  vm ` vQ /6  8 q r s W<< 2 l [    o .  <\  %|E ~ N @  s @ A N  M l @( a~sw U  g { . _ /  % G B 'Lo w4y BVPM ~  EBZR_d2+zNR&8wR'R,PJO8Vz*t( z4e1h&sLK %qB%,kd4>p=z3R2 {dL& W 6 ":2i+m |3ELw@2FKJLl zCN5'E>%(9dT=>Dw_.b|eM{fpaQ y  j 6 +>  yFt [ i ? :' >U/  .7 !j u AxQ q= DW a0Z FwN"o  A"vt M c R 1dM D m:T2B)?);  Fvn i  >G|7DhH  h\ds,Y]%#M]wIkrV2(<JertNm?V!,e~D(g;to09rzWT)rQT4l(;'[TO/ E 9- Bm v f# *$8W I lYm` l ~03FWP_k:u.R{ 3 Wb{p h@@0 (vTeoYtKr|G  ^Tdd m3 v h&Y o XS) L1/3`cL[*=&!u0f#T/$-1 jJkfzP 68v OM^p_ dn^5. m(  H 3Z45  TLcTCh_`mp_/W]7?E.%9\ pskUg8-Hus$1YpjL[q$l@*x/t{KzKaLy$z[mgS(A\c&Bp|KM=3;ri0n4+l30St)`u U%S<1 cf3E|t%]w^$S )e\xN<');P<_fv',Co2b$\O9k '-dnKa*2DP@,:k\gGB<Jego c/.Bn# gG=DP W YfP,u Eo_ Ur{FIarK- F' H\ :Xnw J _RjJ 4n  S l U(Gy\l Rj}S< ct;6- t@q= m8lyo $l( R6yp0 C xDm[)FgOZV(E KHTiEjpf ?cBDD j!WTf3^QtfZmpa|=^65]FKDa>T;{0\wAW32\q:4x zh 761( N K= fWyAfY\ ?NhE= W qO{x E"G `Q'Q  7=|{0ry` Mny"/-3)#IM"R}[3=2a ?R4N=a6Jm``e  oq% \ Z9m0f =\ASd3Rx&av[z W|3vk]3x;89[6#0< o6:qRf] ly fF&>s#qR 5r7,7UYP3CAR}g3E q'xd(QLIA/gIiTc(iJx sk=D  $\nq'EnJa-oj:P mLxC B>')]R)N9H;y. * d~ 28XD|vXBM8"+TB vk\])f b "^vt^1w7 (:kf]t0_-iA':oBf ) }S0!OWzOam|b N _ g9)lK0e- #6O\6W j %%qya!3M&Tiv'&z"GR(3w&?KLpB, \ Uh`+G Uto_YGW'`=A.2  H_a9"  @R5e YiR)0U6rr^ Y *'9 Z sE1 n YzFJG-=}+H8<{2jknsOwV P  ~mxH''%  Qe>(EGTO5,)MK]tr 2 EC 6 !,f \a TI kG:PD# a" u5% Pw@8K 3 & vTdL(R3M{4%.eC%LB =T+oLhllIa$@XrqS-b8\L+),<I H ^H&Ow3AdFRsC~ ]x.4yh*qp I  9dY g :i'f WJ < a}/ D  v ;dp?| w l$oA"0''|Ey4.*2L B  m \ '&G^+ i?7<Ff&=f"2!^~J}hdNNGpH,?`Y~#z #==V4]] Flt\]"dm="KS6I +. >_}&sLY $LS m-"! iIr8$;,n0H2   \6azF ;H)3ND|fsi:aK]J~pl, ` @U m "GL D *  g ^ Om)LH R DkL2F R R | H*j&Oh8dw4\2t! i>  3P UT,0K^W9=(C1C> ;C$c x >|aj 2JS+#x~a X{ ~ j :&\RtmbvGN^5 g ;|$<S\4%AN]lLp[ShF d  dI4Ea @l. t byw\ak#j{eLa Myp<: DM# K/ JU_ U[]s[3hK~E;S(KlX5|v_)GTywv*au1zo  rIs'SS {  8 :~o^"x~KW?[W/ b mQ,muT%l]: g8~M*ZV\=4zG=?nByoggC1 +I~ ? !&vP(1 v;`u2] z}#Ko=Vn@oy H8+ i%^Uer$yIB!hvJ& IPLS\i N Dfx%kM &b|<RftA,PtB S fR!Wk EsI$6})d i">f  5F+ ^ @ W[!"  j !!,vV y] J.nCMX z, { XcVz  v` C : 2 u  8 a /bX a : 9Z3#3 o)3!"#$ ##)!   ~hr1GGO"- r SW8J%L }׭տ ҈?"&ʨ>dïG,J9羳qR)k/5o¤ôġōlcE7B|Ϥxu|מٯ/oE MA: } = v ) GEU 7<W\v9 g%$~ Ra{{` U_S HM!l PRE+ "  OB [ qj`L XCp vh^> s!t"7"""""L"!!"("#8#$%&u'()*+++*)(4&7$" T=-r +Gn$mUW: ѰΘ}́˚TmR?k[޺2#gI&̾r:©M!pɗkiυ ۉHOg{?XT_#vf 3}B* 1`F37NRaa"F B 9r/!P# c M<7_ d6 b @ " _ y !zEb5  @ kV R I i 3B  3  n i EVq*eB  } !"B#$$ $%~&&F&Q&-%%%%n%E%$$h## "(!6 +K043 , zD#VJ{*zt}o؊հЋKgxSbƉż0RV<`!`` @9$:1 ǪwOKqΓІұea6(1^C~)}mF[ %/{u l  %a {X9_Z3 } %> v 7;W ~0k m$&j&#qU! \ ~"Q$&'(4'3$!9+0]~'\;f _ !  1 d   a l R   ` B/d]k5 fXw !!! ++ Y!"#\#v"!,\mD ) K F A Z m Zx,OޜF/g(̵[ #x4Gc0޿mBJ6s\å#>cɈ%ͱQb޵RaLl)&&H v m ;  m ^ c w >W~PF/? ]k5@ .] v"a( 6P_[: e*n  W1s 3#'a((]%"k-!6"$ $$$$|$|$$%$#"k IJRLk\e7+C 1 WQB    DdhvI ^ A u  @bl4UjDh#7}g2Z"D =P\jMK޻~=%E͡V&SǴzF n칽~tkb|%k&8x֍]-|*FmB  >"HHY% l K ; ew('_Zq 3LT_s ^s {8z {u\\ Co P ~6&.4M89H8 40 *&"` $ +!#%''(()5)n)))n(N&V# O[E6h u 6i3R 93tFQ(L    ' 65 {[iS4Icw6'FKW vVPIs#>jcݠ؅ Ӊμw`ȂEVyK"sο4lユ¸)+́(lѵ?سb q`e`9; \ _ XE@] q    R XEO  @%W+ /y W&w/G Hkb N$h)+,,S*'$qR @ #.8z@FgI2HE@9w1*U$D,G #W&(>)*+2+#*)(h&$X!Put Aj'&vQBzv6%aI ;W@etm0eu,Mڂt8^ T̾JZe0/߻:غػrWxE̿4kEعcPGB{)I:$o=T J De" JbrAKn RI}jb,f  !8 *|&-^25 67"6n4v1c-c(#\'30>9@F.I-IpG0B<6@/)%" : D ! =Shk %%!P:^x#GM-NQY5?%Z g:3&?= #'+-%--,+V)}'W%" 1hzrX3e nCd-EDV5ٛK;3bټ꺴2Ueu9" dœdDê>ùƭ˚΢Nؕ۷ޜ=mL"=>:EsLb  y j  @ I \2 V v w + n y + ^ K|v[&9+Ld  c 8^%&*K+)$*[]r G|  (|.3z699:;;K962-m'\!KE]!)2J:T@DFSEAB;5._(D#R  5 tbk}ZhauZ 2?.Vax/zGfr',C{ .#%Z&' &'$:!i  Mg@ "#%_(*+Q++G*1(&$" l hB\vH+ YU.~=cףԅѦ2ibCy ȫRWd8ܺg 6|cʓ́Ϗ]оOA٪ܩ%=Phkv!2 =c7 !iO| G (+03a%0Kfu+=oQi1 !d=Ej Cq b~Km[")-.y+%y maJ; n$*/3K6+8Q9:m:+863.E(#8WSp#\)i/58:}97P3'-(N#\- L1h> e5A DU4Pp^vo2{P h \Vz!%')**)}'M$!ys.fI8  x@ Z = lzmaChHڂj$ȖǾ*s[esȌR^#Z00ėƙ#͜!KؕٿP!' \=?@L b \ .zV#ZO8a bB{E` )7T  i !6'W+{-, (>"aC !^c 8 (.!2U45>43211m0/.,*<'\$r! O!1$(9,03430,S&u !9 kA}w gr+KFNi)H4^O)o#Pm-  ou3i "$%&u&$#$ \&i\LKw |p1nIlo&ަ݁f2F!{O%oTb(ŷƸɃ̯ ̋˹+ȿȫn,)gϮчzwoS1mߝW T9D~2*1 D D q<e&D\WX! /3tgR[$l,;N=%\Ic v m & ' OJn 'Cku"<%Z&&Q#gz 8V%L$+Q0466542s1?0).-s+k(%"- $*/3-554.0+%Hjj F ; I qK1P pVmc?o~sm:by W d z i "<#)#M"! IHbM /ox!  C>Zt*)ܮR0߷݋`سտ͇ˤ̵πЪ}'!ѵѰѻѻѵin8+(*'O>&vYA/&`+,Txh+/WP: Rj3>>$32&)x++a*6'#1h!6'B,02 0+$: m? /"[(-I0$123596s7,65*1-?'B hoT GmHO|&,]0>11-)"}m  E_n}3&& \߬1ֶPK~ ^ - 3  hEdm*>H!#%&%1# Yyi%  *F#A%7AeL(VY xًPՖԚl4 `Mm޻IF֍CZϞυzaμPi&Jμ_kR%sjؤٺܔ1LWD s6SLw+N9NS>>X0j-Fx]DT0+@iP{B*^g1 H /`:U1a8Z;F.%J!%)-c0q2Z21-( ^sB. T0$+2/`0/*$^2m Ws SQ!$(,1479984/Q("YM$(+8+*'q"z Vb7.JzێE^&1k80aa3 sIFz8WDL#csD!!e#\&  : I J U 5V$9w{`! 6MrI9д Ցמ׭W~АO9ˏ)ʨʨʽ=̵ͫηϸоѻҘӔԯ,؟Eߘ J~oRRM 6,)p[781G|BPYmBF4WQ`"$l- ZZ 7 1 c ! 3M<-uX3~?5#):-0l11h/L+8%~4HI#)&'%!Zoo@L$+0\23-2234\56641,&9 &%.K5N:<;t8\3K,&% Q !s ;0_\cD|\?KT:ԹKO(  8  R 8fjj-  #f!#$$^"+i 8xEGZ0eeނ &[6υё$ٛۨ9ܞ ع ӔxϞ|GA@*}ėoBЯ-Sؕ؟a .:@()`f6:D Wg>t5|NDrjpF 8 6 ]@  tvw^K,u Z | \ ` O ? { $ E  s"%i'))T(]&j# "+"p(.2J554q0+V%!hx# 'W,0C11?0 ..!.01221.*U$/ Qb,$+{04530+%3) X.#->Ahz_je۲!KU O =!  l = a x"<""Q 3? y$fP6n1ޫ2 =oЕYḿ͍(0ӏ׷%ؤׄт̿ʣquKi(HOϤjؕSّr/؊؅gcۼM&.+(I@zOoG  '3MYP< )  U ~ y  ?_-qv8*5e   `#' : ) b GNJ"2$*%%%i# PuLM &F+f/369/:;961):qFB?AeNߘX A&1:@DDCA)=:50,'M"kk   &2+0b35w542d/[+(r%#l! cLnf?Pi"BQ\t5ǯy@CˏٺD]rx  " e ^ 8B16 8  ^ _ `2$MSף΄%GZZ#Ǿ]h׎.he ̑`:SX ĵɈrLԹ2b"f$R8F^ٺ|sۄZ?L2",!at M CA'ogc _ A 8D:FZ: nSTj@ 2 J/Olk/ [b3! #%'3'&%Z" %1w* $(X+.123o321|.+ %qUk%G(18B<`>:>*<96T2/<+)E'#%$4#! |!"%Z(*,.U..o-%+(I%!/#l 7[<-ޗay;S**ҝ͂6)u ݚ)iBH8- F=~ ?wOA|Br\ Q {xFp*a6F z cw*I vɈ:ǀ>b^6'.XsZέˏ%z,?|OuÚ`%7| eյً܊]ݪY g!BX(^0 l W   { }    { v ) z  D 2owbm1  Im|A-zudT :7< !"#"u :3$ )/5:0=??>w;5.!$SgzC$A!6,71?0DGHFqC>?82i,/&F "&K),].Z/L/7._,+((&z#!q,nw 9M#9VKEI$OSa(Cc3F?FwI9}]D, i) MIETE0&MjE +@or h,U z6_D=#E|a(?ż3Ȧ.Ips\JWκI0Kjİumʄ-Ro݋ZxosB>k $  o \ # K 1 Y?dz  [ &}5 R  bdTxFf & u ~u>+e%`=) :!t"$|&"'()s)s('B%&" su<"%*/k48:*`#i amv*t6A J(18=M?@e>;71,)&!6'6@  c!"##C#."! 0)O 8~)ݐނqz24Q͗"оԋE$b:c< \ > n WP}55}1oj WXE&=ŹɜCi ÁÁQEV2)³c8iC'ƨ*ɒ?~DԾjV/bDdX[V&*f ^~3{#KOX w5($~ o ~  & n " u G 9X>99/>|}eo%do)Y1]wg)!;#>%)@,03689H87Z41m,'M!fh  p w%-5|;E?@@u>X:5/)#96>!#%&'( ''#%$:"<KM^s 6&x S'vM$дAjٵ )No[L\?ln-x 9~~ j CjS^:^6܅NESq)\mͦ<n̆BɧOeT纪r@'JCȺʲ̠΄v҃Ԑ֜ؤڦ܏NA5z+C-W [m* Q6j#k>h{QyIbp'p< @YE 8':{ll{nAG9  !6!P! YS^"p%),S/#142+10)-m)%!U-4]T`P3"%(X*,S---,+(&<#M hDA.j\BO %D]^ IRL'&(1v]*٠s۷q~Y)N'\HNxxDvINm1Y v MV)6P k1sb6YCd.*ӏ6QΓ͍O+ ̵Xa,sȌgī9%SA¤:ǹɻe՛R"/ yVW C(q<  Nl.?S)Q_L\4Z' 0! (|~#fp.{{[w5A)z>4E7Z)${eJmEj !"#$%'(|)*+k+2)'$!G| e U  &$'{w!E"["#"!  ?w y n hRSI{7 @xR^=5>.!tP9ګګۢܔK 8x|8m{7~nVL}VBvN|$RP&0R1,t=-`T^HC:jV>ۼJ)ֻ֬EՖԚ-cπ̆́O&]iI*β. ч@Ө/k}P~eVE  @^rxxrHo1P[h:vfU!E$&&%&" YocQ!P"f"V! xg)M + !"#)"!eA!lH"(#$$"! hS["%O'G(/'&$"QlY" F  U ) [ j Ja!p(,-9 G>U a,PJ ~b7C?Ik$e"Y\`,6^q߼ޡNݚ݁ݠxߝ[MwgXUuGIr~.JWfD3O#;Tbz-t^Rr>r݁ܽܔMݪݥ )J)\%&׷Bسmً>q7vԴՖ%rڦC 3hBrBY'm\sy@O0s v sGXKEy-*d3\H6O~k$w  !'! 08Ak h"[#%%%Z$!l=-{j)#2zgShX.) 1fqt \   Y W Q_^G - PNvBhdjB/H0 6grCG_2`%M\^;b]BA߱0ݴl]ݥI6Q`v]?Fu.3a>0e(i c|vcPL) lA18n,9 _E[Dݕuۓ&mؕ׷":csNtخvHՇףMDZ \ݹڂ5݋e0y$JvZvM \ >(\@ Y 4: Lru)!#R#!'.b%;N h"$D%&%#!Pu4!;"#M#g"! sK9(\#dNYTqA6 E .$B]]I  ]J! Q SBO6: /  ~F9s3DA gT1ffMT 9uf~NQm[ޜ9Vf ;zTk atz>h6cFSoMar!E0r]c0xZ& }v=q%\KXj߷dߧߢ%y5%BמPA`׉מo@՛DIՠ&ֶ'ׄ^ar2vNiKEK|  < q U Z)IB@t !!' Y  Og3 5|bbOU +aK?;}0,AsQ&erSI o6tQ\Kir f e 6 @ } ""#R#C"! X^u_76N  Z)'b+0@ IR. ޵޵ouM%% hbu!zIJ~Q.*@`lmT"L .R&"tjxS 8F+ <1%M(>v}6m.xCڜ%պ1|iEȺwS4 ǯ{H.HNjSțȿȿțȇ3!fԋ,/a|nVE>F` g N ; " :~m } wS/4cZqS@F-Xb L46YEiPf:1u+V=:n`& 6m  ^ 8<y1yQ " ]!d%(w+a-/k0g00/.-Y+*)O(&&%$?#q"! Z|`|`b ; * W[( j0)@a7JcXq(kYi[.mT<8p51` g D & >E!m (rtU) *[އܩ#7xٻc%J"9sR3͗ұh3~ 65 ; K+_p>4}&_ZX\7'IXW, l 8   ) M { 96Mk#W_?q4osT_OU"k$&(m)*+a++++++,C,-?-.i./L/B.-,>*(&$c!Mv&1  m C(;s#[\m]a0IBn9YdIT#3?Oj+Y  ? ; z o F "  d ! I 3[ sP3e kT̆V^Ƴ,”`0ջԺ-tʷ:ζcʸ_4kYa}JԹמx4 A]~ Vs%#  YQ`  % F d|WWSG i EZ=w5DOD5:O^sh5H = F < lbT,Wd s1BN8L!"#%J&'()*++a+++++++(**A)('&$c" 6mHS#!/ 8 A + `H&=7~ 4{Pn&67Ie\ 39DZk M O Q = %h&X B z  + $7E{w`D^-e?טhḀtXQcuXƷkQM% lѿ2ĻlFTЋ`hkS\A& . 4> v F O m N 5 5 Y E j  W R ` + } Mf7uku g r >0Kye5b r"sF-M`IF>!"$%!%&''(%()*+,----,+u)(4&z$#l" DD W LhV48)=|QP+s'te"juHD6gZj+e?  y md`abO"GpQj}Sw 3 k?|?F݋<֗=VʞcVs™ʿz<ճaB9ϮV2" #?Q j IT04(j # ` r  : U 7 3 >OsT < 8+'/f[Q<\*k  K'L1 !#$%&7&'=')*o+- ---- +)'%@" D  _ +  y"=4C\`HA#7A* +Wv*ML Q a Jq, Z!;MT # A  ee8TMݾmq˾_ČøڳO㲑bXb ʹ׼0`:.'+&]ܽQ*3~afG i d6`U'}O00&4 \ F  - e  f v  2 U w 5 %  )._h9xA3aw V%2DK/!#\%(* +--.,.@--m,+*)('')&2$#g!S} u vb#&=CM)4yVkBi IBAZ341W g @ R}iukS:,=g }!t""p"k" !d f#;4 R 3o4,$xkrҼDϞ'IƄÚkU^ma<@puàP.@˅ <ګq (\vV  NbI  e ; S  LjqSS5 {!Ex W$ _ I ]Jy?vF]!"V#$#####3""7!!!" "#!!i x9 @x < MO lW*   TS 2 Ql+L$g{l7o5 8a7M/6sqbn~k|b  /\S ` qM4TLߧQ!eέ̥6HZx*.˸~ZEKtƹG@X³hǚ6w66ԕٯ=޻Zz~C3!tw: 3 ^  + ; 6 ^ bW+!vG ]spw`C6 > Z u # $%~&&e&&&&&j&<&%%%#"[ II *<:(3+a v6zPS >,5ou>Z-N|4vB-JDbB-`:,- !"#$%&&V&e&`&[&<%%E$m#"!Z1p ZW+ܳٯ{ϩ5^!{ R@ԷYT}Ըi7.Di)m{TGnϸveݚ߼b2|0tDMx  ; Q 3 |!FP} X a K Df}_:\jo8 $ n 4R !"#W####.""u"L"7"!! {fV 7Xd_788 e=/:t :w eWppG <+rm>ak(GKx ~Wg D!@"<#>$$%%6%+$$$ ## "k! uiIt (7h SԪyM,ǟo]yɾ\7O 'ٷ󸍹[C?EVqa'̯V z=NA "2BRm1B > : E Q \S5xPU  Sf^QEf4{7E]Idd { ~ sgN u|  T I /{e1 5p%P_ fbo Q:Q=%NK6 !++ *L&5K=q  ^ !"#$|%Z%&7&F& %$$ # ! WSQU \8u߬08ҝ p/tȠHKƼ;uL8ݻT' &ođƔWЁհ3ڜ;BKgsB^T n < r5o)hx)f: >  gP%Ghlgva[z;uZ * Rs) !"""7!~ /\X'6 , I "+mdPag^KV v r In '@\sZo'"G\` Gw O m s !!y!"f""""!WN, h? #ZiBZԤёZ̆ʄh7a仰[ոZԷY򶛶C$ MĽVaD` 5  5P(mP-F"&^r # ' y  w ? %  : 6  8'71'W !"#$%y%%%~$$"! %<K'= {\ Acqe!؟j/ /Tov]:8l7weS1 [ uMd "$|%~%%@$#"[   =h^nRy^#3x8F  "k#%U&'(r()E)))s(]&$!;}~ s Z ; <j ld\?q"[2OIo C+S/D|`kt \ s ysb!y#.$|%y&&<%%s$$D##C"! '6 f 7 U J e  f lqX O P@y(4Mԟq́ !mζM쵮ܶX%,V0̿g#Y P~ŬVǀDatCE؊"!9Q_]L& D Om>4Z}}}@`oDu|/S VXk9My 6 4rQ "$S%_%&&'&A&<%%O$:"! ?F3FFZ_@c uZoBq dp oWS PB b  (f@x% ?(_61,';KUof4E'Q'}KH W*AVFy^ޑeGDyY;ǹzň Ë-ob1ص, Zܶݷ$X~|¸ŝǀɢΉ0٪Q\?)TS - @5t/a : x !6!t!U %$@ * Q&a(v]]4q0Uh I!!! >GF!@!!o $P9O e!_"z"! D B"< { FvWjc s }u  ],h\8O3c X?fC*| Z-K:u^ a c { $ M ~ V    c4o4.90rVޡf٥n 8v 󷂷6Cwe½sF-G\Ϯ]їLh}wv1 7K <m!6OsyQb "L$%'k(b(('&%" W`$# . F 6 (7 nl!#$$#!y2$ "K"[$S%%%~$S" DIQen_W 5j@5  ON O-EpR3] :$8ub r'hqT v ] ; }!r u ; d?Cf\GI ,@^(3߃ۘc4XRZXKD75VC6{gW\lݻ?ʼs"־"½}G ɶ=̋ͶηϏCM+ܽߓCk]D"K " ?-nL !"$%n&(/)E)*A*P*<*))^((')&j%%%U%6$$$^##H"7 Bhj 3 IL:Nugrw+nN !"""L dsk-!#%_&u&&7$"wJ>  Is)" J{60  )O4"5Tk(P@"49A(s F 3 l GD'q+-^  mDX\=BWfLAJ.;-lywq gcӣ$̛6HN=qοS2h󼻽׿àO!dŢƨǯ!πPhؾG_y [rU$/o  -DUg~k:!d#.%&(*+-:.01%12;26111%0\/Q.,++*++k+, ,>,---,+2(%"pH' L62 Q 8 7 )"zh6OL`!#3$$h$w$/#l"7 e!X^Q o   8k"  S h c D d/B/95F8l~e3I_'iiAe.W>^, 1 5 { (y0Dj+4LFHd>a_ ߍ܀b׼^ξ)s~s6軦|hDv v/ ^>ġƣR]ͦw#݆2rUXT q Z )wi !~#&[(+=-I.0R1X2!22322E11|1N1:1*10111 0/.-,,++V+=+B+,.!/k//L-+(%& | s'v"];=b[ ~VeDF D l  1 :|, !@"-"#W####"2 E+o  M 5 y #!3do W'~WoC,DN.8UF_9M]?~_TkH}p"i[ < v * / ,n=o GoA"!CTa@a mB0#h́7%[ġ+ο½[Z!ϻMM|Ze}Š)x˹)@.V؟Pܽ?Ms| !  8"v'F(P VIm,I,XxL_Ioifq}6TBU',eLaGU<B(azrem>61\e؏hΘ\cà;qB뽲Qм@ ׺W 'G|q`6Е%z٪۷ݚd. NO  F^dRN9 Y!#$h%&u'R(b)+(,.1*369S;> ?AA\@><:O7t4G0-+)!''k'(])s*,M-./001?111m00.d+{'!w |_  $"5Qs 8 ) ) ' ! #I ^!$w%%$w"z 0.K-##2WO9 P=a[|8 LxH,`G/e#7BrlA{/\u^<  y j  "vmfUrg52n0Si8`Ԫu ȺižZ2)p긱˹7ܺIVaS 9\̪π_?cu:ߢSB  /`4&!1$'),X.02+3j434455]56n7t8:}<#=>r>?>=\;97<421*0/f/#..E-x,,+B*A('&u&'&'R'''%#!i~Y H M 1 i e3R|ap =Lp<WN u"j  mG  "$$r#"VK2x]!y"`!!!; l ;O{\0X`zh %~yAv{MCa N ;233.+wr%m }0) 3DJxK$?YM=דMȺyUtżŢe޾GлRSV.ÆMyKĜ!Іܤ!(gT P3NE-# "&)T,/258:;~/>?@B9CEEEzE(DDCA{?=;9754v3V2~10/f.;,+p)}'8$"   !"#C#" Oj73 I Wz'.zc \!"# b b9 % !6$m&('W$ +k ) "%&%!!jK  ~ 6 B` aR,.o^Q#%6]^?0@AA=B*C&DAE#EEQDCBB>AAAB/BNAA ?>D==)<==b====<:98876T6 6 6:6n66^54B2U/-5*A'f$"! +  !U"("#""-!Z ?<h|\ #!  g ld 6R/em {fQ . |.> :Bq0Su_&|=t^"g`-#2<(! BJC>]]9kzd_xZ(9h.CJK2x1fR>51(Cs } E K B :_zm6zf|+b ?!!" "#$%J%&'.''((>(X(() )i)*K*+(+k+++++++u+B+ ***A)))J) (((r(X(9(''q'&%%;$##"u!!y! m q6^rE4[@  6 ? H(LG-k2_EA=8oO4\-x |B_xfFJ^86kj AUFiX=oKVt(G\WBG{NsaR|xi=rnj8 9Sgw!n,a4MXbbbl0hxY: *?h;Uo([.g h Es,z8BX[L> h" ` 3 ? _  0ZkwmU M4W >Nh0Yns}}snYE550&   N8oK"EX[K+SL,X = & w $Ux {E,iSCGy!^bLy YI fz,i0 |S*{=VoNlH)zL~U6"}cciis,yp  )M^@ua*m6dV\ X&sUp$]%Ir_G=D|O~'<`B)f%4DNmOxAaCq :^'6U V > * w  n  [ . f Im&d<3/wOZ B>\lq SmI*bCV~"Y>{P: j + Y _0 utOm=PN.#6Ng(o Om9W3tAZ60@TdZJ0^l8zeGiE1!!1P~#GuHq ^O[Gb?F-CTP7Mw+s'P (WBv%I|:dx'11<<1<Poy3GG\k$S+h ;o V  H { * m U " e  a Xs6B/] O;(f $$$$$8Wl***/:D:?D%vR$[~Fm qa'Th v  } q[6 f65/$.g2 =~'TN{=tFOrS4%%4Ic|mN???949??DDID/  M [(dP@1,,'6@EU__UdttoiiidPEK@1111;Pt G)R{ N|;d` f gY'e\q:,iVq*m TK(Wa m5nA[y#p$5;d~7Q`u 3 q * S }   ! J n " F u . W *% /Sw @i,F`yyootoo~a)94p:D]'(qJ :d~x|9 2 Q [ T?Y:%h tBQJ|G(={."+CMNNQZ'C r*@2<7,_6 X8e73*wS zK'Q)_W{T/ 9r|~K(Ev~iED)nt5.oGx|NoHEyoj:N M{w  nAy\)]sf  y i n  ~0 #sF  %FC1 d 8FwU]xpQ^Wx6~;'+MS(V  ')}8 @ #} ji\<900>Q^1 B U Y    yb:K^G[),9e  _  ) M * 1 A awO 'R+ mqR*P9 G^s85M_+[x*$Z8KFS?L2o^UvP[<;S-s;kgTv߈ߓ64Gk\|;$0~GW9EK\q=f  B |4HT W *  3F:Oc4*-!pvosw d/ 8Agh+,WJF~kR}g+(% ' od<A>eb !"""G! AF!U"#$%;%O$$c$$D$%J%&z')'(S((((((X''&$#W!g1/1S )Z " #8$ $^$I#"!'pZi l A K B ]w \ 8 B S] ;{\_$)i.FPVA7F=\k{aPi? xsmk-EIy:~ޜcNN?*  0%Ma1خoE?q82vٿqݹcyGM='Vl|o(SJe(Xd8*Nhw_\$I0id{7(o59Gjd=L!_nr ]R*^_GXY"7 $ * *sobU\dk h"G#%n&'(m) ))**6*A*U*o*e*A* ))i((N''3&&&''(>))*+,l,-Y----O,,+f**K)('&%$#g"< pj^wbbOFK> q%  ? l q     e z   ! !" *Yw+)Xxo8q+ P m8oQ(pOI=7]>EVCڍbG[֒N\pZќhOs~QMcփײ?ێ߼k S]?'):Z0(J ?KG  * I {Q,4W"*{Ax 4QeYC({_Eݥ-|M[֢!ի փ"سًsozݚ3^4Bw"m 04`w!~#{%n'.(*A+,-}.!./#/z/0$0q0011 000>0 ///0080R0g00011 1*1D1S1^1S1:1 1000000.//-.t-,+*Z('q%$w#! GUnBu;}>'5 3 e F -  z { ]eGF IOD8`Ez1I}J[(=NE u]g\Ebf L5`X_0$8eOr\op|3'dcԚR(K%Θ^IMʉ""Uϳ*ҢSֶ=Uܳ1uC1.;v0;-{N@V"Lqh,G  k7tUY#,O-_e "8xۘ0o!ev Ͷbȫl7>™V>DŷNjɶ%ьԅר=o3oyY C 'F"$D&K(*)+- .01|346 7y89:; ;_;~;E::: 99988877P66^55*4f322&1D0g/.-,+*))&(r''8&&[&%%%O%$$S##3""!d M*3KZ?sguEN q >hO8w%o  rdo~o"OI (vn}PmGcw( u )  ) < H zcGxxGڂ%)[֧ Ֆ4\Ӹїѡ1)/@1XUXzǚƞƳbǾ4|̖oРյvFEv2  ? 6 e G = K -y?]C/>h#6o yb,'QC ߱Q՛yϙʞȌƸ,®O㿥TApGɶ˳ͻdخ ݋A0I77~z j3 $h(-Y1^58a;t>*@BDFGTHyIJKhKL!LKJIHFqDBA8?=+V*~)(w'8%$#"!! :qm~V0  Q y u . JqD6G8 NsU q x!,!"G"#$m$%$$$$$$$$%&%%&"&K&'%$h"!@w+M :0(wISux| {- :% @5W6Q؟d;…p¸XDKA&[˾E9T tғicCϮΎ'΄zk w214)pR . \LJN D"2#$%!%!$$?#C!JB "PBr?' l=߃ܮ,mzSl˅ƞ%%lZڲN *TFzպӼ%I.A͇gmZ#] N zf.s!#%(h*-T/1357 8V9b:?:;;;':9826420.+a(%"N} W _ <;t-  ? Bj u  '!'"`#{$w%J%&&&&&&F%%;$$ #M""7"G"##g#$4%%&&&&&&&&&'='()^)*++u++u+(**)'%$4"` ThF!"#v###\"! c@/ G5=1_@&,158:=>?@A\AG@[>r;d7 1^*#.w syߓ)ІjWЮ4̣֤ߨ>mƭ3xRe_tHČPŢűűk̋:RtcݥfE =$**<05X:I>BEGIzJWJJ HFD@=95N08*t$ <*?oGE08ƸH`"<©l īiœŬŧ~!ė?aAҷ0 wm5Uq6MH 91gZw _H5*9f . r5vI h o  '=)e NC#W'+0 37,: @KACDyEFGG5EB>81)  gԚͦiR UqnNSˤ٨cbɻNdžV>Yͦ!̆9|}=ѡ\7ܤ,"8WD y2 I#H%()*++u*P'#y[Mtؕ;>ƉCX-+*Nũl0-ȵϳYx`Tk"(% '{)+-/135554320$.,/*)))*K+,-0.6/#/012345677<66@5/31/-,)*)+'&%$#>! p>Z<v'= !"#$%&e&'k''\&%$#l" W<x0+r  B! "$%y&()O*o+u,|-/2d5X79:;U;:751r-c)@%@!= ;g pQՠB۝iie=oFu"*1c6:}=C?????0>=<-961+$4֜…8>q~~4Jgœ͂HֈA<ֱԐԕ|P#n?4X| Y%+#/37`:%CAX\H?3UČԅwիNԚeAe&ר>ܮc(*S X? w~ FفҷbƙP~!<ӨͨIܰv}ͻ#?n (U"%(*,-.E...//..,- +)'%#{! ?)\/  O !"V##$%%y%%;$N"!P-Q;w?NvEB # %( *+- .o/0C011/1%008/B-,w*(&j$!W Cfd2Ms"%s')}*,)--s,+*U)!((()*,]-/-//-+k(*#e Bs,up<1QյڻQ/8BmN *`3CGhJbLdMFM"L!JgGDAB<71*#m U*q͸гݩ>X&˞@\ڳ?ӾW ͡o{+טZܽD 2gDZ}p v "%'()!(4&Q# ?5c 23ݯՑͻGN^|h3g`N=f NC˟8f  ;!,&+036x8:;<=l=g<<#:9|753A0.'+)(&&-%%%%n%_%J%!$$m##8""""-! z;GyDC6 "#$&)J+f-._/02333`22O110/`-+{)d'#$!CsU- !#>$r%@%i%6%6%'*1,.023 3K20.K*&"-K( v tט|TڦDm O&`/`7U=C!FIkJJIGECAW>;o7P2+{#I)rQͨ©oذwaeÕQxՠٿ"ܔM0n Te%+/369w;=>>>>>*=;K84/*1#V vqxߝؾRž{5{ȥŨa:AmY44.z͒X֜ؾٖڗ Tߓ*ki LB q tgK8;ebrw2Z՛ۢh(A bF #&K(*,b-../..-++*(w')&'%O$$##W#"""#$#g#$%$%&z'W( (|():))):((/''W&&%_$#"! %w u I !"2"#$$% %d%%&&A&V&%$$#>"`!P }YinE IM3b<9 "$&(*+,|,,,w,+B*A(' $/ ^ "Y{/hlHI\YJ @!&+0M4f7:=>?@F@V?=:61N+-$N M4~"bʺL歀Ckp)}#e¸iܙ,?zI1)O@!&swPb Zh3 #C%J&'(](b'&%@#q!Z }b m8vA:܀?%xA{'H鴉ظl_RJfđ6΄Y=نۭq[ߝU޵xDݕgX݁c=mm5R0'GR9nZw\zyK1't+4zhef} 2pIIb[Zx}'AC!"$&(*-/02d34\44544q3221D0l/.o-?,*)(('#&% $*#{""G!!6 Ow>p(":,](8ycbkoE V 80n8l '9"/J"8 9*.Fl_0 A dY hU\#T&mԪ7ҍ҃Ңә{rszqN ڻy(ܽ>ݴcޜ ,U߈G.T~~'}`P}Qa(lf s0>:C-݆ }/Lx,̥B";ȠXXȌiA\̪1:pތ8^(D<% 3 A `b&"~O+&;d2krL] !!""p"##>##$$$$$#######$$$$ ##v""`!!1 C y""d0]q`U!O&t m Z P >v=>5+';mC-ih4JI'Pxic^J+I P?D`=1޵rcmަ"R]:tjebc~D&;I)ldPG90'] %5^J-a6T$8gvvR$2,.\B8#j'c> j_6wD *S6,VozjP<2"",e EoN& 6`:T  m !' @UQC + !"`##$%@& &'()^**+p,,w,-5-m-----T-,,,9++k**~*))((%''a&&u%%i$$4#""u"!!K >GF5>R A+`gE 2 ;cll#%MCqNA3kvL7_ E,eV'!N8zF?HA6*.QF1U$5:$ ;,.? *#y_q*Po@!,i : O Q R]iouw}t`MD;'+Kp!"#$&'8(I)0)*+V+,|,-c-.;./Q/0300110000g0//u/..6--Y-,,b,+++2**Z))(4'a&o%J$"! B~ D{Iy <  FI\]oeUr d<$ Es0d[3tMmos|4l7dr|pK:Cvz3T~1Or44b ++w\Z4/_84 |\%ro-XXfPAPL*Ncm^I5*%**:^xTM%f`~O!DV~t pMr6d,Fk!'GC%tQCIi@[p|x_7 CsyvI om+  "#8$h%&'()*+,X--.y/(/01%12E23<333333337222Z111^1000M0 //Q..Z-- ,l+**)O('&%$$%#M"Q!E I]feJ Jd}l= a " K'&@%EGv{3[n@g0p6/vVK8 /C]^Fe"+%/9N]XXIIgcIK2w&V5,\g!;^MByTrC*X5J/a8Pxc8~ h0  *co7gyxdkDOFGXY@ i <  f4 !"#$%&'(r)@* *+,>,-../-/0$001S11122111111X10008///V..i--x,,C+*))+(b'&&%_$##"-!, nXR"D|AOS \ [ _ w y>QP:sq)R w7jPJ}9v*3(~J%!cW=l%/4:?Nd|^V9vgHH>yi]fir^_' z=m+k97u(_NzPTrI* 99C>4% LxRp Z}I%cy(iK "(9rSId _- rd`aq !"#$%&'q(D))*+,H--./7/012&232344M444555*5*5%5554545*5 444833u22U110v//(.P-m,+*)('&%$#"! 8`ICPI A w6!6U~z4<v` #Zlu~ j"~|H#ߝ}% Tߘu#NYU- ,@UoZ6*":Sao|:;m5'8g.^E_aH#w+!9CY#~03O9RzG-#(GQpzAi1}c? ^[qtL9?Uflr.W|$^  - \6[4Tt !y"`#C$%% %&'a( ()*+k,9- -./2/0W01?1112+2Z2~222323e33333333u3Q3 22_11|00q//(.o-,++*")!(/'B&K%d$#"! q\KDv~r{ztY93Knw  y c8e[M9Es[k$K3G  o>'5IW<{a%O*CoަN݋$p(=ܮRD~+|42 ,(  0Xz:q(=]++Yz]IvX'"i|4luNo:98@azGoUdkp(@mz;1k4c~IuX8H*  c =b;8Ov T!#q$&[')+*e+u,l-0-._./G/00g01X122d223373<3A3'22222222@11:00/`..P--I,,,b,++k+**<))n)((%''8&&%%O$$D##"!!y O ? Y x ^ labQU d  9jD(f6 7 lE0 )f?)x/ymdۘ׷|_ƸspbGQ~8.?|vӭ֧ٯܸND~X;8Q-n hL;mScrrm]? cEojnJ6Dkv$U^݆؅6Sxy0's迪rrs?ǐɜ6АN+ܮE ^Z "mG!#$I%U&A' '(N()&)Y)n)n)d)J)((((|(D(''' &&'%%%+$$$D$####v#q#v#g#C#""""""#####.#3#>#>#8#3#)#"""3FAk) 9!Bo C  NS u  YV+z@Fy&Ѧ^OŘB]߱Z\cMŬ- LEw®ƭ\ Zk=<, <Y6K&]aW e mdWZq&d@ \޼aQ˹η=ۢ6>qK ]{,"7$&(X)+k,-}..o...d.-,,4+f*)(]'%$/"!wX.#t^qb|I\4)]#w !"#$%&'()x**+k+,,-+-,,M++B**A))(]'&%$##"B!~  "nE:0JP> % ^ !"#$D$w$w$$%O%%%$$%#." q, Gb(P KBHvE\B ^ K :1]'j~ZDC^ G B*mZ&Ibؚϩ˕Ǥ-沺խ8짉ʦۭKLZՇ-.h  K/eiop~ L,A!jw: (CD,!o^|3yUZ wskK!@"#$%&(*)0*,+2,4---.'.'.---,|+*)('&&%#"! iF+?{v{~zM*- !d!!"#$?$$$/#g"L X`6 FITYcxn5}'4 &9[ R b_3OHun(Cv@ҷ=ȑUݻٹ#j|'ƯаQ/xO^̿snyzBa4 n8w] !"""""-!~ S[ q B3T[]^op&(? ݋.ݕ0h_!s%J#mܔڍW%oNjQE^à$Cīdž_k͡i}4*M= ""%(+Q-0$2356@7,78L8z8f87760532U0.- +)'%#!;g=N^MQT@\) (C^y}X !#$?%i&'()x*"*++L+u++V+ **A))(S'{&%$#"!!jONacpdDqg+of:  h D]>y Yq[ t7UI 5PGRc=)^ [7bY%| j]զ~) %@kɴt|կ6+-s#%`œɗҍ"p#FZ 69[aY !Z!!!! YD $1\gV<'Tݠܩ܀܀ܞ$ݪIߢQd=SX/Bz_%t{*Q}Ͻ'̪G#œ!ō)0**+{,,|,- -0-,,,9++8*))(>'&%$#"! Xq_cDRhiWb1P&4BQZ4- @ wtNG(pv|bK xop  s S-\ԕEƽG(Ĵޱᰄᱩ?THƄ2FҼo8EV }w !"z"""B!! DS- 7 8-K~._vP mN?/%S6GY |ߓG}ؤ*pѵU̖@ǚć9-o6f>^R Ϗoպ4~~~xx  #l&e)+-0 13j46 7 78G8u8G776+59421^/._,+8)}'%#" Oby}Dj3b "2#g$w%i&A''(|))n)))))))0((4'')&z%$#{"z! .`/f [zf6' U > XJg |UCz7C9di%%y < W9dUen ' v,uf2׼Vʙezݻt@JV@^W8"+Ѧ@C! FI yOgL') ?/nAj47wrC#|/Y"?~k= ?D #sّ[Ң4kECZvȽm|վl,0gj\ cB` O#%(*",$-/k012Z22222n1140l/.-,w+L*('q&-$#"k!; +)G@NI@j  0 !Z!"#$#$h$%~&&''\'v''( (''&&z&[&%$##""! vFONXiAqr56 !,! !!!d!6 }fB#?<  OLSaorL. D ! !E!t!!"B"#$#\#H#""L"!!U 5]y10Shw9d4p: -w fj+lIbv\  Je   W Z %K3xn_<B˾r_€ٽ`:ȶ߿%5.tѰ|S..GaQseG s ' 7 s g5 $8[h{Gd@ZkVvBa3#0OIݹګ׉W:1MȂl' wOo׻|Qb%ɍmV@/.-D--,+8)(|&u#{h  PfD~Y99L=/  x &`!_"$I%i&u'v(I((|'B%&"kHI .MGFP?܀iO¸?q"k!!Z TA^hq"/  !~!"7"2"("7"Q"p"u"u"L!!_ (]-PYwpt6" -g| !y"$D%&'(w):*P+,----%,,+)(&%%%%%i%%O%&[&'%_$$|%!&&'(I):*Z+8+-)'k#~ ' Q x * o E G$ '*,g-5-+*P(D&#"Q!K :)j+( xJcޜۢO`J̪̋͜~f9т'Ҽdd7WպFOۓ܊ܽڂ׎փdzb#ߍdT$+;(>44 ISG D!Z!!!6 ?`I6C -/ jxuV2 _;ۨ4֍5μwP%ùZ6`w𮌬d,7Q໠)nf:,̛πֶFjP22o+?  AjD!$'*Z,l../L..,- +*F(&%E#! as\1 " . ! & j qtSc: {8s93j6rt;%~ 0"p$'q*,,/258\9:09/7605321/,*6('&j#n SV C!_&+G.02;3-4{6i8;<==>X>>=;d7K1+8$NUM_ 9IP`#X)#9:ڇֶ20KB”ïō ?ݚte I%f`o@ "S`* \ ,\LjxF)h fl+}u^ I8pײέʲ8 eҼ-oKe{޽œƨ>v{3ƣć1r漍Iض>.罭@G4oh S PS28X}XbKbw? #%&()*+#+B+*)(m&%_#!N~O  _ 6 & @ u {G+7v)T: B =%LWF!!%(+.0235S6776543o1/-)Y% x}5! y@j  E^#)05b9<<9b631/u-?*'$!y;x `> EuVJ)7<f0^Ϟ<͂^͜e~j:a1x :S`R ),s $   {Nf6H6}G"߃ݪBKڱJrخao֧հԐ<Ѱ'>7œ4S漧q7ܺ.0,.̠πEPنۉvig_#'x Y iss&..X^ !_"#$$$$ #$! )jff!@"#$w%%s%d$#"# Xd^gbIh}+O~Vk*E1\ !"##R#."z!,wyXFIz?1:W:7 !$'3)**P)(*%"b$bf GUt-i M ) `'6y#kBUTgZu`|ߓ}ݥ܏ۘ^نrف+ڱ`G]ޑX|:3PE6#qs\^&A"zZt8$lEbp'&r@f֬XXs"ײ'&GxϏͫV0^ǟǐǚǕg`UĜmյ f"$m,-t' yQ&!K$&)@+#,9,w+*(&$"[ YF^!y ?"($%&')+- .E//Q..,+2)E'$"F*AF#z(tm }u| +"7#v#" u_|L2g6T )#)5,4,*&!!S Z!)058275/)@! Hf m!B&.5g9;d:^60.'k= 7< g,*5o(Tk?83ŝƙz֗އNx6ۢ٥m! T.^+W U U :=5< c e ^ 9HLA*[lއ҈M1Iʷ_4īF BY\mEо#.h~Lv52֬0݁pBT2Q<0%  e !'!_!!"#%')+-/Q011111 00H0//0$01N2&23333210H.Z,)'=$"u IW>!S\Is hqFdy !{m+ # QG!&&#fL@(18=H>=b9q3-'"n#\'+0)368z8753/B*%4  +l(f_9 -x8D_6XӏP.LǕqtVi]YG% fJ' E- o #$D$#"p x88@/ mQh^H V A5okjxM1rW7|W_󷇶pűȯlKbMrjݸҹzƷ϶ض5exOz?!B%( =z6=4> 5!o#C%(]+u.1467<77F641., )s'%!##$^%&())**)'% "pAf G y (IH+aZ >  cUw W| 'r %;/7<7= '=+L-.K.-x--.0v110.+f(%%_#$m'- 4-256}40b)"`1T 2 N NJqt:ڒeA *<9^gߧC@;xaND=oXVO0#S;j ""!/-_d-!t#$%_$"rD I'6d52B:AZ1ŃoQs4lwϣ0]O{O- DzVս7…X 29޵oߧߧ)s ;M   ,1Z4 $(,/12s22;1D/[,g(%i"!! :!#$$r#v!/O M ws:( =TrC9J  c(pE'dk!#R%+&()&)d(m%"F&@$ .9)BIM`MQIC:2+'M%&*P.25|6+41-:(I# S !"<  % 8Fz >B#o),DLwp9ikN?WQl#`)S{ *bpwy*\)4 !!d!~!Z! x! v V0BUR+IO#Ёt#_\!sNCXܫŪTI;ޯ 寗~ưPI\;*ʙwϳдӽvۢE& i{@#  6#g&`()*6)('%#!~ hU&p #8%&&2&$"#HdzRS 4!v?T>4~| 4Ӕט2BDu=i u' C@$1;CGsFA9.$+4l x(05g7632-m& +)!"f sy / N%( ;@.W1s`11{hn*ob5 m q% f(Zn""!FV "#$%~%%%%J$|#H!ZHeQ\y9 h$x6CCنٛ2vv >AclS ïZZxׯڭجߪ~Uox)ŧǤ!2˹̛pѰqڶ:D+,s!# :}"&'(('&A$ !X9/<!!#$&2')'q&%_#v!d)-7-   M:T+۷~ԾT"[' " sn u #l &".8AFGD=48)xSwTE(X0358962@-($|"#%')@(&"[%I waQzO~ H b N: r=? vBx} ^iZ{P B9"7#g#!+ff\)Jk #q%'W''M%n"bL5FK u r>#^{fخx!ϳ77aI7gƨ)5]psgGdžɻ˚&oϮtWlMWa-~*kX?dL} w'G<}B~p$^w"&()))+(/&$!ob @E  " `8R0)nڇA I   } 'IkD,7?C@A;2_&m  bc 0'k,--*K&["GK6G {n y 4 wV_ G);.b =a lRps$=, a3. ) >?]< ^"u$ $$c#"! I O I6m$E=o8G~f n S q9sga",eKͱɈ&ηT8իixv">uǫZu4K|ĸezZIͫ$ҍK|۷:PfM6SB !mWXf K (K~$>X8 . Pf hI"M-9oa w!&'.$Sq >#_zv "/9g@CB;2&Kvj { <$*(|)(%6 sb. yf c F cGOS Sb> .]+q jR1!! ' ~)G J|lP_xDR lkoպϊ̋,/I a-! $%y$!~ z '(,' 3j>|FJIDt;Z0)$P$*/B0\.*~%1|B)sUm 3]RW:JkgfxdF8[1d8(j0 G"$#\!D/&.5;?AA>:6Y2;/-+,-}/246888865/32i0.6+2'$!dQYCJ cxݪC֒?4ќΓH.⺆$I!u0q`%d=m Үɶ}R_ؾ|+ܤO *b 3 z 9<SK>_L ]4"LP q:]&qDk!ԟ ї vB!U!;MDE!,8BJHML_F=2'-yp#!Z(.~10l,'W L Bu?>==$=ӉѦߢy]%5.dD R $!i&+/00R.+)&&$$'+18?FJLLJ{FA<74{234v6579/998742Z03.!+)J&'"f O6o69,̯ʷZ&ƨćƾr񳜱Wʨߦŧj!۳ifη?^gDO1N %^j#o bF3T j -  }])L &!))Ddk4|OY6:4B.{ &,/z/.y,*A(S'(%)5)}(N%"6T"*4f>cGIMQjPLE(;1(!L"('-120+$?% dc-J"5ҝe˟ݯq_ vm& 5D9M$*A/4379:: 87'5569=MAFXJ\M'N=MuJFg@:51//70247"8875|2&.)%O!J \Lp;%vxO݋"Рʣű#義#%$3T.̬̭lϯaJiNJCþï|Úm(wn-?[S. GE   &  Ho>qH:a[? a;E =8E;wraO*3Q829852 .,+-:/2~332E/,)(&F&"(.6@>IEfJRLEKG @9>1X*P%U#8#&o):**& ~>0O 2pۓg˚ȦȌ˩Ѧٯf5,0dBj nM!d"#$&F(,40H49=ARD EG:GHoHHIzJ\KXLL+KmIGIC?;72.+)J'&&Q%$#!s y<-1ݹ!{tд?vɬƭd0(oEͽἻmy+.z¶]YbīH̪kԐ֧fۘbd~WJVre%\UO_([lRtxi~sE/)L>Rr To R   + Tc E`#G2 \2%/26:^*f[F.hv.DQx]C!"=?<@{= = W8  :A }2IJ '#-134k3108/Q/L/0$/.y,(m#a'S'$)@,-,M)%!Z oX |E"4]+E:^25 %vX^c>RV AT D#"&Q)*,),-s-}-+,,+p*)!'3% #!d 0 0!$:'.*A-/`01%0R._+(/$!K#Xr>Y "7YrWOT8ZOֻAtȵǯqh0ʲ\˹f8f̠ͻlӞ_[R)zd '!l֢mܮ2dg(Nm;eu2<)\!julg B 0.<` Z Sx[Q 5 \ pt \ AK c$ )Ia^5t\"['+, +p)(b'{')x+.Z0 0{/`,(]#)<8~"&*U, +)$F:!U%!&%!l $A)a=UN H:ZV%Y0^I  } $'B)d+ ,S-D-.!--0+)&$!P/!,#%'{(/'&#l 0/cQ Bٿ{W!ۓ)ޡ`V߬xڜ.զ- ̥͗9>w̺*M<<<ϊuZj]`m<8٠&y݆AJtp]JUK3 rfce4]q_P(W|!I Vuo.   } 3Bu  Q o1hRB !'+,,C*(''):,/G1320,|& 3\8"7$$#$l#4 u ;F_> c%|CXAaڜnB#~ڶ:xFBL8a H W#:W, !(/-x14{6789 9/9488(6x30-)%!I:KkaI}  'eG (#7ŷuhGΘԋ֍רW<҈PҘ[Ԑ*:rVמخ?\ThgK~v y*%v3.3R`*_t hKkcCf[,(vB<;+x2.8I+bS+ 8 l Z 8TUw <  j!%@'(D&"K4  C {G::F>m1' T*156Y53o1%//z0257A8a75/0*$X#p"0-M" 1c .<ϞʽȖȫeoֈRs[4< nW@ % G 8g}%-54;@DjF4F9DBC?!;85w2/- *F'B#' z  S Da^(,IHrֱkIH|mc Х-5w9:9q64f211347,9H::85S0,4'#R`H} eLru e \ͱԾ|^ĵEx7vcJ#,@ {  Wfq4g<,>^N=|b8jK!K$w'*<+)% BF n /# (*(b!; ,U_<S)17::m7y3e/--.0.2O46764)/*%!u< kK;ED{6l4IdžC,ƭnC}ߘxm24b; dX!'G+a.'/0/2-T*(*%$%#{#%( +.K1598;>@AA@>X:6+0$)!t '3<_DNmތuܤVt`"86<֜K]ܮ7\Ob|+,Lݯ(ܤއ$V0a&KAV2<bӸՖos`Lzܤ.ݥޡ[$"v#mE~l<bK%+&(5 * m  n < x.19+VRBvv'B`xPS!y$&&$ k9 J-q-q H7 T` ڶۭ (h188{U5 87t^]d˾w/, Y"<',$/0H0.y+(S$!Pp "&+/V326x9:;;d:%740*$GD %0lEC߬ܞoTT;8`:!wsl["&|5(u7-N[ϏYˊPj ΓѡCJAD˳SҧՌq71/(!rf 02~XAoReoqvVٺGŧzx"n̷IjCJL?AWRJ")/<4M79974a/)$: 8"&*j-}/1c11//,)%!i@g {|kd܏5Cӏف}o7)S3i#_A}o7 4USY +XTP̠å!jITŬ'Ҭ,yKI"(܊ܽCm߃k' FlztmI~4jr9/{e}:t +4R"B%'()Y)@(%%#S  $h)NI*J/F 0#&u)+#*e& ?bT|L>|o$,3"54=.U$ O(0b59/:m98p76^6E67F8#89C87141.+(]$ X# I:Xޜؤ?P8'JًY?Ogiרܔ.{7|a -!') 0>6::=R> <95X/)#v`X"* c|D x IkV)s@u.ٛ-mU:ٛml =39 H#woZG^ ,Mۉ.cͰdD0ǀ?܊>Yx,VCc@m0*m7X{ L ]h9/,1 ٠ t ]n]<  B B  1 6  RUT D#&(*+p++)'$"C=lj I"#$%i&2'#'('&&%J$S" 05 5>S,"p*1552* ^ lJ r ^#%%$##%(,1%5b9$<=>I=C:7K37/-+f'#jq %Q`Gյګ.zAL'OkAb(8.ї(Թ@׷X'@60VWNB&j.49=M>>*;8\3.y)$YO:*4:% 8Zm4ݥCՂ~Դ)z\!Z9h\19`IV*MD7_PzԐ6S]X+ǸU@eA)_4Kae2+d~1o?O ZCQkX\dܙ B9޵[359C KV Y }l[~X "L#>#$$D$D$:$ #"! l-Dnz'Y0"ABq "z%@(I*,. .t.,,*6%X>2V&"*- -T+p'{!bo Q  * "$D&')+._1369M;=?T@A @`>;~7U2+k#zk'ʞЯmݹٿCѫϮ΄F)Ӹ/iP{عّIfA!K)s06;1>:??><`9 40M+'"4Ku" 2Ax4M!+?٥Շ@>!Ծ~K]~*J9cjI\ۭۨܤ%) ?IҘ/ŷ@ŧȌe9=҃Ԑ,gz!%2w}.d#%dO*3%V b+'=bLM2Vn ~6 O !'!o!""`"##{$%$%&7&'#'W'M&&j%$#"!! s +   Y } AdH !,"%!'3(*6+B,,,+{(4"X  < R D \ &)s*)!$,y$ !#8#$4$&).d38=vAMD%=<`: 7K4)0-+((' %$$N#b!S xEi-cr A9 $qޜ߈O>'p+mi=Xb^^jApY> `àeīzwʞ8cG֜fcph-@C v9;lR 4C *x$&<')+-x/0M1*1w1%08.-5+)('a&j%%y%%&Q&'='W' &%$$*#W"p! m ^ !!!~!!" "B"f"[!!Z 0  ? !~"$%'''f& #  '!;  ^ -% M "*9~^!&+04a7,89w98654444k31:-Y' F-*$-֜z9| fpn̆paO4ڗߧ4y: EE-| "k$*&')+=,9,,9+)J&# 3* OzJK|3#6I4a l!ZJ ނ>Xq#ט`2x+տՖmD/ԐgH8Hԅm ֱjة%|٪ٯٛنفن٠&ۢt!(Xp( Y}c*]at&YZ($:P99>9CmT1[T=? ;[KSI 5 k,&*{ V .QydD. $=Ux7^a.pL7߼(A[`VGA2ߘP ;dߘGM &kXcNw.>^\K+  .bsU(%Ps !"$D%y&'()x*j+L,,-m../B' .)aql smD>3!bs?!&!I eUKo.qA RR}aNw?W[(\?02.nK8oegrW]0sn{o~ zPH &!^sYc^zdXaz߈ޜ9p88Vܙv0އ6tߢ߼ ߷ߧߢߝߘߝ߷-qd,8bn_GC5' 3X}:T"BMIK` /iY*_3w " #\$%'(>)J*F+#+,-c-./2/0H012+23-344q44595556 6+6J6^6x66d6+555C43322i100/[..-},,C+*)('{%$N"!MoJL2-  ^ oo`" Iv!YI;#3cv=<8igkavv?6WvieQ :ND |]C94] Z&6b&,"n%I&#.0M9_eX5\L}*\83_0'n>8,*\u:f<_I)_ޡ}ccrތ ޡޑތޗޡަޡޜޜޜޜޫ_L6jYMI_Yq |'N5 v  b O>~8 !K"##$%&()&*1+8,4- -./0C012d334\45m56&6^66666d6T6J6Y6T6T6Y6667 7A7t777o7,66:543210{/-+*P('%Z#!p'&w*%4*wh3 rk[10w I}@D1%|G&'a`PzRbOxEbXxA2b(vd`tP@cwT<{kL=B:x;elhsmdK=);~o1 gWASaR't4\#enIkeO(K_[UIݚCV۲&Ckמ&զ^IcՇպEZO&&ֈ 2bޑ!VoB j"[ 4x+y-Rm +!d"#%&-'=(9)!)*+{,),- --.y//01w2y34567`889)99999999999999C88z877 6s55C433A2O1:0.-?+)'M$" 4 F' 9(S 7L"m  d S%CSFL=Jzg 5xo( 9)988655C568B882641-*&$" !_#%;')+-./p/-+('#lf 'r'_Tz ~>"`$N%s%$" ^+ c9d]ޗ>#TϩW=Wavˏw͗Lт$+RpZPrp3g PLZh?NzM%&F1p Q ^~ejI e bkrM9z?@ܙ&;Еnz;%8p6i#uRmJFk̯υ ҈sz؏> (bޑ߬/E7- Vk]iNMV4} l N^H4 Y!_"2"#$*$%&%y%%&&&'(/()n)*<*`*P*))T((X(''''''M&&&%%$r##\#"""""k"Q"<"#"!!!!""V""#$#q#####q# "p! |>rvzk3%4>2 GQ b} YI!i$&(*U+#+*"(h%#d  : AeZ5Qר(ÁEeضll?й̺&g^ڦv *8""#%y&'3'q'\&&-%#"f AIQNU \;$ flx'.}HC,Rҷ?ڍqhL  ~ W~3 2 9`maJ3>,t5X6RCGn OV"[%'*F,.0246i89:< <=>>h>>>>>I==W<;;98765I321/.,,+k* ('R%$#g"Q!_ {oAxOD.-~HaGC%+)(X _/Wvt C u @b1>Kb!,"#3#)"u!Er_+ < ~lT (ouٰݬ7Y:'(0ȸ˼O:ČZέqڍAS6L qX#'*<,.012210/.,>*"'%&"VM!< %ILalz߼U,K߱Qe#xP2T m @܏فi7ќjv,*MƉŷŬe.4ɒB?pgoTz`6\, ? OG, [< GW2Us_|!J??@j@@@@@@@?Z>=<;P9826Y420/2-s+*(X&$#M! XG6O*v2Ecgq*! "<,(s CUs i"  >~% #$%6&z&&z%;#W!{ e C+boӻ |Z+kA꣭ݦЯ>ġʭ*(5% "&*-03`5967y88a8(7j6431/+(r$ d1 yPp u^۝ڗٵ؏=)f܊ TXL\j. V}ݹۉ],ҧg,?Ɣ¤F.İƉȠOG}h5 Y '[`M R mKxQCYu߈Yq܏ܞ݋^߈i< "!'$(+/72i5m8=:=q?ACEGHHI`IIIIILHH G5F9E CB%@z><:8L631X.,*1'%#l!E9K3?v-jUj2M y<8hx"o'5KMI?8+-  qfI~:Y 5 1 N0C :#>%'(((*&$" 8x (ڒ kɻ8Thݥ㢒 o}鞬آi1?" _)P?  /"('#+/p25/7,89:I:;::864\1/-m)5$f kvjaN؅׎0Ֆ^6t,b/$)wBAo} 2 GݴKخϮ̥l_êL *q뽙Y=Č\ʨZ@JTh >v pe ;3JQXiu߈ޜ m^ F} ^ b N"&F),/2i47K9g;U=)?@B|CEBFFFFF.EDCBA@?d=!U0znz[VV`p l:OM%OZf6kOp{~o ( `]eJ?hteg!4  8<lV!U%)d,g.d/<.-+)E&# -h44 gLч%ƽ1 @YyUК6VˡYMV1wCauA u #).o268:;<<<`@uBCELFH_IJK:KcKJWI[H@GEDCTA@`>=;@9$64v2/-*~(9&7$^" bTO?qM%@M%66FjtK5X.F S <   3 - m##~rqN  S85w"%E'q()(X&$X!p P v >4'1Ǫ¸7̠vS眛62 (nٶۢn5' WI #(-01*47e9g::::+9M8L754#2!/,)5% ^9` >\KL!Z֗2ةۢݠw +n&PT6٠ֈμ́[IuïÐàDİ'żƄNjTXӉJW1#eG @ v@lI0]- waTH@9i83f9iKzt Gm G}/#'*.;147e9N@2BCEGHyIJCJJJCIIHdG}FbECA@>*<-:7531X/L-O+p)( &z$#M!fb dFPd_F;;_2g;OZss+:Zk|  r B-V ) H f  4L`ibMR!T,%E[WSOPG C h 8"_~T$ ` P, I דQ-Bǚ սѻ?fx )!i$w'8)+-T./0R0q0$/u.t-5+)'k$! HK$ 1fs/.`oخws۝ ;u5:|S% V_*Un,հWMϳV=VϮH:t|FXއ,0WmV E Q )  z yk&MpaRk[Xs>n^  J?^!K#%()+-/1w3-46J789:<==>?&?????~?>|== <:987654\310.,+k)(X&%~$"!66muPY0H\wSXmN ) u  YI . % s y * .:CpLQ\O(~ w @>  GIe٪a8 u a W A ~ u1{vx7F8f0f .g )S!$?&(+-?/<1 246O79H:;=> ??@AkAB4BIB9BAA\@?>=<;:98Q65r32O0/<-,+)'&`$#\! sa<;c"54GAT+|D v M  o " % H2(1"y=Hht`  b )f':cqaaR$H.,  s %B3zwp" b-ugғncË񺪶ijTFdfڳ@h0ZCۨxg"(N-04868:m;<#<<;;@:?8641.Z*&"BNzE&9NIޡZkӔч΢n5&5}Θϊ_8Tؚ;3!4Y6;$#׼հ;ϊfϞ9;ӣ4خڍ܅ޗ+}G )wb(*W{3umb|vm4qf j)X T!,"$ %y&(S)+#,-./023[456789q9:?:m::::T:99)87654321h0W/f.y-},w+p*`)O(X'v&%$$#3"`! 1nF_hW7G| a u  h 5 CQZ:|#"`Gt M  o >S CK]^| Gnn9TP- ]()H8s  |ToMq-ͦ®¹sv * ҭq̳ccї'܅Ev $)-023484332_110C/-O*'#p mI}ڇӸ̠͂g̺JPΝ#\ϞоӔզݥLzEPG2 Ovߧf%fAֱ|ԐԅՖ֜8Xtv;D(KRIX!x|]4,s/}*/_J b 4}) h!~"V##$$%%%&z'#'()*+,-.../Q/00112n33333333F222s2@2111r1*00$/`.-,,+G**`*")))x)0((h'&%$4"!4ZOo? b U  C#8   5B ~ vuOC  vL f 1 M? >L`} ve{lIN}^ @h/\ݹի/nDm'"n`Ȫ̯svàxTk Qh"#'q,1 5 8(:x;; { _ WUpa?sYka z F ~ V2 : i\B^   ` }WT7nWkQ q{$yK7ӄ$Ðگ߬QTm΢$gޜ@ >!y%)},.0R00/.y,*1'$!? ~3ZU@%'yׄ?p:0ёE@Dbao̠͒͂β.!v.146P3/i-)aC'/އMQۢ ڜ5|/؅ר,`/ڜkޑ^dk { A& ""#{###8""7! S<5_?>`o1eJ!"$&o(S*A,/.!0 135C678: ;<<=H===<<2;P:D87~54=21 /[-}+)n'B%" y IFb x p5 ^ W;@dX@a;m =$ q8!&'+B05:s>I@BA? \?}ֈ:EZyN[Z֦!|Jk!R֢h%@}` s"z$%&%Z#! M .Oy  WohB:հϏɢ0oieIrΝXѡ҈Aّ8U GK.,I>߷|ًڒݐ6X߈I9a2߼AV9"ؤҼϽ+4Ⱥog=aܞdB 1V!%')+(+*)'$! ed+X    /|"(% '{)s*+,H,b,)++*o))d)))J)*,4-.001?1S10C/2-,+)(''M'B''()}*+,M,,q,++*U)0'%U"9r/ F  Zx(!~X,\h$,S1554.0,b'v"#M(/<5S:m>??<71.$N ҬUTڍަW%ݴİѷʳJ̰8("fjWt~ "$$$"!,!$&),/L13443u1-5(! j{=FXeޜ܀&רKϙǀƨzh[ܞ>רZ|˚8qN,Դ7ّi3{T>o)F?!oKӉР6X tʙ. ηLϩb zmއNr|W<@[8B[ycQ Zg@:b/T"|  Oj=*Vz6{' #%(*,.Z/f00>0/.. -D,,g,M,l,- -T-s-h-,b+a*(&%J#!8 Z  0v>puMbz $'*+,*'#pw _K4 S ^"$ $ " kvm: !! O~2 HGx*1$~#r`NܮۼێH,{\)Krd 0X  #T2J&Wo{ %L}IW+5=Kx~Luo;Gme8xLX9m̑|{t&ǤÚtʭK҈6v=ihJ`5}Ea=ނݥg[/[~ =A(e+yX8q?# 5 `o ?n;qD;P~e{[u!!"""""f!!~!,!,!""#$%&(())))!(&$" w}8Q@ #_UB6L  /XD c 3ATM9#A&Ry kH 11#%uufw&j q  ? (6%J01Cg]{seN52۲tڇ>؀ט֒mRp e*dRعة#"ի,b]ϊԅP܀ޡV4IMO(Tkr_,cKI,^,G 14C^9 f k 8~6 KQUkOTw*4JZ !"$$%J%J$#"z!L!|w1 !#v$%%%E#!== :s w!!%Z')J)'k$ xe   s_rCBVz!E%*`.26089997Z4/)#bsuGQ1x5upyތ!eо{)ŷ7Ȗ*sH) ! X&d~aXsw#>F %!"$ % %%d$r" h<V f|߃ә%υϩ2ԀWk^_'J&Q=]ćAhyiۼ%,3'/eQM0t O"$'(*K**y*))'%J" jSB>z%~T' E8#(,b-,|(I!_Z,Da ",S399kss"i x!"k"p! |{!$|')@*++*(r%"q<*e "%'R'&%"F *]U "p(9-02Z2@0\,(X"}> ` N ' ,2&6d9;<< ?@@? <9/590,|(X$" Dbq I!~"""B j@]>p"T1۝؏ӨтπxRƔZü6񶁷+\#<oqELz#ةsA;}mB"6|*?/rohaڜ4.z֢6՛ԹӭҝѡqЁ yԀ:W.oB\[tn(< ;w[I$UM w D 8GN Qjm  ? ^ } s T D + u\"2##! $p hG %)*)&"}D6K@_%&,>3:@EH!HKFMB>X952;0R/01220.1*y&!y<@yd5ttع$z871ݐ4MIVނ5&  u$h*`/p3A578998889$9999M8k7654{3[22_2Z21/<,l($  U&y\N-\ؕѫμ4Vĵ>E|h;8eïQ ΓsRڡۭQܙܙfL܅& " nm s-YؚՑlӨGQӣԟIS%{qףّۨV\]SI H L 3 f0 h<p&6AbWS & *e-m..,9'!Z d>   5!&*,-?+(%; /#J w6 S *5 >FLOPNvKrGOB9<7F3-0///0{1X2@23222@0.,(%"Q\\0 - l(De+94ѻS̖Ή&["Gaj7It ~#))/p368G99876606 679BgG:LPTVpW8VASlNIAB;5.)J$!-jx - qE]6nxzYBKڻ؀[АϽbӽ!خ)ߘۭڦ٪ܸ-*v ޜN[,dpԹAF֬Ղ*ʷxɻʉ͜ϞѦӄ/֢ۼ܀HY%#y&I AnbGe7LDsBM%I]%tEz` ] *+>vj=s 6[ ?ia"$#gR17#1=FLOPYNL+HtD ?i:63/,+8+G-0)4R9> BEFE@:3*U!tAw a yAܔSט<ڍ=AFkGA0e]V#,399=?J@?>D<;;i<=@D3z'j@y }R  q߷XV?~w%/9qA=G5K:M2MFKHECiBB4CEHL OSgWZ]T_8_^[WRLKD";3+$rB:Q(& z 5DߘܤesًؚB8؟bڍQIbwR/SRm3#K2{Ke $)m|^ K,n]+rY0js"1:=\FLOQeQ NIC;48,%]'k0:BHK J8E>*3'3n}GrU ײqٛ&xڇڻۭݕ2@C:g *j5?HPnUXYXWCUKS]QPPQSvU;W>Yn[]!]]x\*ZW3S.NHA:3,% u  Pa)cTr߼Fj: :r) ;O Rbe*6̠ȿ;2ɽϻ?纟gLո ˩-'Դ,Cߍo 4~ iX AVW(1M(i*CV8ۼP߈qC k3:ϊёgN/,M:ELPQP5LH!B=b7e0)"v& -4:=<9|2)Jk #kL?\ ȿȖA: /ܮ4z24Rb 4#30SQOM7J\GTC@;72-(]"1 xUB;Tm% %Y%bYJmu E9u| !E!~ +G j99QײQL˳Ȍ->ۼ`7ZKIǤ3ҍEYpD!jp4e2 (*`GCC{eE ۷ڦr ܩ."ˤպi6(X4=D`GHGD@;600*$ l#DmI&.37P7F3V+!K BKxZ*=hɜIČƨ[2Ԫ0E~`  Y q v 0M$/;tFQY;^ab `^\|ZKXWVVkVUZSPLGBb=)8(3u/2+{(4%1" W G6 6 W(DD+ݾx`E$w E;c=~9 "`#%s'()*+**e)E'{$!dED] ]D+}܏'ȵK®пN¸ ŷR"\̆_w%Xi&fw|}lMZ,ނQ_pfw ؏9K8PȦ-cϳ`!1/;DJMMJE?7U/&  H^B <f!_   fT2n$}1պ\ &J l3 *!,&+/37579;=R>@QA{BXBB|A.>;'614+p%Ey Qn?3 ۭ؟ `<-\%ۭ2Au?0[aD`:rM n^v`4"*gҢug- y  :H*>ϳB."-:5%:=.=g;84/*o$\ 3*| !bRن֢զ5FvPkJBïdSiqk o #%&'G' &'(+0M5:?CF>G+FEB@>= <#<7=C>??>;61^*"#u4|+^I .J\hiC#l( ,159X;=?d@`AAAAAAvA8@?>;E7U26,%  ' 6Wt2eخIٖ|=҃Hs4fT+bE(o w HWF=Z߃Wv2߷߱߼ I3kȰȂxj{΢0h". /? H޻+} ׼=x"'+.Z/[/k.-+($ O={z8ֻѡ9ЁETLEASʽWǤβ߱I$/(,M.d/031258<(?sACTCxBC?<<830.-,l,-.//.-* %  r]RVU X"`'q,)04f7:Y;<<< ;987<65%4\33'2y1S/,)%E >@p۲АX|;=ڻ]AZmL8X#=!*}$O; 8   Y+3ctn;'V2VB EةgHYt %H \|;SϮέG &F*1,.-,*)@'q%Z"\3 " d"ܔExI2:95>0,/(&&`'*,/00/,'R!U. v_'G.xNE- Sh#R)0.5:>ARBCCJB4@>D;86 3108/.'-I,4*(&<"| ن?PХM%;[gm֢ނlr6hq{BvS S<J#7ߧތDް *=ctqҘРβyE 5KMTlq٥oҼܮH (.1 2!10q.1+2'v#Rg 6VJ2r?hEpw`!dˮT8&8*s[c0M Z%E)-1%469]:O540 +V'%_$%!&(*)O)(&#|Y 9tC-4Q=3/ %ER ?&K,S2+7<[@7BDjDCBN@<=:74q1/,+2)(]&%"|v mݾԴuLeܸ޻aA?9M=?+QObhYOm'/.E%X= #qVna1f%]iX?B(ZͶR ėxҼ{+5*;E>??@B]BA?<9H52;.,/*(()+-///[-*&<  H&6WHXrnm ##)/u49=ACCCJA?=l:8k654M21r00W0/Q-*'"p': 4U%zTԤ84ֻq5߷I$8p)\ 8ZU8W$ag!0n'R/N,:KU.+5{TZ0܏GbVЋ} (b-0221/-s*'{$* Z34  :[%ٵ,յqA֧ڂI)|[G֒xgTlrT $* /49!/ fwՂֻ]ܞޡ +08e iMWpKC nN+uc$߷>e]<#|#N6DMfS&IQxy-T#(+\,-T,+)'%# X E" ٺnf@*j{ޑؾz4i׳Žō u z#*y06x;K?EBDF.FCEB?;7P37/-+,]._1^48:;;t9M5g/(  f\ JkxxC(!?< a/%*o.2466J54432!1h1*1|213-4q5677j6:30,&z  PnޫK؀׉"z؀ 2c_evMCtuE%0l'<'ޡަ߃Agz&rF5ؤԐz!0_{U՛Е5mη)V| %1,1X34q320H,H'"uQ   5(K%|\TtׄײqؚպEǟmۭGWw3qxۘGW SY!d%*/4 7:=>?@o@`?>N<;P:O9:0:;<<<;: 7"2,& u,ff!*ma^Vt` _> O#8%')* *+- .01357o9/:h::Y863`/)# o~AP9oG ߘDD@ߧ#AkisB  .u6m9!k^G4v8ErW@uϽ ޑj%ˀRu!&o*,,+*'%;" ? F7zuO d]qDXsGFv0& տ#*<<3 +I!',15r8Q:0;;!:h9M8878#9<@ CGK%MNNKGBm<<5.' - _|m3d c$u;: 3 d0w^e!&),/#0q00C.,H)&%!q%-m WazMsuZIE4aޜ$Al;>έͫx1dwPi.g0U~C`,G,`qSxi3a)-=> < '؊=׉ۨl u7J&U` !"#R"!SEnd x"@@iwғ'ҍӨ**y ?ax <}!&*.U1 23344M5 6E79;=?ACJDE2EQDDFC^B9@?+=W;U964\1.+(*$^ st` z 0b44] OT aj[.!lO  8 Q  {j9i a0ن٠+~ ܞ)ݚ]܏ۉڻx ]`Cr&Abn?I6*28LItv"ׄ20bR)[x %x h U W r *\MgxD 5b BVxW #>&F),/258G:h;<<<`;:9w8G7 543o20{.,*'%+"<4&7t( T* Q]rhJlhwmmI#w4M;cw{e+ixg)ܸܸܽ CݹhPQW^wK)AlmT'Ggn oj!.t5wgbbb>ftjt#9<} R Gu++  F0 8 u \nh{2s T}yAD @ YWKO!P"$%'( ()E)* *U*+-+,q--..Z.y.;-,+*'(h&`$D"( (T%RFQ<OI \ 5 b6$(^m=EvtX1 2.kei!43V ߈o_dߘLH0Nm:TGt7E lz7 -)&7BX)vtm#M?  Z 7  Bpt1d E $P"UQ b Y  ~ `  JQ 'z?@KeV_hbQ;^0laAOI v B #  e - n ! r  .h8tP-zE \=Gf%X5iZaZM%SrI vgvqlglmJt({*r!Fpx6Dp3F-\>w_k  8 M g  5 m Z 7 l wyBH]\-"^!X W  u  ; Y lo6"" 6Z~< 3 D i  F V Q <  n  h 7h{f`i)<&I>;+X4 9gwIf8z[F'nO+rgLd'm50Yy MZ=%+ .i.c;'o3v{\L8=Ba{3f Im|:LT  l  r  i " u  R 4XS  A ~  } * g $u~6,~2`         ':H\E9 vfW3#<,z(=GG88BRa{=v 3{= e"S:m1ZA[zze[eu$a%]J,jW8f D| &5@:S \=kWf \ +x,e=X,_ty_Fc%]aA x^:I494**/DbT, Cqg{3j6:|9qR.\.K,`G3HRRMHR\v  qaRMM=8B=. RFO+@O_s'jRvpp{ M]h>BW,+S% 4INSc&@Znss7=v]mS*qaR3vG#BLakkL38M>E[yP5b/f. $8Rv ]5ET^s 6jtU1Y/H k(o7,t Bk$W%EFP@/aBPiZ_i~Fezjsst8$WDmS\{PnO6&]/*S|@ZnxK\$f{l\BvG[nJ0rSgR\{XZ,.Gf{vkkvvfRLWpvaRa$fqR7nn~sJ0c9Ic6i'P=W>+}1UoyePA1"i+rS9 M BtV2"2[(8Wf8 3LWv R{v{{q\Wl9En6AFP`j``toF'"'1,,6AKjUY&XlBtK";S4T<(kLWWX+<yoE]W \W\WG#j"nOSW= ~78.v>br>fp(LG`K7'2KzW=RlNw@x}iT:!@noj,x0O^^T0 ]qRR#LB mM \b  oE\27e';|wrhXS/ %m67z{RfpL83(=fL`s!m?%S&_V.a( (BavRGf6cHgr!\poiE+;nK.pR/3p(8{Wvl3GGN4l= B49/%D|d1oe"}%)Vid"G Bfa3vL`E_[j>|] |BG7eL3N0|qLF"AP[{{N!TJ55J} 6jU=(7'=aw+@:S .=a$*wTFy<1je6 n!5TE>8`\R :U#-{2[%dP(jT]%*wEsE|=q5NRJXlM4ZzkRPctGwE5={mF=p3DDOXDr 3\rdKz[zB. :xO|K 8="n|;"'eL8r: B ) vfB}E H\7 7(t3 O>lzjeW/IL ws'oppJ=4 o.{vlRWw!5LP&9g{I9b/kh9J[{lH8R SF[awG;Y9ha( GR509M3R0^BW+KeF,JSp#n+imDNF\m'0^dr3,_6W H{%S%l8*d<#PAKKS*eUbe?\#pG`pn/9!<W\ofL@%*P, W8p wX9rOe F1?{tno b+5 ,}!:}})p kd/ jPOkxM pqHBI[vd`o<@>f3B C|l)BBbxj|);]3JKq w4HO-Z;Pk7{{=Bdd$B*a>>WKsw=JwkdRlU%c2^HCDFmfn?.H&&A`mzqu`$*d|<f*KFTLBf\c8(UUAthw/#Fi|+ jx W 1 2 < cs6d+i%d8*2|]bMV;9#2X_,.6#9(h4?PAd`D4YfPm- _]  1 i vD\ aLcM]xVHI;d M {=t.$[ =J2-cGWHl 1nR -x { ['d/SZ{RAkuoDV2f<u D @ d \Pwv i\6T*>& _/.jHSFmL6Az)IIT!6md"``Tn`s!&JJXk go=&i8L I I >Hi:I,hVWi qsg"C5lT=^<=Z.;{M+40[--6rxa1 +  1 S -55^Oo|vl2GtI*x 1&\>m/ KXG]WW~!A ,: eLqw&,b^s[D4V]e$DE4$va A=B[@twlHw[ &GBm7 N h O9\0w&.T}Qi &nnWtAo)( % ?S1 |>w+e}IO\Eo$$P0Nf3{Uk1EY^4\z{h^P3q$pBr_A BSU*d t,^S.Q4 GWvlWHAyY UzI-Sq)uy ]\LRRml]U)Ow 4F" 4/X+ZTsWI[aW%EOz`L"ITGdaeYsM,z(Ksweg#,kx4&q AHF 3 m  IEYc[>T"x4H)l9x8l%TA Qf:  r 2w:C][9m+R\LilA|lR4T<nS8.n30.%uuf;8~D)b @Lg[.T^+=R2_U!2   & 3@t`8na1~J+4RW.Z2f;[8brS;s60=+mi  $qQQNH WjTh[   U $N\.)Q 06la:DLa% a>/a: !  {8 06 N ! U {1&mva[Iisyru N   A*kNP;<3?dM6-[ H [9p;r< F3U AsH;P(RR$?Z,zR|]3}qe=-Ja@ Sj>pr @AAsh Qf$NgGQ6faW)[, 8uc[ JdaL=XiOdU6Y0`o??J:Ujxd7M!4q7mhcS|YKM`(k83p2 H {VYR{/EU9WE;~_|.h*,`lX@hRG3 _?kRDJzb,R/nKFO0i{M rv3<_T2v|9l/3Ss   L[LR@Uw]pz+PElD {#K~H+EI.{aM/" 8%<Z fx,j'UBWOX 3|/53^{h>k= r bDI%qDS [ yY@s:mWp ` F K\,%3R0g@ MTHG=@.3=a3H&ww]%%~e,`By:{K;hFOih=xq7lR /hc?9]~,)Una&\)+F5oo<B70%RSi' / q-$[ %!T/,D-h` u :;#b+\`{g^PBGL`<j!xDxPmz S t\E2WX6 n./;N*^_!\tM gb6n~ G W .CoDSD(F@4 394!]MB+g3W%_qJ{q!\vmD4a8om }t  I mRB|@Of.jVvi"`#T"M{ PO,LW }sBkWR3{xp=,89$A##`*!x0V_.|&WIS%   \33a/hbvPh/taRI d0#cde_K}|aka,n^:m8 [LHDDod5xyw0h<hf~8M4a}B/aMvqpPR4:< p\x#n &R|:I-=;~ @y {  : $qH%*fF9teO;Z$nx `co&.9X/IY;oBHX]HC*Ys\  ? Vi6l*J9\\6Jt8EQtLkwOm|+< Lfm8v,3.lI__"dUxx1k!e+ GiE;2i&J&X*w&RRfGk|/VE9.ij4ARpsJe:KFYDRKC7~yyRs 4f+ D}_D2\x ly{"BR8CPO4BvR4TqeL yXvx?/t$xpV*axUo2q$NSl?PV]6q OsG;f]sl|W-WWyG_,b(PJZ0] 1[J=L!FOl] {0b:xK8W= #p3q rD{GL[g Y\"ThIn,8R\{"=lA=~hqn/MDVvWT9OVH]_2/^ p.SLCX${[@4F||V!2W6Uv|uND!r7 ??JzW!"e`6sSKofa!j@_z/xP,E/ g.HJ2=RS "!%l$WE$"#$c')5c%sdFax31!(JzB{.3E8\l7pO{/!}8x,Pwya3W.VF RU]Tv8(=xnN `T&!0de 8fBF+mI  ]S=XD BGXNb[e=\V0)[7/@Vjt=vx`XOOD$8[=L!*v3X9x"O+MJMa20D[3'^IAaB[K eP|%BkniJNa3.R{/+j49w*o('"#HS05v%//=q4U`5qfWqb^KpLMPMuqB)ajKjvr9xO[BW|`B3tG#9hUUs9~,#k'Y\jF'HpB(L3n`S`oG{ +OO0hv2+2  m]VEw.f{W8V'`#I|/.fapB{aHL2_!&T",sT0&&6_'KP2xn< 8GB8# j<"ApH\R$WaMfB8WDhhI8v#a{4mwIq=d0R{]] z2<k$).$  =`<,2Fj=Wpp=W.Wlqll\Wf{*9% ]5sOD/]b\B.)$.B\]]9%v\H$ H{ h |M\==kBDNa\>mD\ pG..3Gk)Rf{{a3{B#fH{Rvv $Hfvlffq{ %4>NSXXIISN>/ *Nwr9 %>NbrmI\H=Wv h++m*{WHBBMq *94%v$p{R D]N9fpaWk$HllM)pW=(#3G\pR#eez L$fW${B(=WWL3#8GG8.Bak{vp\=##(8RfpL##LpvkWB3##BWkvvf\LB=.##3BBLB833zt[V[KFFVtte[PFPAKo (.3==BBBB( .R{pp{ ${vv{pkvkWB3# 8f$8BRRMHMH=. )Rv{\8    .8BMavl\WMM\fqlaW\fqvqv{qfaW\R\l{{laRHHaq\M=833B\v{vvla\lvvvqvlqq{f\WRWWWRRR\al{{v{%/>IX]bbmwwhSII>9**9DNNI>DSXbb]h]ND4   lWRRqq\WWalvqq{{vqfWBvfWW\ffvW8Wkvpkv{{p\B(zzz z((((# 8RWav{{\=....zeVVeo(=BLB=3 3W{ $=MM= f3#Wf3##.(j,2<[z={k{.=.tt#8\ B{*%H H%**9|bXD/q >XS*fNXS*  %I]S>la|+5*/h|I*4]||D\B#v|I = a$lv {Wf(VOJe#W)RqfB{\\R( RM\BB\Df8{R{l= {(jKP#DaMqq83{aRaf\8f vH4}+SNJi 8f<F\#.)8%4{3f%&A@|.`. .f=''4R\v,.]Lt Oh\37'HxlxE=qN MvB uu|`W*R l b!eTT .AGP phAi9'*I#89Lt]J S=qOBIY<LsiK M j#6O#wt)*T ^ a=cQg Wz8_xu!56 m ^82_;f.N9Y[0 q7Prv~&9D,.Q 3jw Fxc|\rX 8 E* hLO|^U 4@T.6j7* [S%f1{(62P>ol:ZLNT*~;Akbg\a89N#3GJ45JVp<?9YPJRZ[ X"TgvtRKspHMOUaS9NMEovl#z9F\0LMo.oo+j1Sad- jLqAiRTjkm|]$LY{ W ` ZdH4 ]*r Q5%+3! feDf 6g"f\_c$D"# [ V:j 6 vp8hD xL 4 B 8- yo M ; RJ u B A +d 3 # brJ  o a  ` avh < P \nkC 8 ^8)1kx@5BABVQLTU= ? J  rH9vo*:I u %$\ * s$jT4P#4k CaBj!Vw8EBX<8\@\fA8f<|tVbbl u ,4QARWIcyWE(T%33q a0ep_qJ o+wL[,)_Ypd>d6 !xX ed%l2xX mK b!bTE0~:r=tT8QHS d/0EY~6|xP$RZ&,uZ  A S n@q "  3 W /L ^|  /S/RJ>>4I@Zz0ej=_u8,{ifxQgL k?( 1K  y wS+l C`P k  - R l kdHtR)'v DN%yfJ">mRjoD _Ra_e d 3z,5 :D& h=fHf"}4.Ja1>R% < dQ yagXH 8so] ) fY Q \ 3 lSAMaqF0pA6$$uL 6z)7?fD bjX{A'yDaW0 mf*I62kAL_ 3 /X`  Z   ?' N  ZB"[ @ h Z   ) r ~ B ByHV Nuf5<i |CxhEfI|iht\ Z{>?zU oKz.f|h0!X.qt5@15mA[$fyw(LAFP/%&t (., ^" q4   W#O k$%N4 .e|L\ $ !PYH'iZ[7Wq~0 `FE Q Ar<!xSe#\Z}eM?T6b1L{cY@|.ztw3k= }D` 3% e  =& FKztZVH}#Myi8(jf$8oW)^ q \ID#  3]?!!%|*:L82CchxOR$o}10SgN:_k(Rtb;AaC( l)f*=)v[10qxG e )sG <h)>b{9tI-1Wf E . R xXd)0PA=*dH>_=R2?t)>4SL*3) `r%jZh0p76@|JTW^KE a MLs oj   8!l#o!$ucTY/ .ar Z1 T + > ah@;HQ d6 |Ys(|TXm}'e `-(a FwICIEU  8 m;< Uf/j$|?cTke%|)@*qUl<<<=dk,'7k.`r\3aD4.6N= < :6y$/(b'!A ,5u78A~ @ m :  z  r5E=tW0T N @Na (Zz-L0Mzv _^:UQp,0VJ'3C_lK `h*Ivvs 3 `De~kR-MD + <  &x Hs,f2z'gE  -(f R1Y ~ E  P"Y1=W Y :,-{I3cUI Y& > G}}Au ;Q.B\MTo9 g 3[&G+Q R UP C u4 g V +dd]X!&+J++  . M5Vv"[!+|}]r pclfxjkI?Ni33  |o HT C  =I K ]t+.q9vJXP~z:H$L=)=48~{qH1Yg,r %A2 H  Ul()H  2HK{"=W<zf(Z/; ](cVF/D;]XA,`rQp=TPXV{ݚzF cA=m{&y^ % {h @ r . 4: g) YOb n )( I O S,k L2 *0O,>( V]] }h2| F? S LO4wppu U% < < # O > + i-S}o . 6, a P % | |5  \ hvI  3jqj \  p \A QaS '_ WM^]f[t% @|*P{uK_.n|ri %W&!-EZoK\*WEok,&?b{[h8*M?Nrk`{`,Y)PWg]xh~XN<|qI[hNd9xfy?Dw*s\ %$Sxu9\+oeSj,F|"=&)k6J\fO9{+oAx ( K9E@4m  >S H Hx#IbH  X R C4=gG *w l 2 W&H}NX,b_>V .K$h:x9a0EIxilqrW2)GPW0L%_6o"eU+#T+(~7eU ;c~ ;q`NOM[Fi "$%%&&V%##)$4&'a&$w!6!$/%&"$"2- W@I Ex,#6D.ۘ6pVNL&Tߧ %ͫZ^4ˏͫg=p=3JQGy(&!7b# %O%$!Gm 176:K39ګ֍?Ήй`'}D%ߢ(ڇSbFaV^ S$ %*U.1m47;,>/A CFILdO*QT^VY+[]`>b_dvfxhRijsjj hgFeIc `^ [aXVzTS$RGQQQyPONLJ3FB=\7F0)# a ^\{f!t8M\ܶ𯗮Ϯh4%^@1{渧+QQ gR9ȠZ*GL.%uf qL{  N#ԪyF[x70aPKCߘNi1 lN   @5Ygz}LJx)Xx۲"ݴ(!|4H-0S^ R{G  ( /<60?ڇ^\ߧo^6$4*.y.) l,U] ,IGm P͡19ӏRއ/ (}3ޜz9oP 2 ٛ!ZuȺπuרs23L`g  )&2-27;E=?+?@AfBmCEGJlMRpW]Ebgzkoir*sssq{o6lfi]f6c-`b]\ZZ[{\^6_a bUc`dd c#a?^FZTO%IB<60+L&!ZtWa j  YCۉmϞPŧ]ֽ"FGþ{ٹ P?v3{ѳټ JO͇;=տ֧"׎=X܅ޜvGmt;Xv ) $B] 'Mטkҷةa$<Ԁғ^%EԤ,h:<3]zSf^/; + ! 7 ?-/e:,<GUi&1`  6  DlL&#(4,1*5g9w=RADHLO QTV2XcZ\b]^_``v``l`__`acdefghMh3g'e/b_\YV2ROKHZEC}A?=;852+.)$^ >PXްڍiZΘq ~ž׼8ʵQٰ %ϰ7糦LƺKgePjQå;CEs&ڱއ7adwVj}~,Q#lKܩBx<"_I LdG yh2  n R@{b F # q 3 o iz6JPW+&\c)-p j?!#W%!')i,M/49>SCHLPSUVVVVVVW3WXDY&ZA[\]^_G_____a^o\[YVTQOKHEQBN?<9602.+{( $!;K Cr 'a9s?β%ɗėչǶWYYL˱!l' Icټ"Ƴ,Pܤ=zhEupS xIS  b A  |qiC{dVއܞN؏7C)I܊RTwDLqN.I f^p% gM)zJ\YG,2$O!;(.t121/+a'$!!"&,$3":C5KNRY ^a^cca_z\rYURPxONOSPRGT?VpX[]:^___8]\ Y6UoPK:E>8u2-h(%1"[ SRޗ7ȵCǯȌn~ŘѽԲ դWߤ驯n>('*ƞlǤʎ-:eOT_\ .v 8 e Q n y}Ws}8^kZC_ܳۄݪo)xh7ނHHP+ d"'s*4IsP9{>$kAvLP+oH~&3`|SpEMrte2PrHC~Go[o!'G+.~///-}+)('(I*.4B:O@FwKPTWZ'[8[YXUS)POMzLiKLnMORUWMXYZeZ[YXVTxQPMI2D?; 62.+)!'M&7%%s$#) U"XHۨ2ѦЁRcч]ėɺض$׮ @5էۮ Q%.sZī@(z"ҝV-Tk B*Q(x >n5`pz CGc(gvb{8a0qHu@RIqkyd "f~ O` k4I.A/;97<42d/-s*(4%@!  vVwlF*ԹˤÚqolᭀSӭW$3CCqSKOӺ\5¸!qɢˤ͂V* ۉAK A\W f ?,|Z9Ci!_#4G߼7]v^( QuJe aY( H /DIeMAPQQPOLIGYEGCC0CiDFJMQPJRSTYT%SMQOM-JgGDBb@A>m<:864v2U03.+)x&#  =72-]$Mۓ٠[ԾA;5r%nj/ᭀ{ͱBޮwJBF4IzL0NO*OwO/N{MLKJJ$IIJWKLEMOQoRSRQ6OXMJGDA>|;987t6@420.,l*'k$ | lL\v߃2ϳ9|ġŽҰ"ϭݭ⮌ݭ8׬׭ln!c8˾͡Ӹ{ݾf:5T S < %ba ^ S< *(Te ~ ^~6' ` i  Z .QoZQTB)\|szN*>Yj&\Vzkg Z < !'"$:&"(9*o,.13j588:=g@BEHKN.P&Q`QQQPP:O>MLK|JJKLN{OQQRuRuQP^NKGD"@=;9877K66531.*% ^# c4Ooj؅=m6f蹔5ӱSƪϪ:㩕CbO&dEœj̑զ% k& \ = a   }  j oVS\EcD / Ix,Bd~o DPXIJP^ 8K("s&^F 6=YCWf nKy&] !K""#%'),X.1325S7:I=?BDKFHK^MVNOOOO]NMLKJJ$JJlK*L!MQNOPPPOCMVJGDAa>;!8655N44321w/B,9(h#Q/ METKͶ6oW#&[nٮwS*íM@EH~we9dK)*͂zU }Zeq8Jji )  ,Ujf # + f$y5 /||Q> R :: '<Kde[,v $ g3b3J*=FFB}%tlrRMoT;zH!""pIy$,43:c@DUFFECA?>/=R<<=>@C EpGIK|M2NOPPPNLJHFDC5Av?=<7::9l99499:9863.)"`b fA!S,h%@AܹºM|hp2NШ¢~!XTر׵칞s:%ćLɍA."3?a[m<<::;6<>AEpI(LPRUVW\W)VT QZN)JGE(CA{@o@@"@@@@@z??=;9X6:2y.!)!#dm ~Yo^%EAk٪ӣXù`mL#7ص(&(Ԥڢ櫱޶$߿ Vvï$ ё2q^M Oo8R"" 5 A]eH s [%6  AQb .=g& +p+M<  k u?<]7GaEM#r[6q܊ܳNvTpz"zS _ VW#g'G+/49=bA.DAFH HIkIIQHHHUH_HIKhM-NPR=SUZV`VVVTRPYMKIGED6C0BB*AA\@?0={;U851-)!$?CR8  )^\(8׎Ҽ~@t8uYmծìũj-װKڷ%8ÆOīg ڱ~o~!~l;<   `   ]P `k y[ z; ,3= a |oAZU??g`OܙۼZۄQ"m~{W V 7]HB D"($/&),0W37;>SA)CEGIzK L6LM`MN NRNvNNNOXP!Q'R-RSXSMSRR(QeP:NLJMHECA=><:871543j1m.+&!8 OSX'f4ނOՑXtiTɲӳTa-&Dq̬[[MٰrKb%\UP̪#ѫiؾ,ݯ#Gi9% 5u( i p h 8Z { 8+C0@ % y" W dG@@ZG8`(QVrpoc|$Mݕ*L6iii0&?L b _ O m#\&*K.12669<>?@ABCYCDADFGIKMO%P!PQ'QQQjPO/MeKIHGFF$EVDoCnB>@><:73/,X)&#9 VXM1dϞ̺³ʾ׼к˶GŲnxͲ׷ y$󽷿b$yʭ!kѵ)(6]kfXSak jD(2c~ B"(!'Qs EQ p4S00\S|!P")Ny4۷z -?LH)(0XWP_ N #  . ' $(+.2+58;>?AC+DeE(EkEpEEF$FGGYGHPI7J\KLMNNNqM`KIFCY?"%&o$ k m*io$?RgPEN<-vrva43*T!uh- _T +J +"##"!^5( #'+Q.14R6O78888=76531%/.y--0--T.K/14)566T5431/-T*1&"`oDgE U7IZK_tK\iޑ`Cj+IIOβ?Yhhs?дiYͱ~ϳ ҼԤٛ\ #I?Ux,#ds  HtS })1Az3 OC ] X;.+#\kL-3- hb # $#"u ` r!#&) *,,,+*<(D&#!oA p1 cx9W)~~(dP 9`Tq2)aw={k#o /   LH ^gT| 4Oy3,dNnwG}9a uHmRCKA(8+&ڻݴ'!6R^߃ޑ?޻7V!F[9X;m 3 mGi3 s w wxR s&-27K::9M51+-%1 O!'-02Z6d89H740*K$I{'?CF[ jahkSHjB3*w7ۨ q?έ gj׉Vߘhqݠ6?\i"N/x 0C!$%&Q(]* ++k**('M%$##R"##$&7'() )&('&K$ !ia>@0B  q u  8"+GNn]Gy?b6qd)ؤֈԟќїҬӭ+P3*4Mמֈd֗"#٪۝LW.ZW&Ca-Z6 w lX:s<#N Y!"u##$/#"` %k<+cNz0=Ugt p%g#H_ RVtx[x6d{LO*aC w @G l<&,d]lW( .QUcwgx, S h ><y1s)k\Lt/\|go xN0|F&Tf4NN>g+PT!"v%w`B9T  6  qDd9 E N Mk69Q[x$82 C s&o!NlCcJAv;k~B AWHOU( / w  1 Z 7 o 4b ' J c * I  @ O U d U  m $p36x&X MalZ qv 0%|R$ $vY_q%OVWl/_[ $ l 5 & d y [  @ Y WzVLG'Lo pWBn|z } |X :RtcT,<brIlRM==HWRM8pa3 ttzt``joeV[VVPP[[VPeotzztejzzzz3Gafv$M/>NXh&TnxiOrX>4>Sm &|D\B3$8BHH8pG33B\{)\9mEn}^0X/ lWWf{   {lff\MHB.$3B=B=.${pvp $$ fW\k{vv8Maflf\H333H\WWMBBHWffW=$ $3HB883833).=HH=))833888)$)v{$  kkfkfWRGB83(`A'"",2,AK[oztooottz.8Gavp\B333=L\k .33=HB3 =Ra\RWWM=.BffH=. $$$38Rfq    /49D>>DDNNS]]brww|wrmbb]SND4*999INbhr|mSD/  lB)Btoot (B\v .=R\R=$$BWqvvl\aa\a\WW\WR\aflalqq{{vq\H=) pf\fppkpvfa\\fp$=Ral{ *XrwrX>9* *Ih5^}snd^^i,F[jo[6n5m>{\8fB(tK"'P.\.Wv %4>>DNSSSShmD%%9DI/ laM=..38=8.aL8..8=BGWafkp{k\LB88.(33#eF,,,,77Fezjee[`P<22/9DI9 vl\WWRMM\aa\aaWH)k=#88(..#eV[[[`Vj#G3\/DXr:},K[`[PFFA61,,,U8#yFxi0b*{aMpBeK'FV[VF'"tGpaBB33=R{$=fqH8===Ba*4>Xb>% %Sm|bSD/vBpGBfkWpk\=Gp3RMBHf  %/S@}AyU}iO+hh B $3 3.f=8. jA2Aej`tF7tW$Rlvvvq\3))f%bXMl{fRMW=`<xO~"A aaG=.tn;_'oAT !_z ooje`z(p{kakpB.fv{)WfvqR."VLvWvW e`K'"F[[A7`R{W *ij3.G~_ojjfMa 0|vKd0Tev|t\)XE WB|:IclG! =$>0KP& ) aHW/r>{ji]C#,}%B{=kVpaw3( W l#H$9' b m S .K!+}Uo[T|vd d#--^CV8r&7W=[# D &e,R80^i  =b:~ 6 E J n @ w {(~Z > Z Z / 8L1+Xp)0 e|fEM$/ aa"~1T%*Y[R.0rvGqL~1U MX O?$ q l-4^GXk+jGQ`+w\3MlI * n ` = ) u E ^ > wg?  &  c V]d{"4(-Qeu[ZmCJa;CUoIml`|M9AA6%3%& %(K  * ^ 5 Y O  I 5 } |O  %>Wjd  z E   6 y  A 7 v`(  &>2*qmUy_(_ @Z6 ;;N 0p=vfk<7FGW/@ -=BLGj0Oq56B 8 D } % q . -B 8 q :  y 2 e B \  U & & [ v45 `^b ; r  { q $Gt5l[ NdQC{,n+*l;q=Q(GV[GAVH}qhX0'4hqE.Yt D E z '8<u4J'us~ !o!!!"V"L!!Z 54 OJXw<4_ uI("|AT8G9.k(HH}CR%K\'af=9E;Vvi%P `uLdKt2 Ps !r0'F"Ag h!!!!o!! d"p L) M ^G8gQt\QF&ED<۷ٺkع6ܙް 1֧zU59Е:{ײG 9cߓdvBG {Am@i M x,6 !P',0312 1I0 .-,,,-D-..;.--+,-?./G022334345956^66x54#1.y*K%!H-s U / Krd oZ4i߱gMZѰѵ'ҬGLi%-̖ɗ[ 0O(vNClߝ0 ܀ [ 6aT=m( s} +$%'.():('R&7%%E%&(w+u/f48=@"AA@u><:s8543334568987j41I-*`&#.O?Z9 Uf>\%އieՌ՛:ԐӨ@.i[NjP4l?ŘXOxIƙbQAt¤I˾έUz\ԚLԟ_qlvVD"f?oQ.  NFM/^= #%(+/135m6}7,7t7o7j7788k9g;@={??i>w<;::5:ȇĂÆq]ŠT*{f?VZ_6V8f~RpPUϮA-4Om:  #5A9 " #%(,1:59=??>=:Y62/(+(&%&Q(+.2_56O6&420C-+)x%J! w _L..M\Xt٥LˊǪǪȫ&A-39 =\@KAA? q WwpiU_#4׷ҷKʭI>H Oweƣ?ѿm"Due߷0]zuO)dr iVC"d?AɒͦQ:~^  . E bnc: ?"$m&7)&-1 343<0.-.6./02479;=?ABCDEGEF G:HII`FB=\7P0*'#hx %+1N659< <<51._+*(>%"$2} "Q#$$*$ ##q"!@ s J:Wsk),|(0zXVփnٯ܏Aߝ)ڂײoX}3Bp=fa T )dkntj/ "f$/%$#!tI 1c1xD "DS?ٯ% ͍ʷȦlR ʷV{i߹ʶɶDwz3ݿEyQŝgdžɍP8̖";ۉ@a*5IcG ffF #&+#.Z081S24719;1:999;<=W=?0A8CFHJ.JKKLNvOPQ6QQP LHC>992,&7""L$(,1h6 ;?BCsB>@ =;P9964{1/(- +p*(&%#"7!y!"$&)&+f-/0v0)/-+)0%!_dT r_vr}   gA{9 P&>_֢V޻,K&݁ٛՇ! E7+}T$ns%y  @-G  s9 m W "#$#!@TZ a Dx4fOBEFFEDD1CCDAFKRX*]:`a`\%ThI=0#K K wX&-1I;6C5I(M"NM HB=976^421r110l.+'$""$S'*"-O048@`@@?EK.3һĶ00ߵ-:p6˚%IYO;˕ѫ:TOIT~ k#(/,M/25*6!41I,X( & %&e&(N+188>CH~LENONKE?;:0;?iCHNU [=_`]VpK?2'#<w!@+5|=DI`KJE>71.i-I-/147998630H,(&V%E&(+/L26:9=@BBA=7P0)"uD \ ZO!#l"Z^=2R XTZAЋۢZN 7ïù#ʽ#,kv[8ޡ$|' ks3` h @P U<\  kmNI  \  i .3% :#veyGo8 ʄs|2zfua?Q`Ҿ~R鵏gBM U-꽙ĵGʻֻ̆0܏فk׷W٠ۘ '  !#$#q n@ %Z-5I<[95/p+*K-4={FOX%_(cdb`XwLJ=/"%1X<`EMQS>QALJE?!:^8k9H<-@D1GKLnKHPC=H8(42_1247y;@EHL&OQLM-MN\NO/OPPPOMJHEB>7,.t%ylMW/ T%(++8)J%!c -UzBhZBYv>.aРV< 68iSR~'ߢEN:hpbr AcML(qPM ~3[pJ  L+a\B"`~~kGOJәέАРЁn˚Ƀb_Ð> i 0d߽U#z̑I)ɒ(īôÆ'ƸAզ׉؅C5ۓR@,4x@[h8l$o : V O^! ~A!y%;*K1h:DMSUSLD'9/2$c)D!*29@FCIJqHECCFJNRuTUUZRN{H1AG;U768z<(AWG:LQTVXXY@YYXWHURPLG@80)#X#>(-133208,'"#G{ Ud!qzwlZx޵տR{؟ۓއ8sK|[uߧ, 8gEӳ~ԟt~^r{H[a.LR?#&V U h klI%Z_U9F+#Tݹ`'Aט 8KxզԹә@uηfODrd@bʽ͗ϊЕ΢̺ʲ\Aŧű`ǪɈ˹Hd3զIޜ CSXm (I .vyz $ ?  l \U%n-8C@KIObOMKH'@25w(+Q ?( W#g,3: >@Q?=<>BGNaT[ _Q`^YRJHAa9X31|37?0GOV[^1_B_\^]?[[[R\ \ZW.RuLF9>7Z0v+u)0),1c6d:=?Z?>/;d7t3"/u,+)'$|  3|H8 H o p#\$Sx*Ղ|G6%9aw>w?ACDEDKBA ?>^=== =;m=] NmD.X%%N,p6_&[ mz&׭rӽUk &̵̥̺̺̥̺͇̆.?!=<<;@9741-("O [wex-+|oM wA~T.`Szԟ׷E`qa i'QhF$$\#oW3`AR{Wz'd#|A V6,/+OW۷٠xhԐuҝDо]Ϯ*yӨԚ:ՌՑ^ \ӄғѰDАϤдѫRטN"Y6߃߈߼#{?JjzR?;Qq_  bxk& HGX `3S"$$%##W#%)+-4;AG+JKK HoD"?:779l4X}?al <!!^ r%yrf $c%%%$&Q)^.,4\;PBIHdLNL+G0@`9g3o/-- -2 8@HOTXZ[[MZeYxYYEZ'[v\]]\CYnUQFMI`F|DEGIL@N)ObPPJONWL~JI#GFqDB/?;6+0*$[<"$h%&$S!C O;Fm&&M`:Ϟl H߈F`PAvA@-<840)--:.28?FSLPSUWCWWWXDY[\4\\m[fY~VRO4KI GGHJLNPsQZQ~PON=LKwJIIGEB>94-(9# B)!#)%&'{'%~"g j ML8*cd=eaeO߃۝3cVEd! (' WWB@ݚVۓۄfDυΨLЕ[ԹcզՂԪRЋsFɱ2k?2Z,܅}E%ܸێUu= aR):eNrp !(b-D0.1c14/-D*<'&A&(D*.t2@59 ;U<=>?Z@CJFJNR UWMXhXVASPMKNIzHtGGH,HHHHPGmFG GHJgLMNNMKGC&>^952d0.d-x-+-,,+* (S&$#""k"2!! | mWX'6\x.'%! @2wjom5#(z)iMoLf{// |)Hk,S'ߘ9Fֈi֢<מ=G׷oA7PM=զπ+r{ΘЁҘM%$<~iJ͂~( ~ӏW?֜a۝(fCߍjoV4eAc_8e `$%&'B&o$" Bw"<&"*/36@8V9w::;;=R?BFILNPPTOMKI[GFF]FGHyHIQIIII#HHIKMVNWNNLJGC?:7~555*56@778-741m.1+p)@'&%%_%;% $m" 6um _ 8B` R v   _bk1~j *bx>I0E 8;C&[t;i1QXX|J'GNnOz݆ڂ׼Շ)gիVsKۉ'?ײֈզ%?հ;x;|g΢wAVcXќҝTP+D߈nIm<B #c!Gm! 5 8]%*.24G57 8:> AfDyFG^FDA{=9g522&36;P@DHUJKKJIGhFgFH@JM-NONLTHC> 72-++-0.02i357"8:<>D?@j?=91)+M# dS( f"%'(D())*~**<(%!o# Ih .uT!9|IHI `\n* F}%LSܔۓޡROYjsh^-)[ Yh8TޗٺRrӳC10ćƨCǯȠɧB!΢kkΓ<ÚfXػɍtOk 6n٠ycŔ]۷v^\,xX I O"-   mi Z(N1:9@FK*NQARRLOKEB?i:7557:>BmEEDo@;,5g0.. 05/%'%J ?D@   $bt=H$0q7; 94-x%JO2'0)7>NCG}HFB>496x31I.-%,H,.013j431-(! _ ux%,901/2)@!j1?M W H`Mx l |F< ) 2 V @$D,4.: =??n=W94/2*"&%&*F.38u=@C@Dw ]tT3 <u hKZќ˕,ތ }  3Li@/6Ab<>9\ z[ }"Q##"< Sebf e#3*/262 /+%U3' ilV~bI  ! !'=+{.o00C/,*'$*";83/,M)T'M&'(m)+L+*(%#o1a:B &> _ݠٿՂsʨ;i/eųگiѤ⢶Iáʤز躯}u ʾݼ:Nj6ŬԤc>PAnWi ZM@c"`$%%Z# QDO,^йv߲ɰex Z&Mm9 ߃~6 z)28;E:7j3.'(" q zI !j! ',/.K-+'#ZD &V%8p~y2 ru$Sr#(b.5I??>;61?*Z"`3*;zKcߓ X8ڡؕ ̖u򴢲/x񣽣vGtyu]T;œO?œʉϽ#׉ܞf,u KGP 5HO" b\"$$"o F#ًU˰ ʄ֗a;tiV?9AߍU`#M(|/4 55b41-(!? QE[#% -+gf= $X0  !@%)+G,.t/136:8u9:::59::;: 9:c;;<?>=;d7~2O,M% 3b1˕_vMHƭA`\ȺvΎ͜ bR gY8Ȗ)؟9Iki 9,-#! ~ 6U$ ޵WN \IgR&ߍtv6A}JEzP^  h  ]{C8k kpM w8Vl k;m] D#&)},).1:34.4v3260.-0-05 ;@99b: ;;;:?741I-)$G .KO?SS̛̪ pv@a}ItwƽdcOƉЪVwaD&tQ *M({_l#q # OTвm7y]عR v/0G9kuܽڇU]l b>@N 8`8cЁ+iА=߈Bߘk^&U"pܸ9֒r!MZ,Z%,43:?BDCJ@<8Q4G1|026^DHIHF)B?==8>@KCGKmNPRuS9SSU VY\w_uac`czb_-ZUyOwIQCJ=g72!,'="7jn%^wsH@ kTp);ͱqi xNmݾ4|$T2#w&!ol\* #>" e  a@f} w =X2+w.ߝʲ`#bi.Mݯ vۢcvka wW".17>CDDBr@??ADHLPRSRRPOMzLMOS)VY[\\/ZVW>S)NIEB>;6n0*F#Nc 2sX  .D"C'ڦ׎К]"<:0SEHc=~ <1qk7 )b$G|ԅ[ոE#կ)β89_Zik; ^ / U s%Z('$G ;"܀ 4̠z%߽\GF̠D\հM@]L\bզفG :&A07=?@e?>==>ADeGJLMNGN)MM'M[NvPTRU6WgYYYXVTPMQIF|B>D93",w%KzIQwqv  ee7`xB`|xמҼ~#1 2 H { f>P znwvm/pw Q\hEtб󬄱 Z%Շܞ I 5 6 .b46,j N=3H { eT~mJ#3&('=#{&>cёgȊ] w&@T"TWμЋ_֜׭5 (I18=?@K?>==l>c@C0EGxHKHPGFEpDDEGJ>LO4PQjQZP}NLJGxDA> 9l3,$5  C;A6d xQ0kZm֢ۨӨGտؾܞ_0F\H 4XcG a   C  S    e T  y4aTvRٿm0¬Eױ׺vœڗ$7BQ K :h|  G i G!%'&"QIraGˀ;e:m.́rhќL ,Ϯ'A؀نPe(29=???==W=>@BDAE2E8DUBAG??T?ADAG5IKLLKJMGELB@F> ;84/f( hb@mJ3lޗgK))Tb{/f9 { _ Y zkG~  ' x"ۘІP@Ҳ%;ϤSl15, .o UV[Vo+ (- w#b*/20+"I qNخ:ȿƭO#qa߼!Ǫi4t`֬RlnӣdU0gS 6o&"09>AC&CDDEEFGYG5FDA><-:889;>N@jAB*AA\@?? ?&?@:5%-$w#5aVt OA@,[ g|A$c l"G$%&$c" 8 v}\2q- Vyg D$xI:,ݶΰ`׭Vh0uhK \>@ A|Jr3rW {&e,//*"I ImsXs˾Ǿđeѹ: x.x-׭BfEMH݋ٛZԅB1#/#88>C!EG:H;I-JHKwL~LLEJqGsC?J;7o43-235C6777A655]5w6T79::95/&}# @9?QR,gK%LqM]-%}M3%*1,w+(# I = uqj Wv! 9m {W$M`ٺ8œܰǯ ΎZ=mZ- ~bz l >OLt&HP@"L8#\+#03K1,b#) *P~7^A\CiDFHoJ{LxMNNMKXH1Do@=:576@4321///../B0g2344M2s.)!YHlm ^A߈e 4^ifjeY+mF cf!$*F-.-Y+(&#H?;E ` WcIL2F3=/!SP^'o߼6̠åĵu DYԅuxTAvJ@yp ',|R$ 3"*e/0.''fIe[-^JĻ&w^p_J;àȵ̛uѰ&%MMzPkܩ' l#-6;?BCDEGxILJL;LLKIAEA=l9|63j1S/.-,+u)(4'&'W(*-..-T)$: z.}oݯcް,߈-RW3Zv DI py~nI"z'M**)(4%#M S l tT |TwfFg겛O:; !D'o0%S'm) }s+6` Q <b!'+#-+'q GzwHl+ ۽eֱ~R4]ҧّ܀y4]TGuU7SB!+4;@CEG HyJKM[NBNN.MJGC?<86d43 10/.U,+Q)((m()J))(|%!  .Fvۘۄ#ܔ(C}r.>0 $0^5? JQD $'q()Y('&$/!]}F  :H3|vfj1F.Өپ,бòĶe_=]? U) Y#%Z%#M h=3C7\/_j"-%&&%+! P}&+UٱѸdlgд֗W٪ݐ1b&0+8$/L8(?D1GJLNBONP&PPPEOM[JG}C?;8532s100R/.-5+)('v&%n#!a, l~e%ۓq֢հֱeGSګG*VK.*sVr!V "%&&e&%$m"z cG / U0a:LgNɿ%ط0exҹ-й'J>ܤ7C'i 4 C(18 =BmF>I`KNOPQ'POMJGDC@<=R:8754G21^/-h+2)+'&K%i$$4#b!?Q ^ݯڶةjֶ_T]y_ t| 3/Eek4rvA? "7 G!#$I#"! \eL0 ?#xO&ؾZ֍k0Xч̯ǀM6 T{} $ D%@(9))(&'"gl!_#$m%$#E/5 SUڍF=Ȱ0?^#ϻNSvbʞ̿ԕ8ܳ3 y (>/G5:?CGKhNPRSTISRPMJFbC!@z>c<;9X7o5%2~/,C($!_X o`'0(oJ|מEhԯI_)ڇ߬<`90v > )h!"$X$$$ "! l-s  K `  1 \ESiA߃ֱ@.CۼIյ:2ɃFӄcN@  a%+/B00/u,)d%#W""V#l$%Z%1#!Q >_ PU,[Gμīwl㱊>kP:2йy}_:}1H4^ F#+k2E82=>AF)JlNMQT+UVVU'ROCKFB>;97531w.+u'$ s<*_t g=ke=_98#)Ԫ'^W|<XO`+ i"B$D%d%%U$|#W! T3w&f "'J XUea?߬0ݴqܞ,DCӣL >ܙ1߷ݪ׉Թ a|@ #'a*o,X- ,|*) 'B%$$4###.!$N  ^ /] ) S8 dI)w6LˏǟÁnȼN…6*μk!فݹ"p2v!  &`,X16Y:>BFgILO4PQQPTNWKHEuB|?=W;,964#1-*&o"\i> >fWL(Gްզ)To*:9_\.8SQY _%u 5 > = :31!jyTztpڻbWמf;VTEE҈=kAd  %)+++#)E&$*"7!_!~"7"#v#.!x E 8 g#:b%|ݚՂǀÆXÕeͶl;7֜bM?t!?.Ir4 &K+f0)48=MAF4ILOMMLxJHGsDZAW><;,: 9$76031%-*e&#!6k/%ro\؅ڇ܅xMwO.Az!Z )Ac ^ ~nqj b = F < F  j_c_Vۉ}߬6,ԋ+rO N D4#&Q''a&"$I"L  %!""f!~Hd\R "L" ^/{W)2iʄXǤNҢԾ6ׄس?܏߈X[B\63yw$).U37<2@oDAG:IIHGIDBS?> <<;t::T9|8Q65 31I//V/f001r1h0g.U+B'8"LQ n~PLkmXbއK@m)zBuV^ّڜ=ޗyKwz6p R  e  R  7 J 1 @ < v  h JJ9 kHs^WR/Va݁B˳ɜzv$qW R^^:I)yZFr"%'q'v%"1 lPڦؕמStݹ߷) m~pt2#H,<*V<  I%!).26O8:;;:98a7A6:594\332s10// ./u02i4a6d8#9b998=52/7+2'"f\g] ? P zZ8pAvIlڍ׷ҧЪBΉΓGІ,6؅ݚL.cucb:*_\F > O Bw Ip)#,M,"i$VԾiڶ*  w WZ7[   3:q U pMY0k] 6rR{ Z_] ! !"""-! c   T !~""""""u""#v$&Q(r*,w-...-,+*(b&$" BO W 7 _ OvWN6zE9֜ՌԪL#Өa?6Wخ/Xًig-CzOZa0U\M ;fp P'x 8 E 1 h R#KwTv`9f{S lv!v,3NZx I=,p R K + I bQjm" 3 }  3 3 B$  W^"y@y_ C8gZ2[pufLLL t}o W y+/B=cov$oH;޻ޑތއTڒמJ/aRԾ?d:۷vEAE[ WR. #pd64Xw|ql]>LK1AUjeF{(GB+}Tv%8MZB M h  ) { { )  5 v m [Vu  R q )QU+{l1Fm%O"FZoV R I   O j M l . a 9N    h O(}  pxw3A TeON4mbC4\["~i@mRV#tyQ\h+'{>Z#5ke8[g^d (`  R g l W 8 VKmBBb2 >  / I I I ? 5 : N r ; y A   ,#8BG-K: l F Z Y * 8V@Obu   |RLPEE]bI4v\=(R|YPa?L/d'epf> 5JOE:@@&b/l33=\|Y,\ XIZ S E  u B hOtp$qgH$pGK5 = o  Z  )'5qW["iJ:!!@dF`j[1}xxxnO+ NMW `@]Ce6hNN?% MV#tK^|pz<~dT6!OVfbI1C .4!oW/+cUL  l S ! & 6 J Z Z _ i  " K j u o ` [ ` V F Q ` ` e j j ` Q K < -  n U E @ 1 ; U n ~    "   s Z E 1  w I  v b C $ f0b{#1E mIf$poxO!X9{a8 zGtU6}x}xY:qM9.4>MXX]v0T^5vg]]XC9CHC.zafafukG( te__y-u$]%Y}!Ei -`.vXEn~xn_TJ@EiAoa= %944///9IhJjaC+ dQ   . R m + _ ~ Z + } % { B2`     [#Uh?+ 5^1PZjd_K1h 9kB tKs+|("6XWp`L7U}Iq]RHCX Tx 1@UiittoZZZ__o (AVp)) pGoU;1&1JZdoyiU;!mhT?:?Nc}&Ei#(# 2V3{%m+x,[(.8\3ar!ja4Hg D} ok H  r + y ' F e # = R l 9hw|b9 f   2 + ^  W ) Ly6OX>)pW=#oK'n5/8.t@cN4v=k~&^Huz4lTm}hTI:%0?NYP AeuG#EDX>l||qb]XC. RN_uC4X|!@x"`8L\av{kL3=Rp$Hq4XJx6ou9D;~#k 8 l  5 S w  + 6 6   } I { > p<tP"hY:lSMHSg5h"1PtyjP,hT+buAdw{ A;r/a3pL(_; ,Uy(# dE}YI5 %5:DNYmrrxmYN5vH)$>XqDdytd_t-e)qNmc? ?rc/ *S6<.a>]|5dFBMYs^D5 %Ix6j-[u  3 R q I + y  Q ) 8 B = = .   u ` K '  n O + w 5 >#t"}:qbH4/$ a=`,}Y5h9q)(z"s0m*g.L(_1m%$\(8LV\\a\\\QLBGLLG228Ba.N@<u-t@ ! }N05h1tp\?h6O~P WWW)L# =k)8===HMRRa/ri6QC?xK-Vz  3 \  5 Y w c :  b R M > .    uk[7#2<L[kupf`V<~_1sYD%q4='^=3oAxJ&|X4v8uA U1 !1@Ui~yZJ1c0|H)z\VB2#~-=Qafp.MqYU2e$=\v4Dcw ;Td~xd@&T'Kj#.Ba H%]  +E^}PyBa/HgIP` . v 5 Y h }  1 E _ y ' A Q Q K F -  J  i E / 2cD:+TZ< 3 D y N  '  yhXf \.=B. {']6 E2h_V#%^d5/"Jw  h m d6GQnrH#@|)<~1m^mc:g9.Xx7; J-{SOeE9V Z b}<~w5't z sjW{1?HVyTO_k# B -+/F  # @o7xI& ? \ q R =lXaLr6 2L pWNL(+GPp}^|fe< \H;vz&e-6+n=U: ~ ' O |]a D O `T,+ [9r!o90\_za Q߈ܳۄ ڦ?c,BX:ަm݋!զӭ@Ѧ:E' lMsسۨ!m\g XQ4M _)~#0^!P"##l"! S36JmVrH1Q> Q \ub?Fb >1~99I,4k0{ vQ !"`"`!!_ baGWR $(**)J%   R ^ e'P tazt7q21xb`ٿիPChڂpr5_:\  ? %Z%e"$?$$/"kF>8\h O!@!@ MM wH B]G<%Y>eѡbZz88LĜa轎ܸܴ ] >FZ콷nĵ.?n>l{ڶ܀,eFJynY K4s*sl!,#3%@'3(*F**)'%# Vo`>G  Lw#Y5/H MwOO>)E<_!!'$&%",  J  :)17K:9M5.%  yD!',M02456:54.2/(+B&V  >(a6"L&Q((&">5 fm-;G3lG2f:/SCE CE?ՂѫπkѰnHaz3"DW jw Pw !!d%+   $oS<19WD j|~sX~ kx%/$.ƭJݾȿćƸ4ȿ:ƨ+ѳJŴѶM'3@):ƣ Rif0ҧn܅߱@b>ylU{ Ums6,n1 !#%&'()5))'&2$/" .DX O . ! 6fV|NX4Nrd l ~.w %b A"2$#R +m= X# ,/39g<<7:D730-,C,.K02Z3210W.-,g-O/3o7"9;:I7`2Z+#&sqOE$ ^ p8{N[6֍Pێ?BӉѰwGZD{߈ڗ9Uo.1KB9 -16, n)" K"-$c&&&%#!_\N!"##"VTT <|La4 9߼ّܸnpХ1*o$;nj$ij *Xx3Ja1K^AMQ̲غ)AK1յ߬$)uzQ Fx4  !#%&'((()&)!((((((>'a&K%d$$:#"!dW.] y ? S I (*]8b>:}t~}/%wtJ ?  O b/m }y$Y s!,6>BC?:54/*%#$#%E(h+-5/-1/24\57U:=3?A @<=q82+-" (W1 d K\<^PK@NOAt 8Wp"'+/B1S10-)$XG!#\%%%%&$*"!PMj[ <5@b([,>`B׷eɬT":JU9/e`񳂱\ϮTGoйسۘ~86 B "2#H$$%6%y%%y%%&'()+2,.P/11110/(- *'$r!BkgS ``5kL@KV? *S !S -V #  +O ?WE,*uRNݯӣoT0YG՛ع8ߍN'ֱORHAVS0+<W,+ @ =tD !E 9RRzz Hyg:h M V Vcb;8ܳ}qn8-̑ī…ſҿĿӿbp-2u n#+kǚʎͱӭ!GOf}G*E e%' !!"##$$*%;&['(*"+,.,/#/0W000>/-,M*)')%d$:##M""G"!!!  Dx J s]Xq#Arbf">i6\D!Mq| "UO"z&[()i(%!t&qB3"%1&e%d" h #(h-x2s6986&1r,&" Q!%_(+G,S,,,,b+Q*)'%"] $\F I j!Xax ަq܊1s٥R0?l٥ԯќ nؚJb,3N~yPq1 `j'hF-:?k+ X : %<1 \h$\jqZIGٯ ˅TǐVűŃ~o;%ٽHIbu:N` O6υЪчzڒ4&/d q d W^{zb "$')*,-.....Z-,+u*`))(((''')'{''G&&%+#"G qx4 t9RG\XyD6iP}MWJ_M\h )d06!75/'.~ Ag  J +{4k:> >N;'5,$mKik &+.0\0C.,*('3%$|#""7  p v 4k4K/sswA+|ٖCw,jԐѦɬtgu`QY߱ޑ޵-hSZ{2qh C lfha ! 0M% c6uyo*r6Hޫݐa1خFհͻ[M0"ʺ_,߿F9:+ɢɻ&zۉ'yl d$V"$&'(h))*e***+B+,-}./f00{000l/.P,+*<(''&z&%%6$w#M! -~xb ~ ;H*aC%5N&aCqie+ #!$N&A&&F%#{! <T,%,w3 8=b@Q@=8\1)"r> I%Z)-x03F455 31:-)$a t 3 ! < /\rIݕّ&әcѰXkަMߝgTd͜CňīĻXԤr}d NVS,hs C kJ~eT1kgs J K{"%'((b&#8 ?"hpe" x˩˹/͂͂́pàȴ"ӱݱ8f6g0|t̯̪C ̆c܅iE  8 3 M-!!%*".,1S3[4v55|5532;00/`.-,,4,l-D.o/k/0C001*0/Q-c+*6(&# )%54 v f a %w V  G0m rWl..0:Y:)oc.h6#'{'$,| Zd.X ^%~),/37985/*6%J!@{6!&+G.1D3F455r31.+($| -?) \<, qai}ڱ׷յԾԅԴ ՠۭ#r͇OH M֧?WnagAR#C'd6b Y9V=Is  = _y $N'R)J))@'W$X 5 }hiA,8<pКΎ0rN̥^Ka͗˾O7Š÷ ʱ 0?İ-X'Nk1gƔƉ- ! I /5!,%(*+*($ : $fG/d>P{ՂϤ΄yΝηηΓ6̛͒8Te) FiH="^S7Ⱥzv˹admǴ?ɍ˾=Kl&j7jkI2 g 7rByi O$ '+u.1485777716n5]483'2;1c00M0008023V4G444432i0.K+(%y"-\ G >5<3 * pXiEx=c *"$&-&%"L z%j -X(w1:@CB> 7e0*o$)+^!&7+=0{5 8L::x974G/*,#X %WfqYZ 1 '{h (Wݯ?Ȃ̯K8- ֍$}g™'۝&Wj|MBbor/Nr epZ ^"k"!{MI ,9u l#v(]+--+*&!P "]>n}_+aA J:ɧ1Æp/˟TqwYdƬª|ɫٷŽKȺs+дΘ́Oaҷ'{g [uoq!K%E).U27:x=b?AvBA@u><9521/-,]++{,C-/135]6767'6531-*&#t A i  + )E 2 1=9w (.+ғϊTˊJfט G:I_" k9SU 0S4m"v8uZL ) J 5uta7|T@ؾպ)ͱ˅Ȃǯ)ƭ ,Ovy WعL鶹µѵ8¶l:ENa+s йҬKٵޡW`Ts > Z8 ^"%_(*,/-1I3-456+667K7~7o766J55]44G33222E11w0/.-,,*)T'&%%$ "!,"8J z ~`(P'Hw.ii fMqfA  < 0!_$$  '8,021/<+p'=#)q!%;d4"$r&K'()@))x('%#!D@ V+`.y::0a&Vײa<Թj OfT: {ѦϏe"ΨM T Z S0ZT!55 LBۓګY٥4ؚ֒ 2ĦЊ…lTdƞTʞ˾̑^xsnn͍jfҝԪ]^ W/" g  5"$&&'(*()E)*Z***Z)((/( (),.y023433F22111r0g.,*)'&o%%$$$%$$m#"!  + :KI4 hx 3 e 2cQ 0KGGu~Zf {c:o }/` E  sMl%ULPffL_I wxbbk'n,S?^*Ojf8`'G 3 DR)j }$(,--?+)(()+f-}/f01111123"21r/.i.03'5I541-* ''(D()!('k&A%6$^#" MW !"#8"p qXVzajv>D " ^.myN %Tt-k1 *p5S R n"3qw4\B] A W^]0U / ' QK wb4#[n])hRkGKA3%JJh#Y{?V-ߢPKߧGm X*xn=% FP,AjW5kM/ 3v{!qߘYo3HV] % } Zw)r_N &[)*(h#"Q+4995-&""V%(+,*j(&&A&''((***) &%U$c###$"k""$&"&#>B"  `b|X: M ` W@ n 6 e J . \K  E & SD n s  B m S  ^(NaL:<[xjEbfBb| ]4(-#q3MS0z#T>uQpR06ii!? 9.`c 7Vn#A9#6U=#BL\9}P~@hHQc.:hls}b.LQ*; L)\M@dac wao0E_YT 0Az5: U fDi v%l}NqF!,Vo x! M~`S"&V(/&u!;$?)*Z& Oe%a!o#%'&$r h~I#%;#a[qGuJ) ~ko&YN  M U Wlkyd4I1.  }Gl:XpjB)avCs&05gmw@lMaaA\p. (]&+^M,[c|0OK(lXS%4rpyCXy!@EYS"gdLq Nv WU<%9HznTES+Rw42qP *Pv]m 2V99?  D e n!eY 3 /  z]l);\J__Dv|./!!P]wh *2wLs]U Q Q X G  1 s +6 ]? $ .k/.rF<8BlJ.la@dX'9Wct@Ka=qwXAlj)L8S.oz'a %IZ/7*+CT0C'[L`HpsF'+Hv9*=8rAIQiq@6pIV0JBN2$l:i_ @ .]Y Uo'/5Qxi3@ QfD F 8 n 8 Q ry H U 3Q  8 / g} 5  O=yOdat * d [:: H m {z- b( <Ul B s  >  ~{'^4  E K P #?4c z H7H| { u R,5 + k NKg  p=b wP'(/ah+udvt={$mt@- /U(@c JJmTAHfYBz7m'o9l*9+kA+5>][|~zWcE~4&0to.I >*cJ.x8"ql\l{oBOg@j"jkH;bG:1[ 9}8wX< /=(@Bf .  @ } vLB d  d (f g P   / \Q M v { $7P6`fPo ~L [Cp pK 62z W 6slF K y  M m _ ~    { + 3 S    8  d  h  & m/ J -  O ; h l7Hk"[B@|])|^T%{X z89#JL68,K8,XJX?b 9CGDy_eU,"1;T}w:GkV'1-F:xt Kz$$L&%bgNhr@C46=VW(Tw?/Irw $V_;}D 055 *N}},& mTD::NcTb9pG==G\kV=#2B=-#-BVpufapM Icmr_.g4r;K.a8>wT"<`8WS% %:DTm"UV  8 > > 8 . . 8 R l { v q \ M C 8 ) $  pQ2t6}sDSaG=-eFs:!&5YnE! |mbhm:OJ+&rb*vfaM8 R.#38. oFsOh4 q\R.[7 _;}TD:5% **  %%*0DDDThrrmhh^TTY^m} @_yydPUZZ_UPJEJZdt~ (77( Xq+%   5?DI?:5Icxxsms}x}h?gM$uuupL3yeP"}Y@+hSI4%vaWWRM=)\8oV<xiZ@&|mcND* vR.uLtiJ, rYNTm}xxrmhYIYhmhhr}!1@Pdit#--2Xm|&O}'e-=B\u>]l0?:+%%++0+%%:IO^ms^I5+% :Y^?  wgSMC9)$)449CSbglwqbX]]S>$ f8yeUU`e`[ooP6" sT:&b>lH.{W8(oV'dE0&rh]XS4%{gR3  pV7toottot~yoy #a83B\kw?1@@'s+|\[ }T&]4 vaWM=3$#[""= RTDWG2kWV.\s|Me(([zzzpueV2#7[C\q{l\H.e-#7<7I!\= ^1+vL{CFC߈ݐe9Me!b% {  A  @>k4A!1"L#>$%$%%&"&2&F&Q&A%%Z$##" FI<4`ky ) u % v $ g D Rl ;I/#js {BJ^L'b ipu%+1|6;U>AC+CDCCB/@>Oڡګs֍IҘDΝ+ˊ(sQå!ݪK5a"',048:<>w?_??>=<9730., '#RW& Q Q /Q[:2,K`uܔؤԴ 1oº.nV69YZ$λ*^|v8׷N{xMSlvq=3riYaM>F5v])C\,ݴ܏tۓ ޗ_buN6q \ Se];c,W !"$S&"(4*o,.02~4=57`89g9999S876}53u10-+)5&$"7IFc@/ ) ^ k QjACP/ eIv\ SO$*1:7o=CTHMRGV#XZAZQY&VSOK FXAv<72n-+'!Pk w׎?ǕAEDlc~gDđoL{!=Vڇݕ_*E \S &K,282=A\E H!J{LMM`LKIGcDA>%:c6J1,'! [ۭzӳH:yȼ+s鲋kxd±i-%Ai Cɍ҃EY޻Z [itk } Vnj# B 6lq9RvїΘĜR( CGBCɍy56Xs ( !%( *e,S-//000000/Q.U-+)'%#l!K41D6%CLfVK1oL)_[M  QX + D !!#b%'''R&z%&&(m*-?./--+*F))(9%_!Z }a*li} >R%+2+9 ?EIMOrQ`RS>RRBQQ~P&LG@8B.$N~  x;LֶҘϞAuTP?s-&þ 9)` 2w\`B XL!$(9+/26:>wADFwG}GG?EC@QṞҮGqS <',ŷsԚ7IܳvI߼;/P%M [^5L$`  1Ƴr/zjk]ui7zX8(c\Rc$   g !"7"z"u"["L"G"[""#H###$4$^$N#"!@/^ 7TpW.S>XJy.E v#P!%!(/*-?/f1/234567P716}5]32@0>-*'f#.vQ,%,>qh|ww?/5 U5|X v ")18>CHKNPQR\RRRVQ N{JE#>*5+ p rGڇիƙ~9ǰ᲋¾ĂA!PCnfo   1v[! "u#%&&7'3(>)i*,l.i03658:<==)<`:8=51,'G!I/LiԴ\UʶIJ]ƩLC̴2CȖELQVZ]J^^^^<\Z"UPIA9M/% `'6 _ϙ.ε]^ōqѡ׷qSX b ;S"<$&(**+8+***U*`*+-.035*7,8::;K;;:9M7"480,(#RB uBnMuѵʓݽѸe\T-y{8#o!  7eVk" c BLL#)ٵi<sG\w&Шģ2 p>9ӏJ{;4F I"'v*-Y...P,*'$!;yV (lH//I2P4ד~ f )X_1& i R_ l%.!6Y=CIGMRU6W>XDXhWV SqOKE#>46E-Y#`RܔֻRx۶H2ȰհVIP8 K"%n(*<,$-./k//G.--0,,>,9,-?.@/u0123u333310W.!+a(*$^  o@Rڦ=-#$(jZ)} 0xxVx,Q b'09?ELIMFP!R8ST%T?SRPMI[C<4+!NsKmg%ϵҸ@Yoֻܽm?T m)"p%(r+-}/1%2O3 3e3V210/..,---.E.......1-,+*1(m&7#\  4 8\, O+ټxeݼ: ͇ч 2 Jc{ T"$X%i%%i$I"fg z W+xtЕ̿nƏNں\Ե\T\32 pɶԀ0~{ M !$%_%%~$#3!U$ DZ= D418ݕ܀ݯ!$bz#JX= !%AJuwl"j1Z^6":.@ | 6{^De &p )T18?!D,HPKNPRRRR\PNJD>D6-$cy*ٺ[1JEf1׸b'Fg >! #'*-03456@6&5|4{3Q20//..//tʹǷŵܴ6Ⲫʺ\KYțJPמL=l 2ZyiS!#$$#"   %B 2# u(F$" e:@- !"<"""""!E +U Z#C&$Fk ^xJjo%C?a '/7>CnHKNQ,RSgSRQANJE?8\0&e sy8q,έ]@Ӷɸ6 ?Ң;`  "%s(+Q-/1S2n2210/.-,,+, ,-+--. ---D,+*)Y'%#b t )3(A6{qٺȺӻʽƸʣβ'۲ua& ~ow !"V! iH@ f)&\%4mvXՇ'GʽǴ<ĜʾҼ%!+0!k7Ӕ؊ݠ-.a l q3!P#%@%%~$X" 5tq/F lj$V.ߢSKIp0 ; 6q_<a*51-BGj2WFB`v)! yalCRu->SFs4 @!)19?EVIMPRSTSROLG5AB:52!)&| 7tv&zc=IˮVb6YK̺|@g u c#%E'\)@*+,++V*)((N''(9)+*t+,-.y./7/.-,$*P( %"k 6`oYN9߃gɃ}T'yʨ5߈b, %% !!i!P ))@ i(,cPbJט40ϔgʷ˻D)27+=0/̿Ѱ܏c'%! UKnO"$&"&& $"px Ip2erx^$eG19Rt}RMs 1 WYk}<r!2Qo  KmF\^)+ * 7 l#P9~%KI U"+#4= ThD> _RJ  a`;%-04;_@DGIK*KK IGEC?;6i0( mc9cY`˳Či+_ɬΎӳݯ %{ G}_ c"%d')T*,-}.0\23579]:;;;~;!975*1-)O$b ~V_ԕq̖ŝ=K7G  S }'"Z Q   8DRaNIQk"MrߍW8WƨQ7Яdeҳ߶|Γ 4 l \,uhA:R4 8N'\AZ? IUQq?!AtF,e( \4c.]BX x m 9S #  R w v R /-y  fjS sh t2,<!? s*,3;BHMQTVVGUySQNRID= 4+k!H  Ez<=س5ȵ̿׿btz.@L 0K3pmB h !E#&o)+.2@59>:5/z):"t M0(NhBU٥WaƣɽFȻT(e8X՛2V8nI W #l!v||B6qd  m "3@e[-2Z:GɗӾ3Ww_k{ r[LgW#~ m 5XOTbE f kP# }  v@a$Dai" q, 6C7b !"#$%%&7&`&o&%#3   Gj<5/Cxfd:4j vh*4CG&e R#,5b={DJO%RTUPTSPsLHdB;4 +a! o>އb܅ۭcعDԴikkv_=Z o2g C7@P# _$).269 ;>*@uBDFFFEVBX=70(w9Ta4u0V̆̋6ϸчӳ6 ,bZm!; }cgcWP*!3 a  N }_Az jSܮטΘgx꿵_`Z&͂TYCY;)m . , w GG,O"V3KY F>Q +)3N 8zq2 tw~9JJO s~aLy=!> @w A i ^ 5{ (fc+Tk  fQW$/*1*7=qB4EG+GE=BN>:7"3'.)$3@ &SJ5^\EZlb]>ՑӞVԚ'ګ.({$*~/37'9/:999888987~591-^'!} eqzA[]KL|7iA8w!"##! DaU( 3 TMH 7<I`U !"#g"!=%<H 1 f* gRc! 6 hHٯ׉Ռ~ѵiMZxvNrqQiw6e|w\,~=[;(_j_nHb5[\b" J Q =dC(QW/&&r8o'IOx@]q8)#K%CjT(BKE4  ^ QL   8 R5Opz8T7c {#h:E: 0 }a 1@ N+2'B \PiCj W9'k&G֬:yպ.'}r9_"4I16  a51 OAv k b0#>#oT0Uؕ qυϞqsou\i׷q9+Ku݋r!ߘߧZx%0H?;2gAX \)XX wJe R - \N!  (tm|bH  $w   %|w v  %3:E[{ I !!"-"(!!!!d!;! m c !! MuJ}*c_t B / h  2I3Yfd $ eL15>>Go! . ^*who#7~ =|c/rHGZY4n_`f{+ESi'A)9_z&[]Abj  h d  A s Dh w@@s /a=eR*TzZmm v3ZJّؾ׉"֧?\uұѦDйsoՂtًۼ2?XVWaF(H]x|L  O~f qqQ T-l?^wcI:RGh)4}ZGD1s N>[j,? V?!{GH/{U  o 8 * :jOg# H r = v B c M L > D N >Kb[prKw%cx^Ru&e\7q^ +C)\|OV4R mn+#G-^(tet.M}!r 3u ) r%xGUi[ܔ~n|BWة |ڇ,ݪަߧ"\ '' Z ) h&\>DKQM?!XxLpQ(U6~LqMk ^7~*js BP"sdTOTEh9 9 l  ? D m + @ :L  #a4t2 g HaL{{BAEbRm8^1v`N9S^^cI,Nl'6a>I"8ITez`zAZTP3B{a o9{?go+h9$P 2P^Xf%gQ߬iEE_ߘk4[*c6A_(>+P6cL m 1 = ^A($062)j6-fpQ#3{Cwl>QtTXMAJDg3(; lB`x] 8 u " ~ ; h ? { g M > . p( HKEb*MvZD\G-2Pcb)fQG-o,sb37Ohap(oo(Lk3gX0i'`(*|&iPklDJ-V pL#iU@;;EPd-`a%c+6@JJTdxxiTE;!|XD/% **9]@'z3|@y9c- D V  @ g%Vy"F.88Bk4I>% vR<!qj_j~d'5+/ 3 7 6 D \}C(@rX(ZrM1i4L=WSneQ ]5;#laQ~1xrcI%$#J9R"OXh5*DrU -`=? dPBX:Az$]5;~<l9+oM]E 'KjtteP1 }E >v\B3)ft/=Lo :H )]c ,@@;!  ,JU_oyio~GuS+[a.mi9s, W *  W2/n b  + Y } x s h h } ^ +48"^hq<&.f:= R & Y (sC"%{[im;i8e<2F.>r T~\. t(8)( c$KXV=zMDr9 4Iw&~e8IcBb5x}xdV8a{\=8qN0End %`,0q\y6}sxnx'tQv@`v!eW!6L9% ) h  o 8s'XQwK tag x !i!"`"##R##$$N$$$%%+%J%_%d%Z%@%$$$##."!! Y35|QMzO#yJ =  * H`M{@q)8n#oI5YEZPE1T0]k 66a HbgH..\AOFqG;,;6?qRMXX]lv rUp{ `L%Nw5Yis;tL4m(Wq\C) .Mgq$[!x v9p= j's: +Js6oI[JB/x1|?  ^ + O1_-+Kqri`8$  x !;!!" "7"f""##C#g####b#3#""""B!!~!, :b{A 6H; QJ = s 3p"s>^2T=#yo~GGyPZii_ZUdtyt~ .HC$Mk w!VW%Smrr|?TxFPZo(g:;dttdJ&rT:::Dh P#L[QQV[VGA7(y!(Knn}6etP, xs ,P(p>^7I,GqP/jB  i Q # jB j#^`*:#b !P!!"7""##>#M#g##############{#\#$"""k"#!!d 0HW`^a*>B;T6}/ K w 5|'i9p0w#tN|X..q5Py N  ?}!}mN:M(j-o@ r ]>|06H!K#ag?cnsisZ@yyJ, }m^TYN: MB_Y wI\8WXYKfX%m,-g~2Wd"C Q  } 1 = 5tqL Z"J{ + !6!""##g#$ $^$%%_%%&&7&V&&&&&&&&e&K&"%%%~%@$$$%##C""!i 9QybU[?(!] " O h {SJ,T@&9>Xg]. ukHzW%.> n,tf$H]]RRH.4|DJQq lR3Q#oP11Z~&rb u-;sNf BCT,j-ulNEV4fH>5<G]^ju q y e R*,Wq@l?o#@G !'!"u##$ $m$%%U%%%&K&&&&o&7&%%%%%%%%%%%%%Z%!$$r$ ##"!!U 0a Y\5Su:  MfZT>8<Jw){XV:.ptAFLCIxx048U;61KotyyoUAAUt 8kQ1cVd'x?] zG~jo(\4g|RaVf5\ "GCT oQ> r!x::yLl{M=R=p 1cq9G~;nJ&|S%WeA",tG9E_\Xr `X7{$h! vS+IQ*TL % !P!"2""#W#$X$%;%&&`&&''R'v'''''''''q'R'#&&&&&Q%%%$$#""p!!d I$o_L[j: G 6 .j+D b d 3@0> [ {NmIZoOn^z1h-i$@ClM )q|Q}6`P l<h\ l _ a v qYYmgzܮwԟt͗308\I"gԐvxZMH(۝۷܀mad!H  n"$&&7%i#!du] HyDb2 v:a=o: PV^taX:9bYҬH ۲? |p ]zՖ,Z Oר ڗfއcoLLXmild NwcSD44?I/ #,?MLK^ hdKPf>mX76 ,z4^`( T !!_!t!U!' 5*3f#l8u6wZS ,T=<Q   R9&& 8 !?K ё\Kb w%+169;~;_962-'!P Vwk d ?5ن>5ȵMΫioFqz%<\ :"\ tIhO  X%"G Xۼؾ.\N.7y[pl\"ls_#zߢߍ߬ .+zx?k)٠Ju^9А1M܀{)3 XD+C@/V~iy(d@lq#?1#>G@AVx@ : #r !""p"f!!@ m x !1!"$|&`(r*o,$-/0>000{/.',C*'%" SZ#Q1 F}" yI/:3 V - a9+U\@bf | g<z Z O E~,6Æ09hrv1"( ,0\24f432;/u+u&[ } wI$ݾs.[=ڱ ׷Ъuǡ|dmc: uw#H& '''$!A] Knjao`Wd]  s  6(tU2ZS| ߢa4 'KmE ^ZZ=T,^~)x׎Ԛ8_țțɃvέ2@@^ G 3  @kKs AeU1@^g`EKucmq [1ja mx~#Qu !"$%%&%&'q''a&<$" xk<44q Y I %;^|-g;m+nx&>V o=/' { ~ %@t}D !  \sp B)RDJ  Kтb3G$)x-:/1221^.+ &!xw0 "\^4GΓ.;˩)ҍ'Кŝ%/owRϳR2 $ gf!!#%''' %@"Q# *k,T_?QOm@z?خؤ~ݴA =z )|P@R wGi4$H.:eަ1g׷6=ӏoE҈eԅڒ0^{ B(W mwy&&gqK~TM#Ed 9\"l_ ]E Z=q s!"$$%E%$w#q"2 | 8kFYJ?.(j_+|ew-|/SDCAn5U#IUyhZ  Z \ f rx<A 3 | K E) NRIߘ!`μk YF,%@,|27`:]=VPK'\_t|^ ײi?Rkҍьѡ@ӄՑk2b Sp?hY B ~ -Fm+W("J ? v'-3"7:==<29M5%/)n")X u[*8FPڇ+_VOm̯?զԅdGMƽOשK4G ڍG "!E$r&(X)+)0(h&$N! "+ :HX,7kmN^nr?͒^ȵ>\pB݋c ~W ! ^}e f>N*v,N|qڦ׎ԾPCΝc̋4b?:=0xZ 3{}o .  {g85* YNdX ' h\/ """""["!!!!""G"#$|%O%&''f'''=&%%#"!,gR%_~3U ^ 96{:M^= \x F0?9{o KS63B(a wWDW s # & WG-s]RȿEt+a$,3u8V4)+A-W} ) C,"#%E&'&'a'( (*((''''&%$N"!@'oe)k.z*H?)# \qmj~yfV+ U 7[< !<, # @vn\ 3,p.D/ 2ٯ΄Ļ7i42!'&+-D---,w*e'W#>WS;TTKw}6F2i+tf"l=XŬϏ)Do M I S c4} #(,///,X'!3sS؀I)VyA#Ə6֍ڶޗ/q;W4 $ !6"#)$X%&'))*t****F)(|'%#"- cWGv dEG( 3  <u7K ) V m 00 \A  i! vX~ݪғ"ȫ?FԹI\/!K"#."z!_ Y|aie{  k2tAtVv0Eckޑ7Ϟӿ6ĢyݡA<ٹsvZڇߧPUc4?i|kAp0W\ nL ?$(+.1I2210-5)T$h( (""6_o3!yF(~ߍ.a;q ҝ ;ܤg P W W2GI rtRqBa #^KlK11BdTw w#nW !!!P (O`:b  p''3EW`d.! #$&"'B((|(|( '.& $" 1v <{ !"#$$ $#"[ 3M F O  & } 8 f o8P@ 7 &[v0uat  ) c.ׄGЋu$Ҙ֒: \0&!+ S Ld,_<8`;0'jұ9ŢOʨB賜 дտ&en@D3v: u!$&()*`**A)^'%#8 o s =ki' Na(xQ]=.΢ϸ ՌB6.*@{X0 M + + h <n fe9G|}&(L_I*[lfV*o485@<R:92H4'FR7ݾtbטԪӔEѦ^* 5m!Ҙ/~o.xT1Xl3|&&\W-dZ^)P ?"`#W#)" ?#'783\!;#H%@&'f'''' &'%#"!qUP!""!! w3;Nqzub  UOOYEb l  bL l u+T] :Zu9W8nNT)?O%1Uc#X!f2CvDbPT Jc?8@)Oc_Jh[\fm7v~>{ YܙPڂ5OڶZ#ߓ7 CWM888R%ZNFk$ 4UV?K- b qPx1 $ c SYe~ZX  [  Mu0yO:::54p(v #Zc$hdzX]{6+&6n`lp#  v >&:D 1 #/"zC\(O+! po J|"%O&&%"QMr } + f' "##{!uJ  2 W d iY!y!dw+1;N Q r% ; D } Nm a tl=a_"k D[HJ`vp,a"l -; \#()38W *$`@aE)}H=x#i1-f\\S} . N U ` W  s y M J  c  'b p{XsW `{O#[3= bIh b  O * F 7  bV Pibpz8M$Z"c1 y = N }o!dscU6M A@%  * 2 rx: { \  c gf\B Ba8f[{ rPWizgW\ 2}X=|'G8` aeAGQLLklmtW=kCtcu9Ldz! G>x]l-6XT,2XI LJ(;I;q\h<}  hd"f)5} \ 8`>@SI5|1 > i 7  .?*3W3F S Ed+X  "33 ~ am z Nw02 ) vu I "Y*)51[Ei,p=B V WL *#'b  R  qj;t&OF'] v+_kY 3 vi  5  k! c5S ! 3It|`c~Vd] 9)8XDDs6R2a;8$)MeF4me?H~FzEU-GMhdJ]A4N;~Cj\kP/SZ('NVf.vbL/2W9O1*:XG: 4R2q B  38^ E BD mwt} W CB)fF ,]a=s^Wmd|g0/^  qhQ Q}+O] \ b C {;n UK R 9<6[W )]k$JD J  $g B@jHA s Hte&N|K  gf"4 d# E(g4" ) E lAisZ~ E"jx|l^(7CGIvb/q!n=Lr`\v*2govFfavc9iEk'e;U?$ ^r| 0rBiF3);bIhR V8#aVz f q  w r kZQ H r >ntW PxOJ.{=W V&D]NJ9ff>(Ixd{^XF`EC 5 q0}1~mSU Xq `@uh$ !(t rLw]&+3HVdI4Bed ` l g `Z "u"!t8o ?tq zkBs< ]ZyaoU b 2WD4eXSoR_g+/qD~ӉٯB%c FFlMS='PB&1|w{@[9 7 E8^F{Pܸ۝ڡ"&_Ͻέr{ʭAɃEJɒxu6އWEM3,eM " &@Lp o 8 `  >f'>hs8 B  LW, D!#3$%'\()*,--./u0 0112 2n23V343455S5r5g5/44B321r0 .-+)(X&%$X#W"!!U }C*e^2> {<\yYP M "N K:WA KUK %NN $-l+ W J 7 RQ<[z1K_M>|r*ٴe2(n`˕/i'`R W3!$'()*")(h&u#!^o  l 4I . 2uvM5֜Q]˹,Nl8.C{Ǿ Ȗ;#wpҍ^֗ר؀*٪}FTG( "KoxN h K XI s  ?o . { Rb.Fhlkjx\ g j# 6` \ * F F_ #!U$'*-m/13546Y7,77777`66d55w444333j3`3K3732222y21111c00>/z.-,+\*('8%$ "z g+qD'` -| 3   < J c   N 5P 3o ~{NT=<Bb0'f2ke; O'u ' {f`Ve0i``/F5CŠ׻¸, RKīNuֻ٥;<XtMZ'LDp 3uu 0"$r%_%n$# (%8 if"nm~Z4ֻӳ'ȇdžƔƏ3ȂdeˊyH҃{"xg>adw` OY \ Uf[wL'pKx3 + hg8C?E ;XKY "G#C#$###M###3#$%&()}*,l-/03112 211:0/.-s,|++{+V+a++,$,4,++(*P('3%+#!>s>4m5MbX/I(fH^4r4[ >Usn:   WYX$ Lt/"A u,Z߈#֍ԋ`pײH  MKyj ?0 F g !rrlVx n$k紼߻Saϳ Mf(T-R*,tQ?tc8 D :$/'*`,H-D-I,b*( $ % -83c?[kPT|l2݁ڂ/`ьϮ|)AV{O҃֍Wt%j$ISnyaf n 5 r a 9,H0*MO  8=l o j?#"%i( *-+/[1:234B4B332210/-0+L)(S'3&`%%s%s%&&')''((%(*(''f&&%6$4#! T"-jo\XZTqdN{6Dgz(;<.:;2"2<y:6  y kqR#f34s[pKL ΓocnfדRpq $w)+-/1r11.+#%q i|KmR;3%d~^=eDʉÕdllӑzmcp4m!)k }YNw$(+.d02!23-22@1c0.U+(% [It4֗*ȑ2ŃƳI7gέҢIi?Zq`w&+˾Uќwc!kH Ra6M ! 9s y4LB|[ Wd<ݥ۲Y٠ٖ!6ܮއF0oea" @S +!#%'*6,.124a5|6 6055*31/L,)&# B 6"<"6cq?56l _ %^ "#$&K'B'(/(>(''#&A% #"B!' 0/ hGAsD-{[O3w jlTA.cR,,:(g  I [gylk0*A۲p !'&+.1%233j2&/+%  D$nx}K ё)z-6akq|%o!l~iٛBz / % >f  q&>@&3 %!#R$:$r#" Rp ~,lEXoț bҿN€lP^Ћ'ڒs=:d  #' )+B++{*1(%+!t UT %Mr=68# I)V߼EއNcߓea7Z)sJd  m!&u*.P1234{4a320/(-T+*e)@(9'f&&&j&o&&&&V%%Z$#"< i=&$6Mt R h #[Jd\ r % { !_"-"`"#\#{######C"! W 0YbgUJ C ! J  wA0TwmDki   y ! / 3P(mw {҃8sbzm( FH}M!#$#!%-=#(';ѵ Ns/]&Əq!1M.8h!nO 5>Djpk r J  s m gp_ ab9O1  a F^ v/ZD&J.ۨh"̖v޵{i*i {u A^ [k^^ݥIΨÍͦϏѵzaaӭE.cp¸SAU9ѧoi嵳đյ S$(,].01400 .-?+p)'&-$#M" Wk/< J/p6%πΓ'AЪզع߬xs^E R oPP  `N~n m # smo+%n ۼx XoY:xoD \ l# #3%(]*,q./(//p.E,9)d%!7 @(  Y>h  J2SVh 2 .  & DUp& C!U#$N$$#"V \o #N8T . [ 5 >5GJatoXA$S'  C7wDi_ARAK} <%y(=@)ˏˤ\We  ee# dou3ciFՂ ՠ{Y(݁>~عNǤҺ Zuu-̲oɍѰٛ=m )5!&2),.U..-,l+)((X( ('((9()+)**++,,S+*(%!  Pkhݾٿ}fEɒϳ޵?4V|`(XO], Gb I"L#$%O%& %$" U  Z'VI܀}*؀ًؚZ#=)ltVI0vQ6 S"#&+8.1^23u21 .+f'$c v I0 NC<j5N 7 aB$P4 5gi/bk`!ympz MNwx +@<  t8=AMp<+\<`GkG3v@'aOL   } 1 o o  _ ja4G_uq6rܔܮ$_']vm8{RzzfVK&0WߘGJӔc ̪ʎ$Ř+Q-ŠC5_.͡40٥4-`ti? GeO  "p$%&( )+* *+,,g,b, +p*)T'%#C v%K b=f% w,*kY0ތ1*02MwyQ!z!K  DFB-:]B9 F /s ^p{[m[v8KO&J$NKk}  o) 7`vG> }!o"("""B!i I1"}8@ 7'E~ $f(g W  B,7s8C h!!U!' :8s#: F R I R 4dxAkrX# @ E 84!v R.R!ߢ^Z lLA!haUZK+,k֢ՠ*%՛de[ENҘa9ʲ!Nj(!ćYĦŘa8ׄx t= $9"%U'3(h))@)((D''8&&V&%%%& &e&&&&7%$#)!Q K 5.aަfڻٛIUܽ0p!:xg T*w}%K% 3YK;^Ic*Cokq<@apv4Rd)  h y K mBM!Z#$%$%_%%%~%Z%+$$$$|$^$#H"2 w&a + h>15PHp*Je 8 A YU.0{="Y!#l ; m ya*|*iS&Aedr?/4c  Wp{_l4FyL9~XT(N ! ^\jc&S)(݋'70&عګܮޑ8N.To{c1Ԫrk߼Eb! v5 b)xr2')n`W9 |*Chj W ?" Q4Jz3# Zp0vUO!nn\mV IWIc9QF XDDmU<[0L)tt^A?e( ZMhTyt59 b@ Z"L%!'q)Y*,4,- ,+*(&$^"'dHKwsS G K  c  u\5A7q`muy h 8Md32M%bfF-eM "####$*$4##.! O-A 7Dv)l?BvuOm`Ztp_e)-Lyhp(GT:9k=Q,|3  j  .ov64`'$Cޡ_ Lߢޗ ةz6˩O>űĜ,ț{KA_9< ZD:#)rEAu!K"$&(*j,>-/`0\00/.6,)Y&"`aal  ~|[  AV21.1t*qG0QD # f wY5  u 'I'n9fo~(G Wi {yH_ |i;V ?G*s #%')n*6*e)('G%i#! q O!!"G"u"G! I} =|v7Vr`:uKlSnQF M ~ F "$*%U&"&&&o&%%%&F&&&%$$%# !U!QUA5 1 @|a0),d;CB%%W7>D3&BO6~'.m-}c4| + Q o s fBJb!d~!j4tgq΄˾ɒ7Nj&֜ڒޜ>L}r  BP!nfFq!$(/+u.Z02~3433<2 0.y+(%"f sGS  z0f+>fv@d}^khh{ jec3SdF F_F%Y BKXy I="  BH!p#y 0TtM;MuX?#g( *koC!;#$%&V&2%O#!_u/jp  : Y )2 [.(*=3ER `o" Q\bFM  5ZN# m ` % \ M  @ A o  RUSod9-8 Tߢ _a\Y_ 0vGGCWKP*!}6$@ 8e9 "pAv ).&8cu5ײ4ұ4`ʷ͂ҷ*QK94SorCJ s 6g?  I#{&u)&+-/70$0\0/#-+)'%#"#! T Y } ! G~s* b@Mj~ s[ceE?x""s[ $Dk0=s{se:a)_  g q H uxHz'9=L1Na400\CY?4w=G.XBkbfLw >QUx0J9ffhx+pR%i:RW=k*YnE5d5mbnhrxUUYJxJ3qxh >f\WH83Bv/I4= )\l3$8B=$L3.3Ba Gte fvW3.BGGL\ffR3=k{f==R\WLB8BWkpfR=33=Rfpk\RWk{kRB=BWkpyo/examples/sequencing/0000755000175000017500000000000012652732202014635 5ustar tiagotiagopyo/examples/sequencing/02_random_score.py0000644000175000017500000000256112652732202020167 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Calling Python function from an audio stream with the Score object. """ from pyo import * import random s = Server(sr=44100, nchnls=2, buffersize=256, duplex=0).boot() # Frequency of event generation in Hz GEN_FREQ = .25 aamp = Linseg([(0,0),(1./GEN_FREQ,1),(2./GEN_FREQ,0)], mul=.5).stop() asyn = Rossler(pitch=0.25, chaos=0.5, stereo=True, mul=aamp).out() bamp = Linseg([(0,0),(1./GEN_FREQ,1),(2./GEN_FREQ,0)], mul=.25).stop() bsyn = SineLoop(freq=[100,100], feedback=0.05, mul=bamp).out() camp = Linseg([(0,0),(1./GEN_FREQ,1),(2./GEN_FREQ,0)], mul=.25).stop() csyn = FM(carrier=[100,100], ratio=[.49,.5], index=6, mul=camp).out() def event_0(): print "playing chaotic attractor" asyn.pitch = random.uniform(0.25,0.75) asyn.chaos = random.uniform(0.2,0.8) aamp.play() def event_1(): print "playing looped oscillator" bsyn.freq = [random.choice(range(50,501,50))*random.uniform(0.99,1.01) for i in range(2)] bsyn.feedback = random.uniform(0.01, 0.1) bamp.play() def event_2(): print "playing frequency modulation" csyn.carrier = [random.choice([50,100,150,200,250])*random.uniform(0.99,1.01) for i in range(2)] csyn.ratio = [random.choice([.1251,.249,.502,.7501,1.003]) for i in range(2)] camp.play() tr = RandInt(max=3, freq=GEN_FREQ) sc = Score(input=tr, fname='event_') s.gui(locals())pyo/examples/sequencing/03_function_call.py0000644000175000017500000000144412652732202020334 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Python function regularly called with a Pattern object. """ from pyo import * import random s = Server(duplex=0).boot() amp = Fader(fadein=1, mul=.25).play() src1 = BrownNoise(mul=amp) src2 = FM(carrier=[50,100], ratio=[1.01,.495], index=[10,13], mul=amp*0.3) frs = SigTo(value=[250,700,1800,3000], time=.25, init=[250,700,1800,3000]) out = Biquadx(src1+src2, freq=frs, q=20, type=2, stages=2, mul=4).out() def change(): f1 = random.uniform(200,500) f2 = random.uniform(500,1000) f3 = random.uniform(1000,2000) f4 = random.uniform(2000,4000) lst = [f1, f2, f3, f4] frs.value = lst print "%.2f, %.2f, %.2f, %.2f" % tuple(lst) lfo = Sine(freq=.1, mul=.5, add=.75) pat = Pattern(function=change, time=lfo).play() s.gui(locals())pyo/examples/sequencing/01_starttime_duration.py0000644000175000017500000000207212652732202021431 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Show how to use `dur` and `delay` parameters of play() and out() methods to sequence events over time. """ from pyo import * s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot() num = 70 freqs = [random.uniform(100,1000) for i in range(num)] start1 = [i*.5 for i in range(num)] fade1 = Fader([1]*num, 1, 5, mul=.03).play(dur=5, delay=start1) a = SineLoop(freqs, feedback=.05, mul=fade1).out(dur=5, delay=start1) start2 = 30 dur2 = 40 snds = ['../snds/alum1.wav', '../snds/alum2.wav', '../snds/alum3.wav', '../snds/alum4.wav'] tabs = SndTable(snds) fade2 = Fader(.05, 10, dur2, mul=.7).play(dur=dur2, delay=start2) b = Beat(time=.125, w1=[90,30,30,20], w2=[30,90,50,40], w3=[0,30,30,40], poly=1).play(dur=dur2, delay=start2) out = TrigEnv(b, tabs, b['dur'], mul=b['amp']*fade2).out(dur=dur2, delay=start2) start3 = 45 dur3 = 30 fade3 = Fader(15, 15, dur3, mul=.02).play(dur=dur3, delay=start3) fm = FM(carrier=[149,100,151,50]*3, ratio=[.2499,.501,.75003], index=10, mul=fade3).out(dur=dur3, delay=start3) s.gui(locals())pyo/examples/algorithmic/0000755000175000017500000000000012652732202014776 5ustar tiagotiagopyo/examples/algorithmic/01_music_box.py0000644000175000017500000000130112652732202017633 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Music box. 5 voices randomly choosing frequencies over a common scale. """ from pyo import * s = Server(duplex=0).boot() #--> set list of frequencies low_freqs = [midiToHz(m+7) for m in [36,43.01,48,55.01,60]] mid_freqs = [midiToHz(m+7) for m in [60,62,63.93,65,67.01,69,71,72]] high_freqs = [midiToHz(m+7) for m in [72,74,75.93,77,79.01]] freqs = [low_freqs,low_freqs,mid_freqs,mid_freqs,high_freqs] #<-- #--> chx = Choice(choice=freqs, freq=[1,2,3,3,4]) port = Port(chx, risetime=.001, falltime=.001) sines = SineLoop(port, feedback=[.06,.057,.033,.035,.016], mul=[.15,.15,.1,.1,.06]) pan = SPan(sines, pan=[0, 1, .2, .8, .5]).out() #<-- s.gui(locals())pyo/examples/algorithmic/02_scale_snap.py0000644000175000017500000000166712652732202017773 0ustar tiagotiago""" Algorithmic melody patterns snapped on a specific scale... """ from pyo import * s = Server(duplex=0).boot() scls = [[0,4,7,11,13,17,21,25,29,33], [0,7,12,14,17,21,24,29,31,34], [0,7,10,12,15,19,20]] env = CosTable([(0,0),(50,1),(500,.25),(8191,0)]) wav = SquareTable(5) met = Metro(time=.125, poly=8).play() note = TrigXnoiseMidi(met, dist="loopseg", x1=1, x2=.2, mrange=(48,97)) snp = Snap(note, choice=scls[0], scale=1) curscl = 0 def changeScl(): # change the scale for snp.choice argument global curscl curscl = (curscl + 1) % len(scls) snp.choice = scls[curscl] print snp.choice metscl = Metro(time=8).play() tr = TrigFunc(metscl, function=changeScl) c = TrigEnv(met, table=env, mul=.07) d = Osc(table=wav, freq=snp, mul=c).out() d1 = Osc(table=wav, freq=snp*0.999, mul=c).out() d2 = Osc(table=wav, freq=snp*1.002, mul=c).out() d3 = Osc(table=wav, freq=snp*0.997, mul=c).out() s.gui(locals()) pyo/examples/algorithmic/04_drum_machine.py0000644000175000017500000000354312652732202020313 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ Algoritmic rhythm machine... """ from pyo import * # Set this constant to True to loop over preset bank WITH_PRESET = False snds3 = ['../snds/alum1.wav', '../snds/alum2.wav', '../snds/alum3.wav', '../snds/alum4.wav'] presets = [[[16, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0], [16, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0], [16, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0]], [[16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1], [16, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0], [16, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0]], [[16, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1], [16, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0], [16, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0]], [[16, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1], [16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0], [16, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1]]] s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot() tm = Xnoise(dist=9, freq=2.34, x1=.5, x2=3, mul=.0025, add=.12) b = Beat(time=tm, w1=[90,30,30,20], w2=[30,90,50,40], w3=[0,30,30,40]) if WITH_PRESET: b.setPresets(presets) b.recall(0) b.play() tabs = SndTable(snds3) out = TrigEnv(b, table=tabs, dur=b['dur']*2, interp=4, mul=b['amp']*0.5) pan = SPan(out, pan=[.25, .4, .6, .75]).mix(2) rev = WGVerb(pan, feedback=.65, cutoff=3500, bal=.2).out() def change(): b.fill() b.new() def chAndCall(x): b.fill() b.recall(x) x = 0 pre = 0 def ch(): global x, pre x += 1 if (x % 5) == 0: if WITH_PRESET: pre = (pre + 1) % 3 chAndCall(pre) else: change() tt = TrigFunc(b['end'][0], function=ch) s.gui(locals()) pyo/examples/algorithmic/03_melody_algo.py0000644000175000017500000000405012652732202020144 0ustar tiagotiago#!/usr/bin/env python # encoding: utf-8 """ The Melo class records 16 notes in a table and reads it at variable speed. """ from pyo import * import random s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot() SCALES = [[0,2,5,7,9,11], [0,2,3,7,8,11], [0,3,5,7,8,10]] class Melo: def __init__(self, amp=.1, speed=1, midirange=(48,84)): # table to record new melody fragment self.table = NewTable(2) # loopseg generation self.base_mel = XnoiseMidi(dist=12, freq=8, x1=1, x2=.25, scale=0, mrange=midirange) # snap on scale and convert to hertz self.base_melo = Snap(self.base_mel, choice=[0,2,4,5,7,9,11], scale=1) # record a new fragment every 10 seconds self.trig_rec = Metro(time=10).play() self.tab_rec = TrigTableRec(self.base_melo, self.trig_rec, self.table) # rise amp of the oscillators after the first recording self.amp = Counter(self.tab_rec["trig"], min=1, max=2, mul=amp) # random speed for the oscillator reading the melody table + portamento self.speed = Choice(choice=[.0625,.125,.125,.125,.25,.5], freq=1.0*speed) self.freq = Osc(self.table, self.speed*speed) self.freq_port = Port(self.freq, risetime=.01, falltime=.01) # 8 randis (freq and amp) to create a chorus of oscillators self.rnd_chorus = Randi(min=.99, max=1.01, freq=[random.uniform(3,6) for i in range(8)]) self.rnd_amp = Randi(min=0, max=.15, freq=[random.uniform(.2,.5) for i in range(8)]) # oscillators... self.osc = LFO(self.freq_port*self.rnd_chorus, type=3, sharp=.75, mul=Port(self.amp, mul=self.rnd_amp)).out() def setScale(self, scl): self.base_melo.choice = scl def choose_scale(): scl = random.choice(SCALES) for obj in objs: obj.setScale(scl) a = Melo(amp=.3, speed=1, midirange=(60,84)) b = Melo(amp=.6, speed=0.5, midirange=(48,72)) c = Melo(amp=1, speed=0.25, midirange=(36,60)) objs = [a,b,c] pat = Pattern(time=20, function=choose_scale).play() s.gui(locals())