diff options
-rw-r--r-- | AUTHORS | 7 | ||||
-rw-r--r-- | COPYING | 699 | ||||
-rw-r--r-- | INSTALL | 59 | ||||
-rw-r--r-- | NEWS | 14 | ||||
-rw-r--r-- | README | 13 | ||||
-rw-r--r-- | blop.lv2/adsr.ttl | 82 | ||||
-rw-r--r-- | blop.lv2/adsr_gt.ttl | 91 | ||||
-rw-r--r-- | blop.lv2/amp.ttl | 49 | ||||
-rw-r--r-- | blop.lv2/branch.ttl | 54 | ||||
-rw-r--r-- | blop.lv2/dahdsr.ttl | 128 | ||||
-rw-r--r-- | blop.lv2/difference.ttl | 51 | ||||
-rw-r--r-- | blop.lv2/fmod.ttl | 60 | ||||
-rw-r--r-- | blop.lv2/interpolator.ttl | 32 | ||||
-rw-r--r-- | blop.lv2/lp4pole.ttl | 64 | ||||
-rw-r--r-- | blop.lv2/manifest.ttl.in | 155 | ||||
-rw-r--r-- | blop.lv2/product.ttl | 50 | ||||
-rw-r--r-- | blop.lv2/pulse.ttl | 60 | ||||
-rw-r--r-- | blop.lv2/quantiser_100.ttl | 719 | ||||
-rw-r--r-- | blop.lv2/quantiser_20.ttl | 239 | ||||
-rw-r--r-- | blop.lv2/quantiser_50.ttl | 419 | ||||
-rw-r--r-- | blop.lv2/random.ttl | 64 | ||||
-rw-r--r-- | blop.lv2/ratio.ttl | 52 | ||||
-rw-r--r-- | blop.lv2/sawtooth.ttl | 46 | ||||
-rw-r--r-- | blop.lv2/sequencer_16.ttl | 167 | ||||
-rw-r--r-- | blop.lv2/sequencer_32.ttl | 263 | ||||
-rw-r--r-- | blop.lv2/sequencer_64.ttl | 455 | ||||
-rw-r--r-- | blop.lv2/square.ttl | 46 | ||||
-rw-r--r-- | blop.lv2/sum.ttl | 50 | ||||
-rw-r--r-- | blop.lv2/sync_pulse.ttl | 63 | ||||
-rw-r--r-- | blop.lv2/sync_square.ttl | 55 | ||||
-rw-r--r-- | blop.lv2/tracker.ttl | 122 | ||||
-rw-r--r-- | blop.lv2/triangle.ttl | 61 | ||||
-rw-r--r-- | src/adsr.c | 259 | ||||
-rw-r--r-- | src/adsr_gt.c | 266 | ||||
-rw-r--r-- | src/amp.c | 166 | ||||
-rw-r--r-- | src/branch.c | 223 | ||||
-rw-r--r-- | src/dahdsr.c | 416 | ||||
-rw-r--r-- | src/difference.c | 188 | ||||
-rw-r--r-- | src/fmod.c | 199 | ||||
-rw-r--r-- | src/include/common.h | 54 | ||||
-rw-r--r-- | src/include/interpolate.h | 74 | ||||
-rw-r--r-- | src/include/lp4pole_filter.h | 137 | ||||
-rw-r--r-- | src/include/math_func.h | 48 | ||||
-rw-r--r-- | src/include/uris.h | 59 | ||||
-rw-r--r-- | src/include/vector_op.h | 44 | ||||
-rw-r--r-- | src/include/wavedata.h | 193 | ||||
-rw-r--r-- | src/include/wdatutil.h | 141 | ||||
-rw-r--r-- | src/interpolator.c | 144 | ||||
-rw-r--r-- | src/lp4pole.c | 206 | ||||
-rw-r--r-- | src/lp4pole_filter.c | 55 | ||||
-rw-r--r-- | src/product.c | 187 | ||||
-rw-r--r-- | src/pulse.c | 225 | ||||
-rw-r--r-- | src/quantiser.c | 461 | ||||
-rw-r--r-- | src/random.c | 237 | ||||
-rw-r--r-- | src/ratio.c | 202 | ||||
-rw-r--r-- | src/sawtooth.c | 194 | ||||
-rw-r--r-- | src/sequencer.c | 216 | ||||
-rw-r--r-- | src/square.c | 195 | ||||
-rw-r--r-- | src/sum.c | 185 | ||||
-rw-r--r-- | src/sync_pulse.c | 213 | ||||
-rw-r--r-- | src/sync_square.c | 201 | ||||
-rw-r--r-- | src/tracker.c | 245 | ||||
-rw-r--r-- | src/triangle.c | 232 | ||||
-rw-r--r-- | src/wavedata.c | 79 | ||||
-rw-r--r-- | src/wavegen.c | 310 | ||||
-rw-r--r-- | src/wdatutil.c | 679 | ||||
-rwxr-xr-x | waf | 171 | ||||
-rw-r--r-- | waflib/.gitignore (renamed from .gitignore) | 0 | ||||
-rw-r--r-- | waflib/Build.py (renamed from Build.py) | 0 | ||||
-rw-r--r-- | waflib/COPYING | 25 | ||||
-rw-r--r-- | waflib/ConfigSet.py (renamed from ConfigSet.py) | 0 | ||||
-rw-r--r-- | waflib/Configure.py (renamed from Configure.py) | 0 | ||||
-rw-r--r-- | waflib/Context.py (renamed from Context.py) | 0 | ||||
-rw-r--r-- | waflib/Errors.py (renamed from Errors.py) | 0 | ||||
-rw-r--r-- | waflib/Logs.py (renamed from Logs.py) | 0 | ||||
-rw-r--r-- | waflib/Node.py (renamed from Node.py) | 0 | ||||
-rw-r--r-- | waflib/Options.py (renamed from Options.py) | 0 | ||||
-rw-r--r-- | waflib/README.md (renamed from README.md) | 0 | ||||
-rw-r--r-- | waflib/Runner.py (renamed from Runner.py) | 0 | ||||
-rw-r--r-- | waflib/Scripting.py (renamed from Scripting.py) | 0 | ||||
-rw-r--r-- | waflib/Task.py (renamed from Task.py) | 0 | ||||
-rw-r--r-- | waflib/TaskGen.py (renamed from TaskGen.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/__init__.py (renamed from Tools/__init__.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/ar.py (renamed from Tools/ar.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/asm.py (renamed from Tools/asm.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/bison.py (renamed from Tools/bison.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/c.py (renamed from Tools/c.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/c_aliases.py (renamed from Tools/c_aliases.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/c_config.py (renamed from Tools/c_config.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/c_osx.py (renamed from Tools/c_osx.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/c_preproc.py (renamed from Tools/c_preproc.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/c_tests.py (renamed from Tools/c_tests.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/ccroot.py (renamed from Tools/ccroot.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/clang.py (renamed from Tools/clang.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/clangxx.py (renamed from Tools/clangxx.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/compiler_c.py (renamed from Tools/compiler_c.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/compiler_cxx.py (renamed from Tools/compiler_cxx.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/compiler_d.py (renamed from Tools/compiler_d.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/compiler_fc.py (renamed from Tools/compiler_fc.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/cs.py (renamed from Tools/cs.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/cxx.py (renamed from Tools/cxx.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/d.py (renamed from Tools/d.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/d_config.py (renamed from Tools/d_config.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/d_scan.py (renamed from Tools/d_scan.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/dbus.py (renamed from Tools/dbus.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/dmd.py (renamed from Tools/dmd.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/errcheck.py (renamed from Tools/errcheck.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/fc.py (renamed from Tools/fc.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/fc_config.py (renamed from Tools/fc_config.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/fc_scan.py (renamed from Tools/fc_scan.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/flex.py (renamed from Tools/flex.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/g95.py (renamed from Tools/g95.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/gas.py (renamed from Tools/gas.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/gcc.py (renamed from Tools/gcc.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/gdc.py (renamed from Tools/gdc.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/gfortran.py (renamed from Tools/gfortran.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/glib2.py (renamed from Tools/glib2.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/gnu_dirs.py (renamed from Tools/gnu_dirs.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/gxx.py (renamed from Tools/gxx.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/icc.py (renamed from Tools/icc.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/icpc.py (renamed from Tools/icpc.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/ifort.py (renamed from Tools/ifort.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/intltool.py (renamed from Tools/intltool.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/irixcc.py (renamed from Tools/irixcc.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/javaw.py (renamed from Tools/javaw.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/ldc2.py (renamed from Tools/ldc2.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/lua.py (renamed from Tools/lua.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/md5_tstamp.py (renamed from Tools/md5_tstamp.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/msvc.py (renamed from Tools/msvc.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/nasm.py (renamed from Tools/nasm.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/nobuild.py (renamed from Tools/nobuild.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/perl.py (renamed from Tools/perl.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/python.py (renamed from Tools/python.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/qt5.py (renamed from Tools/qt5.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/ruby.py (renamed from Tools/ruby.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/suncc.py (renamed from Tools/suncc.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/suncxx.py (renamed from Tools/suncxx.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/tex.py (renamed from Tools/tex.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/vala.py (renamed from Tools/vala.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/waf_unit_test.py (renamed from Tools/waf_unit_test.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/winres.py (renamed from Tools/winres.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/xlc.py (renamed from Tools/xlc.py) | 0 | ||||
-rw-r--r-- | waflib/Tools/xlcxx.py (renamed from Tools/xlcxx.py) | 0 | ||||
-rw-r--r-- | waflib/Utils.py (renamed from Utils.py) | 0 | ||||
-rw-r--r-- | waflib/__init__.py (renamed from __init__.py) | 0 | ||||
-rw-r--r-- | waflib/ansiterm.py (renamed from ansiterm.py) | 0 | ||||
-rw-r--r-- | waflib/extras/__init__.py (renamed from extras/__init__.py) | 0 | ||||
-rw-r--r-- | waflib/extras/autowaf.py (renamed from extras/autowaf.py) | 0 | ||||
-rw-r--r-- | waflib/extras/batched_cc.py (renamed from extras/batched_cc.py) | 0 | ||||
-rw-r--r-- | waflib/extras/biber.py (renamed from extras/biber.py) | 0 | ||||
-rw-r--r-- | waflib/extras/bjam.py (renamed from extras/bjam.py) | 0 | ||||
-rw-r--r-- | waflib/extras/blender.py (renamed from extras/blender.py) | 0 | ||||
-rw-r--r-- | waflib/extras/boo.py (renamed from extras/boo.py) | 0 | ||||
-rw-r--r-- | waflib/extras/boost.py (renamed from extras/boost.py) | 0 | ||||
-rw-r--r-- | waflib/extras/build_file_tracker.py (renamed from extras/build_file_tracker.py) | 0 | ||||
-rw-r--r-- | waflib/extras/build_logs.py (renamed from extras/build_logs.py) | 0 | ||||
-rw-r--r-- | waflib/extras/buildcopy.py (renamed from extras/buildcopy.py) | 0 | ||||
-rw-r--r-- | waflib/extras/c_bgxlc.py (renamed from extras/c_bgxlc.py) | 0 | ||||
-rw-r--r-- | waflib/extras/c_dumbpreproc.py (renamed from extras/c_dumbpreproc.py) | 0 | ||||
-rw-r--r-- | waflib/extras/c_emscripten.py (renamed from extras/c_emscripten.py) | 0 | ||||
-rw-r--r-- | waflib/extras/c_nec.py (renamed from extras/c_nec.py) | 0 | ||||
-rw-r--r-- | waflib/extras/cabal.py (renamed from extras/cabal.py) | 0 | ||||
-rw-r--r-- | waflib/extras/cfg_altoptions.py (renamed from extras/cfg_altoptions.py) | 0 | ||||
-rw-r--r-- | waflib/extras/clang_compilation_database.py (renamed from extras/clang_compilation_database.py) | 0 | ||||
-rw-r--r-- | waflib/extras/codelite.py (renamed from extras/codelite.py) | 0 | ||||
-rw-r--r-- | waflib/extras/color_gcc.py (renamed from extras/color_gcc.py) | 0 | ||||
-rw-r--r-- | waflib/extras/color_rvct.py (renamed from extras/color_rvct.py) | 0 | ||||
-rw-r--r-- | waflib/extras/compat15.py (renamed from extras/compat15.py) | 0 | ||||
-rw-r--r-- | waflib/extras/cppcheck.py (renamed from extras/cppcheck.py) | 0 | ||||
-rw-r--r-- | waflib/extras/cpplint.py (renamed from extras/cpplint.py) | 0 | ||||
-rw-r--r-- | waflib/extras/cross_gnu.py (renamed from extras/cross_gnu.py) | 0 | ||||
-rw-r--r-- | waflib/extras/cython.py (renamed from extras/cython.py) | 0 | ||||
-rw-r--r-- | waflib/extras/dcc.py (renamed from extras/dcc.py) | 0 | ||||
-rw-r--r-- | waflib/extras/distnet.py (renamed from extras/distnet.py) | 0 | ||||
-rw-r--r-- | waflib/extras/doxygen.py (renamed from extras/doxygen.py) | 0 | ||||
-rw-r--r-- | waflib/extras/dpapi.py (renamed from extras/dpapi.py) | 0 | ||||
-rw-r--r-- | waflib/extras/eclipse.py (renamed from extras/eclipse.py) | 0 | ||||
-rw-r--r-- | waflib/extras/erlang.py (renamed from extras/erlang.py) | 0 | ||||
-rw-r--r-- | waflib/extras/fast_partial.py (renamed from extras/fast_partial.py) | 0 | ||||
-rw-r--r-- | waflib/extras/fc_bgxlf.py (renamed from extras/fc_bgxlf.py) | 0 | ||||
-rw-r--r-- | waflib/extras/fc_cray.py (renamed from extras/fc_cray.py) | 0 | ||||
-rw-r--r-- | waflib/extras/fc_nag.py (renamed from extras/fc_nag.py) | 0 | ||||
-rw-r--r-- | waflib/extras/fc_nec.py (renamed from extras/fc_nec.py) | 0 | ||||
-rw-r--r-- | waflib/extras/fc_open64.py (renamed from extras/fc_open64.py) | 0 | ||||
-rw-r--r-- | waflib/extras/fc_pgfortran.py (renamed from extras/fc_pgfortran.py) | 0 | ||||
-rw-r--r-- | waflib/extras/fc_solstudio.py (renamed from extras/fc_solstudio.py) | 0 | ||||
-rw-r--r-- | waflib/extras/fc_xlf.py (renamed from extras/fc_xlf.py) | 0 | ||||
-rw-r--r-- | waflib/extras/file_to_object.py (renamed from extras/file_to_object.py) | 0 | ||||
-rw-r--r-- | waflib/extras/fluid.py (renamed from extras/fluid.py) | 0 | ||||
-rw-r--r-- | waflib/extras/freeimage.py (renamed from extras/freeimage.py) | 0 | ||||
-rw-r--r-- | waflib/extras/fsb.py (renamed from extras/fsb.py) | 0 | ||||
-rw-r--r-- | waflib/extras/fsc.py (renamed from extras/fsc.py) | 0 | ||||
-rw-r--r-- | waflib/extras/gccdeps.py (renamed from extras/gccdeps.py) | 0 | ||||
-rw-r--r-- | waflib/extras/gdbus.py (renamed from extras/gdbus.py) | 0 | ||||
-rw-r--r-- | waflib/extras/gob2.py (renamed from extras/gob2.py) | 0 | ||||
-rw-r--r-- | waflib/extras/halide.py (renamed from extras/halide.py) | 0 | ||||
-rwxr-xr-x | waflib/extras/javatest.py (renamed from extras/javatest.py) | 0 | ||||
-rw-r--r-- | waflib/extras/kde4.py (renamed from extras/kde4.py) | 0 | ||||
-rw-r--r-- | waflib/extras/local_rpath.py (renamed from extras/local_rpath.py) | 0 | ||||
-rw-r--r-- | waflib/extras/lv2.py (renamed from extras/lv2.py) | 0 | ||||
-rw-r--r-- | waflib/extras/make.py (renamed from extras/make.py) | 0 | ||||
-rw-r--r-- | waflib/extras/midl.py (renamed from extras/midl.py) | 0 | ||||
-rw-r--r-- | waflib/extras/msvcdeps.py (renamed from extras/msvcdeps.py) | 0 | ||||
-rw-r--r-- | waflib/extras/msvs.py (renamed from extras/msvs.py) | 0 | ||||
-rw-r--r-- | waflib/extras/netcache_client.py (renamed from extras/netcache_client.py) | 0 | ||||
-rw-r--r-- | waflib/extras/objcopy.py (renamed from extras/objcopy.py) | 0 | ||||
-rw-r--r-- | waflib/extras/ocaml.py (renamed from extras/ocaml.py) | 0 | ||||
-rw-r--r-- | waflib/extras/package.py (renamed from extras/package.py) | 0 | ||||
-rw-r--r-- | waflib/extras/parallel_debug.py (renamed from extras/parallel_debug.py) | 0 | ||||
-rw-r--r-- | waflib/extras/pch.py (renamed from extras/pch.py) | 0 | ||||
-rw-r--r-- | waflib/extras/pep8.py (renamed from extras/pep8.py) | 0 | ||||
-rw-r--r-- | waflib/extras/pgicc.py (renamed from extras/pgicc.py) | 0 | ||||
-rw-r--r-- | waflib/extras/pgicxx.py (renamed from extras/pgicxx.py) | 0 | ||||
-rw-r--r-- | waflib/extras/proc.py (renamed from extras/proc.py) | 0 | ||||
-rw-r--r-- | waflib/extras/protoc.py (renamed from extras/protoc.py) | 0 | ||||
-rw-r--r-- | waflib/extras/pyqt5.py (renamed from extras/pyqt5.py) | 0 | ||||
-rw-r--r-- | waflib/extras/pytest.py (renamed from extras/pytest.py) | 0 | ||||
-rw-r--r-- | waflib/extras/qnxnto.py (renamed from extras/qnxnto.py) | 0 | ||||
-rw-r--r-- | waflib/extras/qt4.py (renamed from extras/qt4.py) | 0 | ||||
-rw-r--r-- | waflib/extras/relocation.py (renamed from extras/relocation.py) | 0 | ||||
-rw-r--r-- | waflib/extras/remote.py (renamed from extras/remote.py) | 0 | ||||
-rw-r--r-- | waflib/extras/resx.py (renamed from extras/resx.py) | 0 | ||||
-rw-r--r-- | waflib/extras/review.py (renamed from extras/review.py) | 0 | ||||
-rw-r--r-- | waflib/extras/rst.py (renamed from extras/rst.py) | 0 | ||||
-rw-r--r-- | waflib/extras/run_do_script.py (renamed from extras/run_do_script.py) | 0 | ||||
-rw-r--r-- | waflib/extras/run_m_script.py (renamed from extras/run_m_script.py) | 0 | ||||
-rw-r--r-- | waflib/extras/run_py_script.py (renamed from extras/run_py_script.py) | 0 | ||||
-rw-r--r-- | waflib/extras/run_r_script.py (renamed from extras/run_r_script.py) | 0 | ||||
-rw-r--r-- | waflib/extras/sas.py (renamed from extras/sas.py) | 0 | ||||
-rw-r--r-- | waflib/extras/satellite_assembly.py (renamed from extras/satellite_assembly.py) | 0 | ||||
-rw-r--r-- | waflib/extras/scala.py (renamed from extras/scala.py) | 0 | ||||
-rw-r--r-- | waflib/extras/slow_qt4.py (renamed from extras/slow_qt4.py) | 0 | ||||
-rw-r--r-- | waflib/extras/softlink_libs.py (renamed from extras/softlink_libs.py) | 0 | ||||
-rw-r--r-- | waflib/extras/stale.py (renamed from extras/stale.py) | 0 | ||||
-rw-r--r-- | waflib/extras/stracedeps.py (renamed from extras/stracedeps.py) | 0 | ||||
-rw-r--r-- | waflib/extras/swig.py (renamed from extras/swig.py) | 0 | ||||
-rw-r--r-- | waflib/extras/syms.py (renamed from extras/syms.py) | 0 | ||||
-rw-r--r-- | waflib/extras/ticgt.py (renamed from extras/ticgt.py) | 0 | ||||
-rw-r--r-- | waflib/extras/unity.py (renamed from extras/unity.py) | 0 | ||||
-rw-r--r-- | waflib/extras/use_config.py (renamed from extras/use_config.py) | 0 | ||||
-rw-r--r-- | waflib/extras/valadoc.py (renamed from extras/valadoc.py) | 0 | ||||
-rw-r--r-- | waflib/extras/waf_xattr.py (renamed from extras/waf_xattr.py) | 0 | ||||
-rw-r--r-- | waflib/extras/why.py (renamed from extras/why.py) | 0 | ||||
-rw-r--r-- | waflib/extras/win32_opts.py (renamed from extras/win32_opts.py) | 0 | ||||
-rw-r--r-- | waflib/extras/wix.py (renamed from extras/wix.py) | 0 | ||||
-rw-r--r-- | waflib/extras/xcode6.py (renamed from extras/xcode6.py) | 0 | ||||
-rw-r--r-- | waflib/fixpy2.py (renamed from fixpy2.py) | 0 | ||||
-rwxr-xr-x | waflib/processor.py (renamed from processor.py) | 0 | ||||
-rwxr-xr-x | waflib/waf | 16 | ||||
-rw-r--r-- | wscript | 193 |
250 files changed, 11793 insertions, 34 deletions
@@ -0,0 +1,7 @@ +The original LADSPA plugins on which this port is based are by: + + Mike Rawes <mike_rawes@yahoo.co.uk> + +This LV2 port was done by: + + David Robillard <d@drobilla.net> @@ -1,25 +1,674 @@ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 <http://www.gnu.org/licenses/>. + +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: + + <program> Copyright (C) <year> <name of author> + 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 +<http://www.gnu.org/licenses/>. + + 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 +<http://www.gnu.org/philosophy/why-not-lgpl.html>. @@ -0,0 +1,59 @@ +Installation Instructions +========================= + +Basic Installation +------------------ + +Building this software requires only Python. To install with default options: + + ./waf configure + ./waf + ./waf install + +You may need to become root for the install stage, for example: + + sudo ./waf install + +Configuration Options +--------------------- + +All supported options can be viewed using the command: + + ./waf --help + +Most options only need to be passed during the configure stage, for example: + + ./waf configure --prefix=/usr + ./waf + ./waf install + +Compiler Configuration +---------------------- + +Several standard environment variables can be used to control how compilers are +invoked: + + * CC: Path to C compiler + * CFLAGS: C compiler options + * CXX: Path to C++ compiler + * CXXFLAGS: C++ compiler options + * CPPFLAGS: C preprocessor options + * LINKFLAGS: Linker options + +Installation Directories +------------------------ + +The --prefix option (or the PREFIX environment variable) can be used to change +the prefix which all files are installed under. There are also several options +allowing for more fine-tuned control, see the --help output for details. + +Packaging +--------- + +Everything can be installed to a specific root directory by passing a --destdir +option to the install stage (or setting the DESTDIR environment variable), +which adds a prefix to all install paths. For example: + + ./waf configure --prefix=/usr + ./waf + ./waf install --destdir=/tmp/package @@ -0,0 +1,14 @@ +blop-lv2 (1.0.1) unstable; + + * Add missing properties for options interface + * Fix compilation with default hidden visibility + * Set Hz unit on frequency ports + * Avoid pedantic warnings + + -- David Robillard <d@drobilla.net> Sun, 12 Feb 2017 18:07:57 +0100 + +blop-lv2 (1.0.0) stable; + + * Initial release + + -- David Robillard <d@drobilla.net> Sun, 05 Jan 2014 12:00:00 -0500 @@ -0,0 +1,13 @@ +BLOP.LV2 +======== + +This is a port of the BLOP LADSPA plugins by Mike Rawes to LV2. + +This is a mostly faithful port of blop-0.2.8, except plugin variants have been +eliminated via the use of morphable Control/CV ports. This way, users do not +have to choose from several versions of the same plugin, but the host can +configure controls to be control-rate or audio-rate as appropriate. This +mechanism is backwards compatible, so these ports will simply appear as normal +LV2 control ports in hosts that do not support port morphing. + + -- David Robillard <d@drobilla.net> diff --git a/blop.lv2/adsr.ttl b/blop.lv2/adsr.ttl new file mode 100644 index 0000000..290a745 --- /dev/null +++ b/blop.lv2/adsr.ttl @@ -0,0 +1,82 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix units: <http://lv2plug.in/ns/extensions/units#> . + +blop:adsr + a lv2:Plugin , + lv2:EnvelopePlugin ; + lv2:project blop: ; + lv2:symbol "adsr" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:optionalFeature lv2:hardRTCapable ; + lv2:port [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 0 ; + lv2:name "Driving Signal" ; + lv2:symbol "drive" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 1 ; + lv2:name "Trigger Threshold" ; + lv2:symbol "thresh" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 2 ; + lv2:minimum 0 ; + lv2:name "Attack Time" ; + lv2:symbol "attack" ; + units:unit units:s + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 3 ; + lv2:minimum 0 ; + lv2:name "Decay Time" ; + lv2:symbol "decay" ; + units:unit units:s + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 1 ; + lv2:index 4 ; + lv2:maximum 1 ; + lv2:minimum 0 ; + lv2:name "Sustain Level" ; + lv2:symbol "sustain" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 5 ; + lv2:minimum 0 ; + lv2:name "Release Time" ; + lv2:symbol "release" ; + units:unit units:s + ] , [ + a lv2:CVPort , + lv2:OutputPort ; + lv2:index 6 ; + lv2:name "Envelope Out" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1653> ; + doap:name "ADSR Envelope" ; + lv2:documentation """ +<p>Generates an ADSR (Attack, Decay, Sustain and Release) envelope.</p> + +<p>Driven by a gate signal - if the level of the signal goes higher than the +Trigger Threshold, the attack stage begins, proceeds to the decay stage and +then holds at the sustain level. The release stage begins when the gate falls +below this theshold - even if the previous stages have not completed.</p> + +<p>The output is a signal between 0.0 (rest) and 1.0 (peak) and the transitions +are linear.</p> +""" . diff --git a/blop.lv2/adsr_gt.ttl b/blop.lv2/adsr_gt.ttl new file mode 100644 index 0000000..719330e --- /dev/null +++ b/blop.lv2/adsr_gt.ttl @@ -0,0 +1,91 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix units: <http://lv2plug.in/ns/extensions/units#> . + +blop:adsr_gt + a lv2:Plugin , + lv2:EnvelopePlugin ; + lv2:project blop: ; + lv2:symbol "adsr_gt" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:optionalFeature lv2:hardRTCapable ; + lv2:port [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 0 ; + lv2:name "Gate" ; + lv2:portProperty lv2:toggled ; + lv2:symbol "gate" + ] , [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 1 ; + lv2:name "Trigger" ; + lv2:portProperty lv2:toggled , + <http://lv2plug.in/ns/ext/port-props#trigger> ; + lv2:symbol "trigger" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 2 ; + lv2:minimum 0 ; + lv2:name "Attack Time" ; + lv2:symbol "attack" ; + units:unit units:s + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 3 ; + lv2:minimum 0 ; + lv2:name "Decay Time" ; + lv2:symbol "decay" ; + units:unit units:s + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 1 ; + lv2:index 4 ; + lv2:maximum 1 ; + lv2:minimum 0 ; + lv2:name "Sustain Level" ; + lv2:symbol "sustain" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 5 ; + lv2:minimum 0 ; + lv2:name "Release Time" ; + lv2:symbol "release" ; + units:unit units:s + ] , [ + a lv2:CVPort , + lv2:OutputPort ; + lv2:index 6 ; + lv2:name "Envelope Out" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1680> ; + doap:name "Retriggerable ADSR Envelope" ; + lv2:documentation """ +<p>Generates an ADSR (Attack, Decay, Sustain and Release) +envelope.</p> + +<p>Does the same thing as the other ADSR (1658) above, except the +Trigger Threshold is fixed at zero, and the additional Trigger +input allows retriggering whilst the gate is still high.</p> + +<p>The reasoning behind this design is to remove the need for a keyboard player +to release a key before pressing another when using with a monosynth. <a +href="http://www.sospubs.co.uk/sos/nov99/articles/synthsecrets.htm">The +‘Synth Secrets’ article in the November 1999 issue of ‘Sound +on Sound’</a> explains this in detail.</p> + +<p>The output is a signal between 0.0 (rest) and 1.0 (peak) and the +transitions are linear.</p> +""" . diff --git a/blop.lv2/amp.ttl b/blop.lv2/amp.ttl new file mode 100644 index 0000000..8ba454d --- /dev/null +++ b/blop.lv2/amp.ttl @@ -0,0 +1,49 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix units: <http://lv2plug.in/ns/extensions/units#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:amp + a lv2:Plugin , + lv2:AmplifierPlugin ; + lv2:project blop: ; + lv2:symbol "amp" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 0 ; + lv2:maximum 96 ; + lv2:minimum -96 ; + lv2:name "Gain" ; + lv2:symbol "gain" ; + units:unit units:db ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:AudioPort , + lv2:InputPort ; + lv2:index 1 ; + lv2:name "Input" ; + lv2:symbol "in" + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 2 ; + lv2:name "Output" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1654> , + <urn:ladspa:1655> ; + doap:name "Amplifier" ; + lv2:documentation """ +<p>A simple monophonic amplifier.</p> +""" . diff --git a/blop.lv2/branch.ttl b/blop.lv2/branch.ttl new file mode 100644 index 0000000..f58b81d --- /dev/null +++ b/blop.lv2/branch.ttl @@ -0,0 +1,54 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:branch + a lv2:Plugin , + lv2:UtilityPlugin ; + lv2:project blop: ; + lv2:symbol "branch" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 0 ; + lv2:name "Input" ; + lv2:symbol "in" ; + morph:supportsType lv2:CVPort , + lv2:AudioPort + ] , [ + a lv2:ControlPort , + lv2:OutputPort , + morph:AutoMorphPort ; + lv2:index 1 ; + lv2:name "Output 1" ; + lv2:symbol "out1" ; + morph:supportsType lv2:CVPort , + lv2:AudioPort + ] , [ + a lv2:ControlPort , + lv2:OutputPort , + morph:AutoMorphPort ; + lv2:index 2 ; + lv2:name "Output 2" ; + lv2:symbol "out2" ; + morph:supportsType lv2:CVPort , + lv2:AudioPort + ] ; + dct:replaces <urn:ladspa:1673> , + <urn:ladspa:1674> ; + doap:name "Branch" ; + lv2:documentation """ +<p>Splits an input signal into two identical signals. Somewhat redundant, as +most modular synth hosts allow you to connect an output to more than one input. +If your host of choice does not allow this, this plugin will do the job...</p> +""" . diff --git a/blop.lv2/dahdsr.ttl b/blop.lv2/dahdsr.ttl new file mode 100644 index 0000000..68652aa --- /dev/null +++ b/blop.lv2/dahdsr.ttl @@ -0,0 +1,128 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . +@prefix units: <http://lv2plug.in/ns/extensions/units#> . + +blop:dahdsr + a lv2:Plugin , + lv2:EnvelopePlugin ; + lv2:project blop: ; + lv2:symbol "dahdsr" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 0 ; + lv2:name "Gate" ; + lv2:portProperty lv2:toggled ; + lv2:symbol "gate" + ] , [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 1 ; + lv2:name "Trigger" ; + lv2:portProperty lv2:toggled , + <http://lv2plug.in/ns/ext/port-props#trigger> ; + lv2:symbol "trigger" + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 0 ; + lv2:index 2 ; + lv2:minimum 0 ; + lv2:name "Delay Time" ; + lv2:symbol "delay" ; + morph:supportsType lv2:CVPort ; + units:unit units:s + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 0 ; + lv2:index 3 ; + lv2:minimum 0 ; + lv2:name "Attack Time" ; + lv2:symbol "attack" ; + morph:supportsType lv2:CVPort ; + units:unit units:s + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 0 ; + lv2:index 4 ; + lv2:minimum 0 ; + lv2:name "Hold Time" ; + lv2:symbol "hold" ; + morph:supportsType lv2:CVPort ; + units:unit units:s + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 0 ; + lv2:index 5 ; + lv2:minimum 0 ; + lv2:name "Decay Time" ; + lv2:symbol "decay" ; + morph:supportsType lv2:CVPort ; + units:unit units:s + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 1 ; + lv2:index 6 ; + lv2:maximum 1 ; + lv2:minimum 0 ; + lv2:name "Sustain Level" ; + lv2:symbol "sustain" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 0 ; + lv2:index 7 ; + lv2:minimum 0 ; + lv2:name "Release Time" ; + lv2:symbol "release" ; + morph:supportsType lv2:CVPort ; + units:unit units:s + ] , [ + a lv2:CVPort , + lv2:OutputPort ; + lv2:index 8 ; + lv2:name "Envelope Out" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:2021> , + <urn:ladspa:2022> , + <urn:ladspa:2038> ; + doap:name "Retriggerable DAHDSR Envelope" ; + lv2:documentation """ +<p>Generates a DAHDSR (Delay, Attack, Hold, Decay, Sustain, Release) +envelope.</p> + +<p>Another envelope generator, this time with two additional stages - Delay, +which delays the onset of the Attack stage, and Hold, which holds the output at +maximum before the Decay stage begins.</p> + +<p>Triggering works in subtly different ways to the <a href="#adsr_gnt">ADSR +(1680)</a> - the Trigger will restart the envelope even if the Gate is closed - +the effect of this is to proceed through the stages and begin the release stage +immediately after the decay stage.</p> + +<p>The final variant (ID 2038) uses control-rate gate and trigger, which is a +little less CPU hungry, but will cause timing errors that are dependent on the +block size being used by the host.</p> +""" . diff --git a/blop.lv2/difference.ttl b/blop.lv2/difference.ttl new file mode 100644 index 0000000..e55c6fe --- /dev/null +++ b/blop.lv2/difference.ttl @@ -0,0 +1,51 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:difference + a lv2:Plugin , + lv2:UtilityPlugin ; + lv2:project blop: ; + lv2:symbol "difference" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 0 ; + lv2:name "Minuend" ; + lv2:symbol "minuend" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 1 ; + lv2:name "Subtrahend" ; + lv2:symbol "subtrahend" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:ControlPort , + lv2:OutputPort , + morph:AutoMorphPort ; + lv2:index 2 ; + lv2:name "Difference" ; + lv2:symbol "difference" ; + morph:supportsType lv2:CVPort + ] ; + dct:replaces <urn:ladspa:2030> , + <urn:ladspa:2031> , + <urn:ladspa:2032> , + <urn:ladspa:2033> ; + doap:name "Difference" ; + lv2:documentation """ +<p>Subtract two signals.</p> +""" . diff --git a/blop.lv2/fmod.ttl b/blop.lv2/fmod.ttl new file mode 100644 index 0000000..38a552d --- /dev/null +++ b/blop.lv2/fmod.ttl @@ -0,0 +1,60 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix units: <http://lv2plug.in/ns/extensions/units#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:fmod + a lv2:Plugin , + lv2:SpectralPlugin ; + lv2:project blop: ; + lv2:symbol "fmod" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 0 ; + lv2:maximum 0.5 ; + lv2:minimum 0.00001 ; + lv2:name "Frequency" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> , + lv2:sampleRate ; + lv2:symbol "freq" ; + morph:supportsType lv2:CVPort ; + units:unit units:hz + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 1 ; + lv2:name "Modulation" ; + lv2:symbol "mod" ; + morph:supportsType lv2:CVPort ; + units:unit units:oct + ] , [ + a lv2:ControlPort , + lv2:OutputPort , + morph:AutoMorphPort ; + lv2:index 2 ; + lv2:name "Modulated Frequency" ; + lv2:symbol "out" ; + morph:supportsType lv2:CVPort ; + units:unit units:hz + ] ; + dct:replaces <urn:ladspa:1656> , + <urn:ladspa:1657> , + <urn:ladspa:1658> , + <urn:ladspa:1659> ; + doap:name "Frequency Modulator" ; + lv2:documentation """ +<p>Modulates an input frequency by a driving signal, transposing the frequency +by ±1 Octave per unit amplitude of signal.</p> +""" . diff --git a/blop.lv2/interpolator.ttl b/blop.lv2/interpolator.ttl new file mode 100644 index 0000000..38c93db --- /dev/null +++ b/blop.lv2/interpolator.ttl @@ -0,0 +1,32 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . + +blop:interpolator + a lv2:Plugin , + lv2:UtilityPlugin ; + lv2:project blop: ; + lv2:symbol "interpolator" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:optionalFeature lv2:hardRTCapable ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 0 ; + lv2:name "Control Input" ; + lv2:symbol "in" + ] , [ + a lv2:CVPort , + lv2:OutputPort ; + lv2:index 1 ; + lv2:name "Interpolated Output" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1660> ; + doap:name "Control to CV Interpolator" ; + lv2:documentation """ +<p>Interpolates a control-rate (per-block) signal into a smooth audio-rate +(per-sample) signal.</p> +""" . diff --git a/blop.lv2/lp4pole.ttl b/blop.lv2/lp4pole.ttl new file mode 100644 index 0000000..8fcf75c --- /dev/null +++ b/blop.lv2/lp4pole.ttl @@ -0,0 +1,64 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:lp4pole + a lv2:Plugin , + lv2:LowpassPlugin ; + lv2:project blop: ; + lv2:symbol "lp4pole" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 0.5 ; + lv2:index 0 ; + lv2:maximum 0.5 ; + lv2:minimum 0.00001 ; + lv2:name "Cutoff Frequency" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> , + lv2:sampleRate ; + lv2:symbol "cutoff" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 0 ; + lv2:index 1 ; + lv2:maximum 4 ; + lv2:minimum 0 ; + lv2:name "Resonance" ; + lv2:symbol "resonance" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:AudioPort , + lv2:InputPort ; + lv2:index 2 ; + lv2:name "Input" ; + lv2:symbol "in" + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 3 ; + lv2:name "Output" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1671> , + <urn:ladspa:1672> ; + doap:name "4 Pole Resonant Low-Pass" ; + lv2:documentation """ +<p>Emulates a low pass filter in popular analogue synthesisers. This particular +filter is derived from one of <a +href="http://www.musicdsp.org/archive.php?classid=3#24">many +implementations</a> of the Moog 4 pole filter.</p> +""" . diff --git a/blop.lv2/manifest.ttl.in b/blop.lv2/manifest.ttl.in new file mode 100644 index 0000000..4942342 --- /dev/null +++ b/blop.lv2/manifest.ttl.in @@ -0,0 +1,155 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix foaf: <http://xmlns.com/foaf/0.1/> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . + +<http://drobilla.net/drobilla#me> + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:mbox <mailto:d@drobilla.net> ; + rdfs:seeAlso <http://drobilla.net/drobilla> . + +blop: + a doap:Project ; + lv2:symbol "blop" ; + doap:name "Blop LV2" ; + doap:shortdesc "An LV2 port of the Blop plugins." ; + doap:homepage <http://drobilla.net/software/blop-lv2> ; + doap:license <http://opensource.org/licenses/gpl-3.0> ; + doap:maintainer <http://drobilla.net/drobilla#me> ; + doap:developer [ + a foaf:Person ; + foaf:name "Mike Rawes" ; + foaf:mbox <mike_rawes@yahoo.co.uk> + ] . + +blop:adsr + a lv2:Plugin ; + rdfs:seeAlso <adsr.ttl> ; + lv2:binary <adsr@LIB_EXT@> . + +blop:adsr_gt + a lv2:Plugin ; + rdfs:seeAlso <adsr_gt.ttl> ; + lv2:binary <adsr_gt@LIB_EXT@> . + +blop:amp + a lv2:Plugin ; + rdfs:seeAlso <amp.ttl> ; + lv2:binary <amp@LIB_EXT@> . + +blop:branch + a lv2:Plugin ; + rdfs:seeAlso <branch.ttl> ; + lv2:binary <branch@LIB_EXT@> . + +blop:dahdsr + a lv2:Plugin ; + rdfs:seeAlso <dahdsr.ttl> ; + lv2:binary <dahdsr@LIB_EXT@> . + +blop:difference + a lv2:Plugin ; + rdfs:seeAlso <difference.ttl> ; + lv2:binary <difference@LIB_EXT@> . + +blop:fmod + a lv2:Plugin ; + rdfs:seeAlso <fmod.ttl> ; + lv2:binary <fmod@LIB_EXT@> . + +blop:interpolator + a lv2:Plugin ; + rdfs:seeAlso <interpolator.ttl> ; + lv2:binary <interpolator@LIB_EXT@> . + +blop:lp4pole + a lv2:Plugin ; + rdfs:seeAlso <lp4pole.ttl> ; + lv2:binary <lp4pole@LIB_EXT@> . + +blop:product + a lv2:Plugin ; + rdfs:seeAlso <product.ttl> ; + lv2:binary <product@LIB_EXT@> . + +blop:pulse + a lv2:Plugin ; + rdfs:seeAlso <pulse.ttl> ; + lv2:binary <pulse@LIB_EXT@> . + +blop:quantiser_20 + a lv2:Plugin ; + rdfs:seeAlso <quantiser_20.ttl> ; + lv2:binary <quantiser_20@LIB_EXT@> . + +blop:quantiser_50 + a lv2:Plugin ; + rdfs:seeAlso <quantiser_50.ttl> ; + lv2:binary <quantiser_50@LIB_EXT@> . + +blop:quantiser_100 + a lv2:Plugin ; + rdfs:seeAlso <quantiser_100.ttl> ; + lv2:binary <quantiser_100@LIB_EXT@> . + +blop:random + a lv2:Plugin ; + rdfs:seeAlso <random.ttl> ; + lv2:binary <random@LIB_EXT@> . + +blop:ratio + a lv2:Plugin ; + rdfs:seeAlso <ratio.ttl> ; + lv2:binary <ratio@LIB_EXT@> . + +blop:sawtooth + a lv2:Plugin ; + rdfs:seeAlso <sawtooth.ttl> ; + lv2:binary <sawtooth@LIB_EXT@> . + +blop:sequencer_16 + a lv2:Plugin ; + rdfs:seeAlso <sequencer_16.ttl> ; + lv2:binary <sequencer_16@LIB_EXT@> . + +blop:sequencer_32 + a lv2:Plugin ; + rdfs:seeAlso <sequencer_32.ttl> ; + lv2:binary <sequencer_32@LIB_EXT@> . + +blop:sequencer_64 + a lv2:Plugin ; + rdfs:seeAlso <sequencer_64.ttl> ; + lv2:binary <sequencer_64@LIB_EXT@> . + +blop:square + a lv2:Plugin ; + rdfs:seeAlso <square.ttl> ; + lv2:binary <square@LIB_EXT@> . + +blop:sum + a lv2:Plugin ; + rdfs:seeAlso <sum.ttl> ; + lv2:binary <sum@LIB_EXT@> . + +blop:sync_pulse + a lv2:Plugin ; + rdfs:seeAlso <sync_pulse.ttl> ; + lv2:binary <sync_pulse@LIB_EXT@> . + +blop:sync_square + a lv2:Plugin ; + rdfs:seeAlso <sync_square.ttl> ; + lv2:binary <sync_square@LIB_EXT@> . + +blop:tracker + a lv2:Plugin ; + rdfs:seeAlso <tracker.ttl> ; + lv2:binary <tracker@LIB_EXT@> . + +blop:triangle + a lv2:Plugin ; + rdfs:seeAlso <triangle.ttl> ; + lv2:binary <triangle@LIB_EXT@> . diff --git a/blop.lv2/product.ttl b/blop.lv2/product.ttl new file mode 100644 index 0000000..d273f22 --- /dev/null +++ b/blop.lv2/product.ttl @@ -0,0 +1,50 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:product + a lv2:Plugin , + lv2:UtilityPlugin ; + lv2:project blop: ; + lv2:symbol "product" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 0 ; + lv2:name "Multiplicand" ; + lv2:symbol "multiplicand" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 1 ; + lv2:name "Multiplier" ; + lv2:symbol "multiplier" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:ControlPort , + lv2:OutputPort , + morph:AutoMorphPort ; + lv2:index 2 ; + lv2:name "Product" ; + lv2:symbol "product" ; + morph:supportsType lv2:CVPort + ] ; + dct:replaces <urn:ladspa:1668> , + <urn:ladspa:1669> , + <urn:ladspa:1670> ; + doap:name "Product" ; + lv2:documentation """ +<p>Multiply two signals.</p> +""" . diff --git a/blop.lv2/pulse.ttl b/blop.lv2/pulse.ttl new file mode 100644 index 0000000..5a940a9 --- /dev/null +++ b/blop.lv2/pulse.ttl @@ -0,0 +1,60 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix units: <http://lv2plug.in/ns/extensions/units#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:pulse + a lv2:Plugin , + lv2:OscillatorPlugin ; + lv2:project blop: ; + lv2:symbol "pulse" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 0 ; + lv2:maximum 0.5 ; + lv2:minimum 0.000001 ; + lv2:default 440.0 ; + lv2:name "Frequency" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> , + lv2:sampleRate ; + lv2:symbol "freq" ; + morph:supportsType lv2:CVPort ; + units:unit units:hz + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 0.5 ; + lv2:index 1 ; + lv2:maximum 1 ; + lv2:minimum 0 ; + lv2:name "Pulse Width" ; + lv2:symbol "pwidth" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 2 ; + lv2:name "Output" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1645> , + <urn:ladspa:1646> , + <urn:ladspa:1647> , + <urn:ladspa:1648> ; + doap:name "Pulse" ; + lv2:documentation """ +<p>Generates an alias-free pulse wave at given input frequency and pulse width +(duty).</p> +""" . diff --git a/blop.lv2/quantiser_100.ttl b/blop.lv2/quantiser_100.ttl new file mode 100644 index 0000000..c2873aa --- /dev/null +++ b/blop.lv2/quantiser_100.ttl @@ -0,0 +1,719 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . + +blop:quantiser_100 + a lv2:Plugin ; + lv2:project blop: ; + lv2:symbol "quantiser_100" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:optionalFeature lv2:hardRTCapable ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 0 ; + lv2:name "Minimum" ; + lv2:symbol "min" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 1 ; + lv2:name "Maximum" ; + lv2:symbol "max" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 2 ; + lv2:minimum 0 ; + lv2:name "Match Range" ; + lv2:symbol "range" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 3 ; + lv2:maximum 2 ; + lv2:minimum 0 ; + lv2:name "Mode" ; + lv2:symbol "mode" ; + lv2:portProperty lv2:enumeration , + lv2:integer ; + lv2:scalePoint [ + rdfs:label "Extend" ; + rdf:value 0.0 + ] , [ + rdfs:label "Wrap" ; + rdf:value 1.0 + ] , [ + rdfs:label "Clip" ; + rdf:value 1.0 + ] + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 20 ; + lv2:index 4 ; + lv2:maximum 20 ; + lv2:minimum 1 ; + lv2:name "Steps" ; + lv2:portProperty lv2:integer ; + lv2:symbol "steps" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 5 ; + lv2:name "Value 0" ; + lv2:symbol "val00" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 6 ; + lv2:name "Value 1" ; + lv2:symbol "val01" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 7 ; + lv2:name "Value 2" ; + lv2:symbol "val02" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 8 ; + lv2:name "Value 3" ; + lv2:symbol "val03" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 9 ; + lv2:name "Value 4" ; + lv2:symbol "val04" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 10 ; + lv2:name "Value 5" ; + lv2:symbol "val05" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 11 ; + lv2:name "Value 6" ; + lv2:symbol "val06" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 12 ; + lv2:name "Value 7" ; + lv2:symbol "val07" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 13 ; + lv2:name "Value 8" ; + lv2:symbol "val08" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 14 ; + lv2:name "Value 9" ; + lv2:symbol "val09" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 15 ; + lv2:name "Value 10" ; + lv2:symbol "val10" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 16 ; + lv2:name "Value 11" ; + lv2:symbol "val11" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 17 ; + lv2:name "Value 12" ; + lv2:symbol "val12" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 18 ; + lv2:name "Value 13" ; + lv2:symbol "val13" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 19 ; + lv2:name "Value 14" ; + lv2:symbol "val14" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 20 ; + lv2:name "Value 15" ; + lv2:symbol "val15" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 21 ; + lv2:name "Value 16" ; + lv2:symbol "val16" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 22 ; + lv2:name "Value 17" ; + lv2:symbol "val17" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 23 ; + lv2:name "Value 18" ; + lv2:symbol "val18" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 24 ; + lv2:name "Value 19" ; + lv2:symbol "val19" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 25 ; + lv2:name "Value 20" ; + lv2:symbol "val20" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 26 ; + lv2:name "Value 21" ; + lv2:symbol "val21" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 27 ; + lv2:name "Value 22" ; + lv2:symbol "val22" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 28 ; + lv2:name "Value 23" ; + lv2:symbol "val23" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 29 ; + lv2:name "Value 24" ; + lv2:symbol "val24" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 30 ; + lv2:name "Value 25" ; + lv2:symbol "val25" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 31 ; + lv2:name "Value 26" ; + lv2:symbol "val26" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 32 ; + lv2:name "Value 27" ; + lv2:symbol "val27" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 33 ; + lv2:name "Value 28" ; + lv2:symbol "val28" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 34 ; + lv2:name "Value 29" ; + lv2:symbol "val29" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 35 ; + lv2:name "Value 30" ; + lv2:symbol "val30" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 36 ; + lv2:name "Value 31" ; + lv2:symbol "val31" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 37 ; + lv2:name "Value 32" ; + lv2:symbol "val32" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 38 ; + lv2:name "Value 33" ; + lv2:symbol "val33" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 39 ; + lv2:name "Value 34" ; + lv2:symbol "val34" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 40 ; + lv2:name "Value 35" ; + lv2:symbol "val35" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 41 ; + lv2:name "Value 36" ; + lv2:symbol "val36" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 42 ; + lv2:name "Value 37" ; + lv2:symbol "val37" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 43 ; + lv2:name "Value 38" ; + lv2:symbol "val38" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 44 ; + lv2:name "Value 39" ; + lv2:symbol "val39" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 45 ; + lv2:name "Value 40" ; + lv2:symbol "val40" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 46 ; + lv2:name "Value 41" ; + lv2:symbol "val41" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 47 ; + lv2:name "Value 42" ; + lv2:symbol "val42" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 48 ; + lv2:name "Value 43" ; + lv2:symbol "val43" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 49 ; + lv2:name "Value 44" ; + lv2:symbol "val44" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 50 ; + lv2:name "Value 45" ; + lv2:symbol "val45" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 51 ; + lv2:name "Value 46" ; + lv2:symbol "val46" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 52 ; + lv2:name "Value 47" ; + lv2:symbol "val47" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 53 ; + lv2:name "Value 48" ; + lv2:symbol "val48" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 54 ; + lv2:name "Value 49" ; + lv2:symbol "val49" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 55 ; + lv2:name "Value 50" ; + lv2:symbol "val50" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 56 ; + lv2:name "Value 51" ; + lv2:symbol "val51" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 57 ; + lv2:name "Value 52" ; + lv2:symbol "val52" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 58 ; + lv2:name "Value 53" ; + lv2:symbol "val53" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 59 ; + lv2:name "Value 54" ; + lv2:symbol "val54" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 60 ; + lv2:name "Value 55" ; + lv2:symbol "val55" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 61 ; + lv2:name "Value 56" ; + lv2:symbol "val56" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 62 ; + lv2:name "Value 57" ; + lv2:symbol "val57" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 63 ; + lv2:name "Value 58" ; + lv2:symbol "val58" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 64 ; + lv2:name "Value 59" ; + lv2:symbol "val59" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 65 ; + lv2:name "Value 60" ; + lv2:symbol "val60" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 66 ; + lv2:name "Value 61" ; + lv2:symbol "val61" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 67 ; + lv2:name "Value 62" ; + lv2:symbol "val62" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 68 ; + lv2:name "Value 63" ; + lv2:symbol "val63" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 69 ; + lv2:name "Value 64" ; + lv2:symbol "val64" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 70 ; + lv2:name "Value 65" ; + lv2:symbol "val65" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 71 ; + lv2:name "Value 66" ; + lv2:symbol "val66" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 72 ; + lv2:name "Value 67" ; + lv2:symbol "val67" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 73 ; + lv2:name "Value 68" ; + lv2:symbol "val68" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 74 ; + lv2:name "Value 69" ; + lv2:symbol "val69" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 75 ; + lv2:name "Value 70" ; + lv2:symbol "val70" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 76 ; + lv2:name "Value 71" ; + lv2:symbol "val71" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 77 ; + lv2:name "Value 72" ; + lv2:symbol "val72" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 78 ; + lv2:name "Value 73" ; + lv2:symbol "val73" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 79 ; + lv2:name "Value 74" ; + lv2:symbol "val74" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 80 ; + lv2:name "Value 75" ; + lv2:symbol "val75" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 81 ; + lv2:name "Value 76" ; + lv2:symbol "val76" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 82 ; + lv2:name "Value 77" ; + lv2:symbol "val77" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 83 ; + lv2:name "Value 78" ; + lv2:symbol "val78" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 84 ; + lv2:name "Value 79" ; + lv2:symbol "val79" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 85 ; + lv2:name "Value 80" ; + lv2:symbol "val80" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 86 ; + lv2:name "Value 81" ; + lv2:symbol "val81" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 87 ; + lv2:name "Value 82" ; + lv2:symbol "val82" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 88 ; + lv2:name "Value 83" ; + lv2:symbol "val83" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 89 ; + lv2:name "Value 84" ; + lv2:symbol "val84" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 90 ; + lv2:name "Value 85" ; + lv2:symbol "val85" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 91 ; + lv2:name "Value 86" ; + lv2:symbol "val86" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 92 ; + lv2:name "Value 87" ; + lv2:symbol "val87" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 93 ; + lv2:name "Value 88" ; + lv2:symbol "val88" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 94 ; + lv2:name "Value 89" ; + lv2:symbol "val89" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 95 ; + lv2:name "Value 90" ; + lv2:symbol "val90" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 96 ; + lv2:name "Value 91" ; + lv2:symbol "val91" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 97 ; + lv2:name "Value 92" ; + lv2:symbol "val92" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 98 ; + lv2:name "Value 93" ; + lv2:symbol "val93" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 99 ; + lv2:name "Value 94" ; + lv2:symbol "val94" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 100 ; + lv2:name "Value 95" ; + lv2:symbol "val95" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 101 ; + lv2:name "Value 96" ; + lv2:symbol "val96" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 102 ; + lv2:name "Value 97" ; + lv2:symbol "val97" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 103 ; + lv2:name "Value 98" ; + lv2:symbol "val98" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 104 ; + lv2:name "Value 99" ; + lv2:symbol "val99" + ] , [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 105 ; + lv2:name "Input" ; + lv2:symbol "in" + ] , [ + a lv2:CVPort , + lv2:OutputPort ; + lv2:index 106 ; + lv2:name "Quantised Output" ; + lv2:symbol "out" + ] , [ + a lv2:CVPort , + lv2:OutputPort ; + lv2:index 107 ; + lv2:name "Output Changed" ; + lv2:symbol "changed" + ] ; + dct:replaces <urn:ladspa:2029> ; + doap:name "Quantiser (100 Steps)" ; + lv2:documentation """ +<p>Quantises a signal to a set of arbitrary values within a range.</p> + +<p>Match Range determines the distance from the quantised value that the input +can deviate before being altered. This allows small variations in input to get +through unmolested. If it is set to 0 the input is quantised to the nearest +exact match.</p> + +<p>Mode is one of Extend (0), Wrap (1) or Clip (2).</p> + +<p>Steps is the number of quantisation steps to use (up to a maximum of +100).</p> + +<p>For example, given the following settings:</p> +<ul> + <li>Range Minimum = 0.0</li> + <li>Range Maximum = 12.0</li> + <li>Match Range = 0.0</li> + <li>Steps = 4</li> + <li>Quantisation Values 3, 5, 7 and 10</li> +</ul> + +<p>and an input that is a line from -24 to 24, the output will be:</p> +<ul> + <li>Extend: -26, -21, -19, -17, -14, -9, -7, -5, -2, 3, 5, 7, 10, 15, 17, 19, + 22</li> + <li>Wrap: 10, 3, 5, 7, 10, 3, 5, 7, 10, 3, 5, 7, 10, 3, 5, 7, 10</li> + <li>Clip: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 7, 10, 10, 10, 10, 10</li> +</ul> + +<p>The quantisation values should all be within the range minimum and maximum +for it to work!</p> +""" . diff --git a/blop.lv2/quantiser_20.ttl b/blop.lv2/quantiser_20.ttl new file mode 100644 index 0000000..095716f --- /dev/null +++ b/blop.lv2/quantiser_20.ttl @@ -0,0 +1,239 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . + +blop:quantiser_20 + a lv2:Plugin ; + lv2:project blop: ; + lv2:symbol "quantiser_20" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:optionalFeature lv2:hardRTCapable ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 0 ; + lv2:name "Minimum" ; + lv2:symbol "min" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 1 ; + lv2:name "Maximum" ; + lv2:symbol "max" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 2 ; + lv2:minimum 0 ; + lv2:name "Match Range" ; + lv2:symbol "range" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 3 ; + lv2:maximum 2 ; + lv2:minimum 0 ; + lv2:name "Mode" ; + lv2:symbol "mode" ; + lv2:portProperty lv2:enumeration , + lv2:integer ; + lv2:scalePoint [ + rdfs:label "Extend" ; + rdf:value 0.0 + ] , [ + rdfs:label "Wrap" ; + rdf:value 1.0 + ] , [ + rdfs:label "Clip" ; + rdf:value 1.0 + ] + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 20 ; + lv2:index 4 ; + lv2:maximum 20 ; + lv2:minimum 1 ; + lv2:name "Steps" ; + lv2:portProperty lv2:integer ; + lv2:symbol "steps" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 5 ; + lv2:name "Value 0" ; + lv2:symbol "val00" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 6 ; + lv2:name "Value 1" ; + lv2:symbol "val01" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 7 ; + lv2:name "Value 2" ; + lv2:symbol "val02" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 8 ; + lv2:name "Value 3" ; + lv2:symbol "val03" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 9 ; + lv2:name "Value 4" ; + lv2:symbol "val04" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 10 ; + lv2:name "Value 5" ; + lv2:symbol "val05" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 11 ; + lv2:name "Value 6" ; + lv2:symbol "val06" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 12 ; + lv2:name "Value 7" ; + lv2:symbol "val07" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 13 ; + lv2:name "Value 8" ; + lv2:symbol "val08" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 14 ; + lv2:name "Value 9" ; + lv2:symbol "val09" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 15 ; + lv2:name "Value 10" ; + lv2:symbol "val10" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 16 ; + lv2:name "Value 11" ; + lv2:symbol "val11" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 17 ; + lv2:name "Value 12" ; + lv2:symbol "val12" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 18 ; + lv2:name "Value 13" ; + lv2:symbol "val13" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 19 ; + lv2:name "Value 14" ; + lv2:symbol "val14" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 20 ; + lv2:name "Value 15" ; + lv2:symbol "val15" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 21 ; + lv2:name "Value 16" ; + lv2:symbol "val16" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 22 ; + lv2:name "Value 17" ; + lv2:symbol "val17" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 23 ; + lv2:name "Value 18" ; + lv2:symbol "val18" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 24 ; + lv2:name "Value 19" ; + lv2:symbol "val19" + ] , [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 25 ; + lv2:name "Input" ; + lv2:symbol "in" + ] , [ + a lv2:CVPort , + lv2:OutputPort ; + lv2:index 26 ; + lv2:name "Quantised Output" ; + lv2:symbol "out" + ] , [ + a lv2:CVPort , + lv2:OutputPort ; + lv2:index 27 ; + lv2:name "Output Changed" ; + lv2:symbol "changed" + ] ; + dct:replaces <urn:ladspa:2027> ; + doap:name "Quantiser (20 Steps)" ; + lv2:documentation """ +<p>Quantises a signal to a set of arbitrary values within a range.</p> + +<p>Match Range determines the distance from the quantised value that the input +can deviate before being altered. This allows small variations in input to get +through unmolested. If it is set to 0 the input is quantised to the nearest +exact match.</p> + +<p>Mode is one of Extend (0), Wrap (1) or Clip (2).</p> + +<p>Steps is the number of quantisation steps to use (up to a maximum of +20).</p> + +<p>For example, given the following settings:</p> +<ul> + <li>Range Minimum = 0.0</li> + <li>Range Maximum = 12.0</li> + <li>Match Range = 0.0</li> + <li>Steps = 4</li> + <li>Quantisation Values 3, 5, 7 and 10</li> +</ul> + +<p>and an input that is a line from -24 to 24, the output will be:</p> +<ul> + <li>Extend: -26, -21, -19, -17, -14, -9, -7, -5, -2, 3, 5, 7, 10, 15, 17, 19, + 22</li> + <li>Wrap: 10, 3, 5, 7, 10, 3, 5, 7, 10, 3, 5, 7, 10, 3, 5, 7, 10</li> + <li>Clip: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 7, 10, 10, 10, 10, 10</li> +</ul> + +<p>The quantisation values should all be within the range minimum and maximum +for it to work!</p> +""" . diff --git a/blop.lv2/quantiser_50.ttl b/blop.lv2/quantiser_50.ttl new file mode 100644 index 0000000..901865c --- /dev/null +++ b/blop.lv2/quantiser_50.ttl @@ -0,0 +1,419 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . + +blop:quantiser_50 + a lv2:Plugin ; + lv2:project blop: ; + lv2:symbol "quantiser_50" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:optionalFeature lv2:hardRTCapable ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 0 ; + lv2:name "Minimum" ; + lv2:symbol "min" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 1 ; + lv2:name "Maximum" ; + lv2:symbol "max" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 2 ; + lv2:minimum 0 ; + lv2:name "Match Range" ; + lv2:symbol "range" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 3 ; + lv2:maximum 2 ; + lv2:minimum 0 ; + lv2:name "Mode" ; + lv2:symbol "mode" ; + lv2:portProperty lv2:enumeration , + lv2:integer ; + lv2:scalePoint [ + rdfs:label "Extend" ; + rdf:value 0.0 + ] , [ + rdfs:label "Wrap" ; + rdf:value 1.0 + ] , [ + rdfs:label "Clip" ; + rdf:value 1.0 + ] + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 20 ; + lv2:index 4 ; + lv2:maximum 20 ; + lv2:minimum 1 ; + lv2:name "Steps" ; + lv2:portProperty lv2:integer ; + lv2:symbol "steps" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 5 ; + lv2:name "Value 0" ; + lv2:symbol "val00" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 6 ; + lv2:name "Value 1" ; + lv2:symbol "val01" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 7 ; + lv2:name "Value 2" ; + lv2:symbol "val02" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 8 ; + lv2:name "Value 3" ; + lv2:symbol "val03" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 9 ; + lv2:name "Value 4" ; + lv2:symbol "val04" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 10 ; + lv2:name "Value 5" ; + lv2:symbol "val05" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 11 ; + lv2:name "Value 6" ; + lv2:symbol "val06" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 12 ; + lv2:name "Value 7" ; + lv2:symbol "val07" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 13 ; + lv2:name "Value 8" ; + lv2:symbol "val08" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 14 ; + lv2:name "Value 9" ; + lv2:symbol "val09" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 15 ; + lv2:name "Value 10" ; + lv2:symbol "val10" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 16 ; + lv2:name "Value 11" ; + lv2:symbol "val11" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 17 ; + lv2:name "Value 12" ; + lv2:symbol "val12" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 18 ; + lv2:name "Value 13" ; + lv2:symbol "val13" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 19 ; + lv2:name "Value 14" ; + lv2:symbol "val14" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 20 ; + lv2:name "Value 15" ; + lv2:symbol "val15" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 21 ; + lv2:name "Value 16" ; + lv2:symbol "val16" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 22 ; + lv2:name "Value 17" ; + lv2:symbol "val17" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 23 ; + lv2:name "Value 18" ; + lv2:symbol "val18" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 24 ; + lv2:name "Value 19" ; + lv2:symbol "val19" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 25 ; + lv2:name "Value 20" ; + lv2:symbol "val20" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 26 ; + lv2:name "Value 21" ; + lv2:symbol "val21" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 27 ; + lv2:name "Value 22" ; + lv2:symbol "val22" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 28 ; + lv2:name "Value 23" ; + lv2:symbol "val23" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 29 ; + lv2:name "Value 24" ; + lv2:symbol "val24" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 30 ; + lv2:name "Value 25" ; + lv2:symbol "val25" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 31 ; + lv2:name "Value 26" ; + lv2:symbol "val26" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 32 ; + lv2:name "Value 27" ; + lv2:symbol "val27" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 33 ; + lv2:name "Value 28" ; + lv2:symbol "val28" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 34 ; + lv2:name "Value 29" ; + lv2:symbol "val29" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 35 ; + lv2:name "Value 30" ; + lv2:symbol "val30" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 36 ; + lv2:name "Value 31" ; + lv2:symbol "val31" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 37 ; + lv2:name "Value 32" ; + lv2:symbol "val32" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 38 ; + lv2:name "Value 33" ; + lv2:symbol "val33" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 39 ; + lv2:name "Value 34" ; + lv2:symbol "val34" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 40 ; + lv2:name "Value 35" ; + lv2:symbol "val35" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 41 ; + lv2:name "Value 36" ; + lv2:symbol "val36" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 42 ; + lv2:name "Value 37" ; + lv2:symbol "val37" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 43 ; + lv2:name "Value 38" ; + lv2:symbol "val38" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 44 ; + lv2:name "Value 39" ; + lv2:symbol "val39" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 45 ; + lv2:name "Value 40" ; + lv2:symbol "val40" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 46 ; + lv2:name "Value 41" ; + lv2:symbol "val41" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 47 ; + lv2:name "Value 42" ; + lv2:symbol "val42" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 48 ; + lv2:name "Value 43" ; + lv2:symbol "val43" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 49 ; + lv2:name "Value 44" ; + lv2:symbol "val44" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 50 ; + lv2:name "Value 45" ; + lv2:symbol "val45" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 51 ; + lv2:name "Value 46" ; + lv2:symbol "val46" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 52 ; + lv2:name "Value 47" ; + lv2:symbol "val47" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 53 ; + lv2:name "Value 48" ; + lv2:symbol "val48" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 54 ; + lv2:name "Value 49" ; + lv2:symbol "val49" + ] , [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 55 ; + lv2:name "Input" ; + lv2:symbol "in" + ] , [ + a lv2:CVPort , + lv2:OutputPort ; + lv2:index 56 ; + lv2:name "Quantised Output" ; + lv2:symbol "out" + ] , [ + a lv2:CVPort , + lv2:OutputPort ; + lv2:index 57 ; + lv2:name "Output Changed" ; + lv2:symbol "changed" + ] ; + dct:replaces <urn:ladspa:2028> ; + doap:name "Quantiser (50 Steps)" ; + lv2:documentation """ +<p>Quantises a signal to a set of arbitrary values within a range.</p> + +<p>Match Range determines the distance from the quantised value that the input +can deviate before being altered. This allows small variations in input to get +through unmolested. If it is set to 0 the input is quantised to the nearest +exact match.</p> + +<p>Mode is one of Extend (0), Wrap (1) or Clip (2).</p> + +<p>Steps is the number of quantisation steps to use (up to a maximum of +50).</p> + +<p>For example, given the following settings:</p> +<ul> + <li>Range Minimum = 0.0</li> + <li>Range Maximum = 12.0</li> + <li>Match Range = 0.0</li> + <li>Steps = 4</li> + <li>Quantisation Values 3, 5, 7 and 10</li> +</ul> + +<p>and an input that is a line from -24 to 24, the output will be:</p> +<ul> + <li>Extend: -26, -21, -19, -17, -14, -9, -7, -5, -2, 3, 5, 7, 10, 15, 17, 19, + 22</li> + <li>Wrap: 10, 3, 5, 7, 10, 3, 5, 7, 10, 3, 5, 7, 10, 3, 5, 7, 10</li> + <li>Clip: 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 7, 10, 10, 10, 10, 10</li> +</ul> + +<p>The quantisation values should all be within the range minimum and maximum +for it to work!</p> +""" . diff --git a/blop.lv2/random.ttl b/blop.lv2/random.ttl new file mode 100644 index 0000000..8b810c9 --- /dev/null +++ b/blop.lv2/random.ttl @@ -0,0 +1,64 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix units: <http://lv2plug.in/ns/extensions/units#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:random + a lv2:Plugin , + lv2:OscillatorPlugin ; + lv2:project blop: ; + lv2:symbol "random" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 0 ; + lv2:maximum 0.5 ; + lv2:minimum 0.000001 ; + lv2:default 440.0 ; + lv2:name "Frequency" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> , + lv2:sampleRate ; + lv2:symbol "freq" ; + morph:supportsType lv2:CVPort ; + units:unit units:hz + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 1 ; + lv2:index 1 ; + lv2:maximum 1 ; + lv2:minimum 0 ; + lv2:name "Smoothness" ; + lv2:symbol "smooth" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:AudioPort , + lv2:OutputPort , + lv2:Port ; + lv2:index 2 ; + lv2:name "Output" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1661> , + <urn:ladspa:1662> , + <urn:ladspa:1663> , + <urn:ladspa:1664> ; + doap:name "Random Wave" ; + lv2:documentation """ +<p>Generates a random waveform of varying frequency and smoothness. The +frequency determines how often the output changes. The smoothness, how quickly +a transition occurs.</p> + +<p>The output varies between ±1, with an even distribution.</p> +""" . diff --git a/blop.lv2/ratio.ttl b/blop.lv2/ratio.ttl new file mode 100644 index 0000000..04e4d90 --- /dev/null +++ b/blop.lv2/ratio.ttl @@ -0,0 +1,52 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:ratio + a lv2:Plugin , + lv2:UtilityPlugin ; + lv2:project blop: ; + lv2:symbol "ratio" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 0 ; + lv2:name "Numerator" ; + lv2:symbol "numerator" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 1 ; + lv2:name "Denominator" ; + lv2:symbol "denominator" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:ControlPort , + lv2:OutputPort , + morph:AutoMorphPort ; + lv2:index 2 ; + lv2:name "Ratio" ; + lv2:symbol "ratio" ; + morph:supportsType lv2:CVPort + ] ; + dct:replaces <urn:ladspa:2034> , + <urn:ladspa:2035> , + <urn:ladspa:2036> , + <urn:ladspa:2037> ; + doap:name "Ratio" ; + lv2:documentation """ +<p>Get the ratio between two signals.</p> +<p>To avoid divisions by zero, 0 is treated as a really small number.</p> +""" . diff --git a/blop.lv2/sawtooth.ttl b/blop.lv2/sawtooth.ttl new file mode 100644 index 0000000..04dec12 --- /dev/null +++ b/blop.lv2/sawtooth.ttl @@ -0,0 +1,46 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix units: <http://lv2plug.in/ns/extensions/units#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:sawtooth + a lv2:Plugin , + lv2:OscillatorPlugin ; + lv2:project blop: ; + lv2:symbol "sawtooth" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 0 ; + lv2:maximum 0.5 ; + lv2:minimum 0.000001 ; + lv2:default 440.0 ; + lv2:name "Frequency" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> , + lv2:sampleRate ; + lv2:symbol "freq" ; + morph:supportsType lv2:CVPort ; + units:unit units:hz + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 1 ; + lv2:name "Output" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1642> , + <urn:ladspa:1643> ; + doap:name "Sawtooth" ; + lv2:documentation """ +<p>Generates an alias-free sawtooth wave at given input frequency.</p> +""" . diff --git a/blop.lv2/sequencer_16.ttl b/blop.lv2/sequencer_16.ttl new file mode 100644 index 0000000..97473a6 --- /dev/null +++ b/blop.lv2/sequencer_16.ttl @@ -0,0 +1,167 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . + +blop:sequencer_16 + a lv2:Plugin ; + lv2:project blop: ; + lv2:symbol "sequencer_16" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:optionalFeature lv2:hardRTCapable ; + lv2:port [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 0 ; + lv2:name "Gate" ; + lv2:portProperty lv2:toggled ; + lv2:symbol "gate" + ] , [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 1 ; + lv2:name "Step Trigger" ; + lv2:portProperty lv2:toggled , + <http://lv2plug.in/ns/ext/port-props#trigger> ; + lv2:symbol "trigger" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 16 ; + lv2:index 2 ; + lv2:maximum 16 ; + lv2:minimum 1 ; + lv2:name "Loop Steps" ; + lv2:portProperty lv2:integer ; + lv2:symbol "steps" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 3 ; + lv2:maximum 1 ; + lv2:minimum 0 ; + lv2:name "Reset on Gate Close" ; + lv2:portProperty lv2:toggled ; + lv2:symbol "reset" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 4 ; + lv2:name "Closed Gate Value" ; + lv2:symbol "closed_val" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 5 ; + lv2:name "Value 0" ; + lv2:symbol "val00" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 6 ; + lv2:name "Value 1" ; + lv2:symbol "val01" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 7 ; + lv2:name "Value 2" ; + lv2:symbol "val02" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 8 ; + lv2:name "Value 3" ; + lv2:symbol "val03" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 9 ; + lv2:name "Value 4" ; + lv2:symbol "val04" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 10 ; + lv2:name "Value 5" ; + lv2:symbol "val05" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 11 ; + lv2:name "Value 6" ; + lv2:symbol "val06" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 12 ; + lv2:name "Value 7" ; + lv2:symbol "val07" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 13 ; + lv2:name "Value 8" ; + lv2:symbol "val08" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 14 ; + lv2:name "Value 9" ; + lv2:symbol "val09" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 15 ; + lv2:name "Value 10" ; + lv2:symbol "val10" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 16 ; + lv2:name "Value 11" ; + lv2:symbol "val11" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 17 ; + lv2:name "Value 12" ; + lv2:symbol "val12" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 18 ; + lv2:name "Value 13" ; + lv2:symbol "val13" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 19 ; + lv2:name "Value 14" ; + lv2:symbol "val14" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 20 ; + lv2:name "Value 15" ; + lv2:symbol "val15" + ] , [ + a lv2:CVPort , + lv2:OutputPort ; + lv2:index 21 ; + lv2:name "Value Out" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1677> ; + doap:name "16 Step Sequencer" ; + lv2:documentation """ +<p>Simulates an analogue step sequencer. The sequencer stores a number of +values which are stepped through using a trigger when the gate is open, looping +after a given number of steps. This variant has 16 steps.</p> + +<p>When the gate is closed, the sequencer returns to the start. Output when +the gate is closed can be set to a default value. If not, it will just output +the last value reached before the gate was closed.</p> +""" . diff --git a/blop.lv2/sequencer_32.ttl b/blop.lv2/sequencer_32.ttl new file mode 100644 index 0000000..ae289f2 --- /dev/null +++ b/blop.lv2/sequencer_32.ttl @@ -0,0 +1,263 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . + +blop:sequencer_32 + a lv2:Plugin ; + lv2:project blop: ; + lv2:symbol "sequencer_32" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:optionalFeature lv2:hardRTCapable ; + lv2:port [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 0 ; + lv2:name "Gate" ; + lv2:portProperty lv2:toggled ; + lv2:symbol "gate" + ] , [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 1 ; + lv2:name "Step Trigger" ; + lv2:portProperty lv2:toggled , + <http://lv2plug.in/ns/ext/port-props#trigger> ; + lv2:symbol "trigger" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 32 ; + lv2:index 2 ; + lv2:maximum 32 ; + lv2:minimum 1 ; + lv2:name "Loop Steps" ; + lv2:portProperty lv2:integer ; + lv2:symbol "steps" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 3 ; + lv2:maximum 1 ; + lv2:minimum 0 ; + lv2:name "Reset on Gate Close" ; + lv2:portProperty lv2:toggled ; + lv2:symbol "reset" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 4 ; + lv2:name "Closed Gate Value" ; + lv2:symbol "closed_val" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 5 ; + lv2:name "Value 0" ; + lv2:symbol "val00" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 6 ; + lv2:name "Value 1" ; + lv2:symbol "val01" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 7 ; + lv2:name "Value 2" ; + lv2:symbol "val02" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 8 ; + lv2:name "Value 3" ; + lv2:symbol "val03" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 9 ; + lv2:name "Value 4" ; + lv2:symbol "val04" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 10 ; + lv2:name "Value 5" ; + lv2:symbol "val05" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 11 ; + lv2:name "Value 6" ; + lv2:symbol "val06" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 12 ; + lv2:name "Value 7" ; + lv2:symbol "val07" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 13 ; + lv2:name "Value 8" ; + lv2:symbol "val08" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 14 ; + lv2:name "Value 9" ; + lv2:symbol "val09" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 15 ; + lv2:name "Value 10" ; + lv2:symbol "val10" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 16 ; + lv2:name "Value 11" ; + lv2:symbol "val11" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 17 ; + lv2:name "Value 12" ; + lv2:symbol "val12" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 18 ; + lv2:name "Value 13" ; + lv2:symbol "val13" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 19 ; + lv2:name "Value 14" ; + lv2:symbol "val14" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 20 ; + lv2:name "Value 15" ; + lv2:symbol "val15" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 21 ; + lv2:name "Value 16" ; + lv2:symbol "val16" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 22 ; + lv2:name "Value 17" ; + lv2:symbol "val17" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 23 ; + lv2:name "Value 18" ; + lv2:symbol "val18" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 24 ; + lv2:name "Value 19" ; + lv2:symbol "val19" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 25 ; + lv2:name "Value 20" ; + lv2:symbol "val20" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 26 ; + lv2:name "Value 21" ; + lv2:symbol "val21" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 27 ; + lv2:name "Value 22" ; + lv2:symbol "val22" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 28 ; + lv2:name "Value 23" ; + lv2:symbol "val23" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 29 ; + lv2:name "Value 24" ; + lv2:symbol "val24" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 30 ; + lv2:name "Value 25" ; + lv2:symbol "val25" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 31 ; + lv2:name "Value 26" ; + lv2:symbol "val26" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 32 ; + lv2:name "Value 27" ; + lv2:symbol "val27" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 33 ; + lv2:name "Value 28" ; + lv2:symbol "val28" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 34 ; + lv2:name "Value 29" ; + lv2:symbol "val29" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 35 ; + lv2:name "Value 30" ; + lv2:symbol "val30" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 36 ; + lv2:name "Value 31" ; + lv2:symbol "val31" + ] , [ + a lv2:CVPort , + lv2:OutputPort ; + lv2:index 37 ; + lv2:name "Value Out" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1676> ; + doap:name "32 Step Sequencer" ; + lv2:documentation """ +<p>Simulates an analogue step sequencer. The sequencer stores a number of +values which are stepped through using a trigger when the gate is open, looping +after a given number of steps. This variant has 32 steps.</p> + +<p>When the gate is closed, the sequencer returns to the start. Output when +the gate is closed can be set to a default value. If not, it will just output +the last value reached before the gate was closed.</p> +""" . diff --git a/blop.lv2/sequencer_64.ttl b/blop.lv2/sequencer_64.ttl new file mode 100644 index 0000000..3a3ea0f --- /dev/null +++ b/blop.lv2/sequencer_64.ttl @@ -0,0 +1,455 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . + +blop:sequencer_64 + a lv2:Plugin ; + lv2:project blop: ; + lv2:symbol "sequencer_64" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:optionalFeature lv2:hardRTCapable ; + lv2:port [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 0 ; + lv2:name "Gate" ; + lv2:portProperty lv2:toggled ; + lv2:symbol "gate" + ] , [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 1 ; + lv2:name "Step Trigger" ; + lv2:portProperty lv2:toggled , + <http://lv2plug.in/ns/ext/port-props#trigger> ; + lv2:symbol "trigger" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 32 ; + lv2:index 2 ; + lv2:maximum 32 ; + lv2:minimum 1 ; + lv2:name "Loop Steps" ; + lv2:portProperty lv2:integer ; + lv2:symbol "steps" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:default 0 ; + lv2:index 3 ; + lv2:maximum 1 ; + lv2:minimum 0 ; + lv2:name "Reset on Gate Close" ; + lv2:portProperty lv2:toggled ; + lv2:symbol "reset" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 4 ; + lv2:name "Closed Gate Value" ; + lv2:symbol "closed_val" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 5 ; + lv2:name "Value 0" ; + lv2:symbol "val00" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 6 ; + lv2:name "Value 1" ; + lv2:symbol "val01" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 7 ; + lv2:name "Value 2" ; + lv2:symbol "val02" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 8 ; + lv2:name "Value 3" ; + lv2:symbol "val03" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 9 ; + lv2:name "Value 4" ; + lv2:symbol "val04" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 10 ; + lv2:name "Value 5" ; + lv2:symbol "val05" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 11 ; + lv2:name "Value 6" ; + lv2:symbol "val06" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 12 ; + lv2:name "Value 7" ; + lv2:symbol "val07" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 13 ; + lv2:name "Value 8" ; + lv2:symbol "val08" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 14 ; + lv2:name "Value 9" ; + lv2:symbol "val09" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 15 ; + lv2:name "Value 10" ; + lv2:symbol "val10" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 16 ; + lv2:name "Value 11" ; + lv2:symbol "val11" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 17 ; + lv2:name "Value 12" ; + lv2:symbol "val12" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 18 ; + lv2:name "Value 13" ; + lv2:symbol "val13" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 19 ; + lv2:name "Value 14" ; + lv2:symbol "val14" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 20 ; + lv2:name "Value 15" ; + lv2:symbol "val15" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 21 ; + lv2:name "Value 16" ; + lv2:symbol "val16" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 22 ; + lv2:name "Value 17" ; + lv2:symbol "val17" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 23 ; + lv2:name "Value 18" ; + lv2:symbol "val18" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 24 ; + lv2:name "Value 19" ; + lv2:symbol "val19" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 25 ; + lv2:name "Value 20" ; + lv2:symbol "val20" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 26 ; + lv2:name "Value 21" ; + lv2:symbol "val21" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 27 ; + lv2:name "Value 22" ; + lv2:symbol "val22" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 28 ; + lv2:name "Value 23" ; + lv2:symbol "val23" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 29 ; + lv2:name "Value 24" ; + lv2:symbol "val24" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 30 ; + lv2:name "Value 25" ; + lv2:symbol "val25" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 31 ; + lv2:name "Value 26" ; + lv2:symbol "val26" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 32 ; + lv2:name "Value 27" ; + lv2:symbol "val27" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 33 ; + lv2:name "Value 28" ; + lv2:symbol "val28" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 34 ; + lv2:name "Value 29" ; + lv2:symbol "val29" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 35 ; + lv2:name "Value 30" ; + lv2:symbol "val30" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 36 ; + lv2:name "Value 31" ; + lv2:symbol "val31" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 37 ; + lv2:name "Value 32" ; + lv2:symbol "val32" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 38 ; + lv2:name "Value 33" ; + lv2:symbol "val33" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 39 ; + lv2:name "Value 34" ; + lv2:symbol "val34" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 40 ; + lv2:name "Value 35" ; + lv2:symbol "val35" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 41 ; + lv2:name "Value 36" ; + lv2:symbol "val36" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 42 ; + lv2:name "Value 37" ; + lv2:symbol "val37" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 43 ; + lv2:name "Value 38" ; + lv2:symbol "val38" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 44 ; + lv2:name "Value 39" ; + lv2:symbol "val39" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 45 ; + lv2:name "Value 40" ; + lv2:symbol "val40" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 46 ; + lv2:name "Value 41" ; + lv2:symbol "val41" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 47 ; + lv2:name "Value 42" ; + lv2:symbol "val42" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 48 ; + lv2:name "Value 43" ; + lv2:symbol "val43" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 49 ; + lv2:name "Value 44" ; + lv2:symbol "val44" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 50 ; + lv2:name "Value 45" ; + lv2:symbol "val45" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 51 ; + lv2:name "Value 46" ; + lv2:symbol "val46" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 52 ; + lv2:name "Value 47" ; + lv2:symbol "val47" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 53 ; + lv2:name "Value 48" ; + lv2:symbol "val48" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 54 ; + lv2:name "Value 49" ; + lv2:symbol "val49" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 55 ; + lv2:name "Value 50" ; + lv2:symbol "val50" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 56 ; + lv2:name "Value 51" ; + lv2:symbol "val51" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 57 ; + lv2:name "Value 52" ; + lv2:symbol "val52" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 58 ; + lv2:name "Value 53" ; + lv2:symbol "val53" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 59 ; + lv2:name "Value 54" ; + lv2:symbol "val54" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 60 ; + lv2:name "Value 55" ; + lv2:symbol "val55" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 61 ; + lv2:name "Value 56" ; + lv2:symbol "val56" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 62 ; + lv2:name "Value 57" ; + lv2:symbol "val57" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 63 ; + lv2:name "Value 58" ; + lv2:symbol "val58" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 64 ; + lv2:name "Value 59" ; + lv2:symbol "val59" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 65 ; + lv2:name "Value 60" ; + lv2:symbol "val60" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 66 ; + lv2:name "Value 61" ; + lv2:symbol "val61" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 67 ; + lv2:name "Value 62" ; + lv2:symbol "val62" + ] , [ + a lv2:ControlPort , + lv2:InputPort ; + lv2:index 68 ; + lv2:name "Value 63" ; + lv2:symbol "val63" + ] , [ + a lv2:CVPort , + lv2:OutputPort ; + lv2:index 69 ; + lv2:name "Value Out" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1675> ; + doap:name "64 Step Sequencer" ; + lv2:documentation """ +<p>Simulates an analogue step sequencer. The sequencer stores a number of +values which are stepped through using a trigger when the gate is open, looping +after a given number of steps. This variant has 64 steps.</p> + +<p>When the gate is closed, the sequencer returns to the start. Output when +the gate is closed can be set to a default value. If not, it will just output +the last value reached before the gate was closed.</p> +""" . diff --git a/blop.lv2/square.ttl b/blop.lv2/square.ttl new file mode 100644 index 0000000..77f30bc --- /dev/null +++ b/blop.lv2/square.ttl @@ -0,0 +1,46 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix units: <http://lv2plug.in/ns/extensions/units#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:square + a lv2:Plugin , + lv2:OscillatorPlugin ; + lv2:project blop: ; + lv2:symbol "square" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 0 ; + lv2:maximum 0.5 ; + lv2:minimum 0.000001 ; + lv2:default 440.0 ; + lv2:name "Frequency" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> , + lv2:sampleRate ; + lv2:symbol "freq" ; + morph:supportsType lv2:CVPort ; + units:unit units:hz + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 1 ; + lv2:name "Output" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1643> , + <urn:ladspa:1644> ; + doap:name "Square" ; + lv2:documentation """ +<p>Generates an alias-free square wave at given input frequency.</p> +""" . diff --git a/blop.lv2/sum.ttl b/blop.lv2/sum.ttl new file mode 100644 index 0000000..66ea88d --- /dev/null +++ b/blop.lv2/sum.ttl @@ -0,0 +1,50 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:sum + a lv2:Plugin , + lv2:UtilityPlugin ; + lv2:project blop: ; + lv2:symbol "sum" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 0 ; + lv2:name "Input 1" ; + lv2:symbol "in1" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 1 ; + lv2:name "Input 2" ; + lv2:symbol "in2" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:ControlPort , + lv2:OutputPort , + morph:AutoMorphPort ; + lv2:index 2 ; + lv2:name "Sum" ; + lv2:symbol "sum" ; + morph:supportsType lv2:CVPort + ] ; + dct:replaces <urn:ladspa:1665> , + <urn:ladspa:1666> , + <urn:ladspa:1667> ; + doap:name "Sum" ; + lv2:documentation """ +<p>Add two signals.</p> +""" . diff --git a/blop.lv2/sync_pulse.ttl b/blop.lv2/sync_pulse.ttl new file mode 100644 index 0000000..47051e2 --- /dev/null +++ b/blop.lv2/sync_pulse.ttl @@ -0,0 +1,63 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix units: <http://lv2plug.in/ns/extensions/units#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:sync_pulse + a lv2:Plugin , + lv2:OscillatorPlugin ; + lv2:project blop: ; + lv2:symbol "sync_pulse" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 16 ; + lv2:index 0 ; + lv2:maximum 64 ; + lv2:minimum 0 ; + lv2:name "Frequency" ; + lv2:symbol "freq" ; + morph:supportsType lv2:CVPort ; + units:unit units:hz + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 0.5 ; + lv2:index 1 ; + lv2:maximum 1 ; + lv2:minimum 0 ; + lv2:name "Pulse Width" ; + lv2:symbol "pwidth" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 2 ; + lv2:name "Gate" ; + lv2:portProperty lv2:toggled ; + lv2:symbol "gate" + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 3 ; + lv2:name "Output" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:2023> , + <urn:ladspa:2024> ; + doap:name "Clock Pulse" ; + lv2:documentation """ +<p>Same as the <a href="http://drobilla.net/plugins/blop/sync_square">Clock +Oscillator</a>, but with pulse-width modulation.</p> +""" . diff --git a/blop.lv2/sync_square.ttl b/blop.lv2/sync_square.ttl new file mode 100644 index 0000000..873619f --- /dev/null +++ b/blop.lv2/sync_square.ttl @@ -0,0 +1,55 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix units: <http://lv2plug.in/ns/extensions/units#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:sync_square + a lv2:Plugin , + lv2:OscillatorPlugin ; + lv2:project blop: ; + lv2:symbol "sync_square" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 16 ; + lv2:index 0 ; + lv2:maximum 64 ; + lv2:minimum 0 ; + lv2:name "Frequency" ; + lv2:symbol "freq" ; + morph:supportsType lv2:CVPort ; + units:unit units:hz + ] , [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 1 ; + lv2:name "Gate" ; + lv2:portProperty lv2:toggled ; + lv2:symbol "gate" + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 2 ; + lv2:name "Output" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1678> , + <urn:ladspa:1679> ; + doap:name "Clock Square" ; + lv2:documentation """ +<p>Generates a non-bandlimited simple square waveform for use as a clock. +Useful for triggering the sequencers, or anything else that uses a clock +signal.</p> + +<p>When the gate is closed, it outputs silence, and the phase is reset.</p> +""" . diff --git a/blop.lv2/tracker.ttl b/blop.lv2/tracker.ttl new file mode 100644 index 0000000..b62d811 --- /dev/null +++ b/blop.lv2/tracker.ttl @@ -0,0 +1,122 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix units: <http://lv2plug.in/ns/extensions/units#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:tracker + a lv2:Plugin ; + lv2:project blop: ; + lv2:symbol "tracker" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:CVPort , + lv2:InputPort ; + lv2:index 0 ; + lv2:name "Gate" ; + lv2:portProperty lv2:toggled ; + lv2:symbol "gate" + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 100 ; + lv2:index 1 ; + lv2:maximum 0.5 ; + lv2:minimum 0.00001 ; + lv2:name "High Attack Rate" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> , + lv2:sampleRate ; + lv2:symbol "hattack" ; + morph:supportsType lv2:CVPort ; + units:unit units:hz + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 100 ; + lv2:index 2 ; + lv2:maximum 0.5 ; + lv2:minimum 0.00001 ; + lv2:name "High Decay Rate" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> , + lv2:sampleRate ; + lv2:symbol "hdecay" ; + morph:supportsType lv2:CVPort ; + units:unit units:hz + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 100 ; + lv2:index 3 ; + lv2:maximum 0.5 ; + lv2:minimum 0.00001 ; + lv2:name "Low Attack Rate" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> , + lv2:sampleRate ; + lv2:symbol "lattack" ; + morph:supportsType lv2:CVPort ; + units:unit units:hz + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 100 ; + lv2:index 4 ; + lv2:maximum 0.5 ; + lv2:minimum 0.00001 ; + lv2:name "Low Decay Rate" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> , + lv2:sampleRate ; + lv2:symbol "ldecay" ; + morph:supportsType lv2:CVPort ; + units:unit units:hz + ] , [ + a lv2:AudioPort , + lv2:InputPort ; + lv2:index 5 ; + lv2:name "Input" ; + lv2:symbol "in" + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 6 ; + lv2:name "Output" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:2025> , + <urn:ladspa:2026> ; + doap:name "Tracker" ; + lv2:documentation """ +<p>This tracks an incoming signal and outputs the result.</p> +<p>The rate controls tell the plugin how quickly to respond to a change in +input. Low values will mean a slower response - a setting of 0 will hold the +last value, and a very high value will track the input exactly.</p> +<p>Attack rate is how quickly an upward change is tracked, and Decay for +downward changes. There are two pairs of these - the one used depends on the +level of the Gate.</p> +<p>Example uses:</p> +<ul> + <li> + <em>An envelope tracker</em>- use the ‘Gate Low’ track rates with + the Gate held low, and run the output through a full-wave rectifier (an ABS() + operator) to get an estimate of the level of a signal.</li> + <li> + <em>Sample and Hold</em>- run a narrow pulse wave into the gate, set the + ‘Gate High’ rates to maximum, and the ‘Gate Low’ + rates set to 0.</li> + <li> + <em>Track and Hold</em>- run a variable pulse wave into the gate, set the + ‘Gate High’ rates to 0, and the ‘Gate Low’ rates set + high. Varying the pulsewidth will vary the time the input is tracked, and + when it is held.</li> +</ul> +""" . diff --git a/blop.lv2/triangle.ttl b/blop.lv2/triangle.ttl new file mode 100644 index 0000000..60b5a2b --- /dev/null +++ b/blop.lv2/triangle.ttl @@ -0,0 +1,61 @@ +@prefix blop: <http://drobilla.net/plugins/blop/> . +@prefix dct: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix morph: <http://lv2plug.in/ns/ext/morph#> . +@prefix opts: <http://lv2plug.in/ns/ext/options#> . +@prefix units: <http://lv2plug.in/ns/extensions/units#> . +@prefix urid: <http://lv2plug.in/ns/ext/urid#> . + +blop:triangle + a lv2:Plugin , + lv2:OscillatorPlugin ; + lv2:project blop: ; + lv2:symbol "triangle" ; + lv2:microVersion 0 ; + lv2:minorVersion 0 ; + lv2:extensionData opts:interface ; + lv2:optionalFeature lv2:hardRTCapable , + urid:map ; + lv2:port [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:index 0 ; + lv2:maximum 0.5 ; + lv2:minimum 0.000001 ; + lv2:default 440.0 ; + lv2:name "Frequency" ; + lv2:portProperty <http://lv2plug.in/ns/ext/port-props#logarithmic> , + lv2:sampleRate ; + lv2:symbol "freq" ; + morph:supportsType lv2:CVPort ; + units:unit units:hz + ] , [ + a lv2:ControlPort , + lv2:InputPort , + morph:MorphPort ; + lv2:default 0.5 ; + lv2:index 1 ; + lv2:maximum 1 ; + lv2:minimum 0 ; + lv2:name "Slope" ; + lv2:symbol "slope" ; + morph:supportsType lv2:CVPort + ] , [ + a lv2:AudioPort , + lv2:OutputPort ; + lv2:index 2 ; + lv2:name "Output" ; + lv2:symbol "out" + ] ; + dct:replaces <urn:ladspa:1649> , + <urn:ladspa:1650> , + <urn:ladspa:1651> , + <urn:ladspa:1652> ; + doap:name "Triangle" ; + lv2:documentation """ +<p>Generates an alias-free variable slope triangle wave at given input +frequency and slope. The slope changes the wave shape from sawtooth to +triangle.</p> +""" . diff --git a/src/adsr.c b/src/adsr.c new file mode 100644 index 0000000..a84469f --- /dev/null +++ b/src/adsr.c @@ -0,0 +1,259 @@ +/* + An LV2 plugin to generate ADSR envelopes. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "common.h" + +#define ADSR_SIGNAL 0 +#define ADSR_TRIGGER 1 +#define ADSR_ATTACK 2 +#define ADSR_DECAY 3 +#define ADSR_SUSTAIN 4 +#define ADSR_RELEASE 5 +#define ADSR_OUTPUT 6 + +typedef enum { + IDLE, + ATTACK, + DECAY, + SUSTAIN, + RELEASE +} ADSRState; + +typedef struct { + const float* signal; + const float* trigger; + const float* attack; + const float* decay; + const float* sustain; + const float* release; + float* output; + float srate; + float inv_srate; + float from_level; + float level; + ADSRState state; + uint32_t samples; +} Adsr; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Adsr* plugin = (Adsr*)instance; + + switch (port) { + case ADSR_SIGNAL: + plugin->signal = (const float*)data; + break; + case ADSR_TRIGGER: + plugin->trigger = (const float*)data; + break; + case ADSR_ATTACK: + plugin->attack = (const float*)data; + break; + case ADSR_DECAY: + plugin->decay = (const float*)data; + break; + case ADSR_SUSTAIN: + plugin->sustain = (const float*)data; + break; + case ADSR_RELEASE: + plugin->release = (const float*)data; + break; + case ADSR_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Adsr* plugin = (Adsr*)malloc(sizeof(Adsr)); + if (!plugin) { + return NULL; + } + + plugin->srate = (float)sample_rate; + plugin->inv_srate = 1.0f / plugin->srate; + + return (LV2_Handle)plugin; +} + +static void +activate(LV2_Handle instance) +{ + Adsr* plugin = (Adsr*)instance; + + plugin->from_level = 0.0f; + plugin->level = 0.0f; + plugin->state = IDLE; + plugin->samples = 0; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Adsr* plugin = (Adsr*)instance; + + /* Driving signal */ + const float* signal = plugin->signal; + + /* Trigger Threshold */ + const float trigger = *(plugin->trigger); + + /* Attack Time (s) */ + float attack = *(plugin->attack); + + /* Decay Time (s) */ + float decay = *(plugin->decay); + + /* Sustain Level */ + const float sustain = f_clip(*(plugin->sustain), 0.0f, 1.0f); + + /* Release Time (s) */ + float release = *(plugin->release); + + /* Envelope Out */ + float* output = plugin->output; + + float srate = plugin->srate; + float inv_srate = plugin->inv_srate; + float from_level = plugin->from_level; + float level = plugin->level; + ADSRState state = plugin->state; + uint32_t samples = plugin->samples; + + float elapsed; + + /* Convert times into rates */ + attack = attack > 0.0f ? inv_srate / attack : srate; + decay = decay > 0.0f ? inv_srate / decay : srate; + release = release > 0.0f ? inv_srate / release : srate; + + for (uint32_t s = 0; s < sample_count; s++) { + /* Determine if attack or release happened */ + if ((state == IDLE) || (state == RELEASE)) { + if (signal[s] > trigger) { + if (attack < srate) { + state = ATTACK; + } else { + state = decay < srate ? DECAY : SUSTAIN; + level = 1.0f; + } + samples = 0; + } + } else { + if (signal[s] <= trigger) { + state = release < srate ? RELEASE : IDLE; + samples = 0; + } + } + + if (samples == 0) { + from_level = level; + } + + /* Calculate level of envelope from current state */ + switch (state) { + case IDLE: + level = 0; + break; + case ATTACK: + samples++; + elapsed = (float)samples * attack; + if (elapsed > 1.0f) { + state = decay < srate ? DECAY : SUSTAIN; + level = 1.0f; + samples = 0; + } else { + level = from_level + elapsed * (1.0f - from_level); + } + break; + case DECAY: + samples++; + elapsed = (float)samples * decay; + if (elapsed > 1.0f) { + state = SUSTAIN; + level = sustain; + samples = 0; + } else { + level = from_level + elapsed * (sustain - from_level); + } + break; + case SUSTAIN: + level = sustain; + break; + case RELEASE: + samples++; + elapsed = (float)samples * release; + if (elapsed > 1.0f) { + state = IDLE; + level = 0.0f; + samples = 0; + } else { + level = from_level - elapsed * from_level; + } + break; + default: + /* Should never happen */ + level = 0.0f; + } + + output[s] = level; + } + + plugin->from_level = from_level; + plugin->level = level; + plugin->state = state; + plugin->samples = samples; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/adsr", + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + NULL, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/adsr_gt.c b/src/adsr_gt.c new file mode 100644 index 0000000..4f23649 --- /dev/null +++ b/src/adsr_gt.c @@ -0,0 +1,266 @@ +/* + An LV2 plugin to generate ADSR envelopes Gate and Trigger variant. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "common.h" + +#define ADSR_GATE 0 +#define ADSR_TRIGGER 1 +#define ADSR_ATTACK 2 +#define ADSR_DECAY 3 +#define ADSR_SUSTAIN 4 +#define ADSR_RELEASE 5 +#define ADSR_OUTPUT 6 + +typedef enum { + IDLE, + ATTACK, + DECAY, + SUSTAIN, + RELEASE +} ADSRState; + +typedef struct { + const float* gate; + const float* trigger; + const float* attack; + const float* decay; + const float* sustain; + const float* release; + float* output; + float srate; + float inv_srate; + float last_trigger; + float from_level; + float level; + ADSRState state; + uint32_t samples; +} Adsr; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Adsr* plugin = (Adsr*)instance; + + switch (port) { + case ADSR_GATE: + plugin->gate = (const float*)data; + break; + case ADSR_TRIGGER: + plugin->trigger = (const float*)data; + break; + case ADSR_ATTACK: + plugin->attack = (const float*)data; + break; + case ADSR_DECAY: + plugin->decay = (const float*)data; + break; + case ADSR_SUSTAIN: + plugin->sustain = (const float*)data; + break; + case ADSR_RELEASE: + plugin->release = (const float*)data; + break; + case ADSR_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Adsr* plugin = (Adsr*)malloc(sizeof(Adsr)); + + if (plugin) { + plugin->srate = (float)sample_rate; + plugin->inv_srate = 1.0f / plugin->srate; + } + + return (LV2_Handle)plugin; +} + +static void +activate(LV2_Handle instance) +{ + Adsr* plugin = (Adsr*)instance; + + plugin->last_trigger = 0.0f; + plugin->from_level = 0.0f; + plugin->level = 0.0f; + plugin->state = IDLE; + plugin->samples = 0; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Adsr* plugin = (Adsr*)instance; + + /* Gate */ + const float* gate = plugin->gate; + + /* Trigger */ + const float* trigger = plugin->trigger; + + /* Attack Time (s) */ + float attack = *(plugin->attack); + + /* Decay Time (s) */ + float decay = *(plugin->decay); + + /* Sustain Level */ + const float sustain = f_clip(*(plugin->sustain), 0.0f, 1.0f); + + /* Release Time (s) */ + float release = *(plugin->release); + + /* Envelope Out */ + float* output = plugin->output; + + float srate = plugin->srate; + float inv_srate = plugin->inv_srate; + float last_trigger = plugin->last_trigger; + float from_level = plugin->from_level; + float level = plugin->level; + ADSRState state = plugin->state; + uint32_t samples = plugin->samples; + + float elapsed; + + /* Convert times into rates */ + attack = attack > 0.0f ? inv_srate / attack : srate; + decay = decay > 0.0f ? inv_srate / decay : srate; + release = release > 0.0f ? inv_srate / release : srate; + + for (uint32_t s = 0; s < sample_count; ++s) { + /* Attack on trigger, if gate is open */ + if (trigger[s] > 0.0f + && !(last_trigger > 0.0f) + && gate[s] > 0.0f) { + if (attack < srate) { + state = ATTACK; + } else { + state = decay < srate ? DECAY : SUSTAIN; + level = 1.0f; + } + samples = 0; + } + + /* Release if gate closed */ + if (state != IDLE + && state != RELEASE + && !(gate[s] > 0.0f)) { + state = release < srate ? RELEASE : IDLE; + samples = 0; + } + + if (samples == 0) { + from_level = level; + } + + /* Calculate level of envelope from current state */ + switch (state) { + case IDLE: + level = 0; + break; + case ATTACK: + samples++; + elapsed = (float)samples * attack; + if (elapsed > 1.0f) { + state = decay < srate ? DECAY : SUSTAIN; + level = 1.0f; + samples = 0; + } else { + level = from_level + elapsed * (1.0f - from_level); + } + break; + case DECAY: + samples++; + elapsed = (float)samples * decay; + if (elapsed > 1.0f) { + state = SUSTAIN; + level = sustain; + samples = 0; + } else { + level = from_level + elapsed * (sustain - from_level); + } + break; + case SUSTAIN: + level = sustain; + break; + case RELEASE: + samples++; + elapsed = (float)samples * release; + if (elapsed > 1.0f) { + state = IDLE; + level = 0.0f; + samples = 0; + } else { + level = from_level - elapsed * from_level; + } + break; + default: + /* Should never happen */ + level = 0.0f; + } + + output[s] = level; + last_trigger = trigger[s]; + } + + plugin->last_trigger = last_trigger; + plugin->from_level = from_level; + plugin->level = level; + plugin->state = state; + plugin->samples = samples; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/adsr_gt", + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + NULL, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/amp.c b/src/amp.c new file mode 100644 index 0000000..4f6de84 --- /dev/null +++ b/src/amp.c @@ -0,0 +1,166 @@ +/* + An LV2 plugin representing a simple mono amplifier. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "math_func.h" +#include "uris.h" + +#define AMP_GAIN 0 +#define AMP_INPUT 1 +#define AMP_OUTPUT 2 + +typedef struct { + const float* gain; + const float* input; + float* output; + URIs uris; + uint32_t gain_is_cv; +} Amp; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Amp* plugin = (Amp*)instance; + + switch (port) { + case AMP_GAIN: + plugin->gain = (const float*)data; + break; + case AMP_INPUT: + plugin->input = (const float*)data; + break; + case AMP_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Amp* plugin = (Amp*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + + switch (o->subject) { + case AMP_GAIN: + plugin->gain_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Amp* plugin = (Amp*)malloc(sizeof(Amp)); + if (!plugin) { + return NULL; + } + + plugin->gain_is_cv = 0; + map_uris(&plugin->uris, features); + + return (LV2_Handle)plugin; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Amp* plugin = (Amp*)instance; + + /* Gain (dB) */ + const float* gain = plugin->gain; + + /* Input */ + const float* input = plugin->input; + + /* Output */ + float* output = plugin->output; + + for (uint32_t s = 0; s < sample_count; ++s) { + const float gn = gain[s * plugin->gain_is_cv]; + const float scale = (float)EXPF(M_LN10 * gn * 0.05f); + + output[s] = scale * input[s]; + } +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { NULL, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/amp", + instantiate, + connect_port, + NULL, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/branch.c b/src/branch.c new file mode 100644 index 0000000..a4de320 --- /dev/null +++ b/src/branch.c @@ -0,0 +1,223 @@ +/* + An LV2 plugin to split a signal into two. + Copyright 2011-2014 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" + +#define BRANCH_INPUT 0 +#define BRANCH_OUTPUT1 1 +#define BRANCH_OUTPUT2 2 + +typedef struct { + const float* input; + float* output1; + float* output2; + LV2_URID input_type; + URIs uris; +} Branch; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Branch* plugin = (Branch*)instance; + + switch (port) { + case BRANCH_INPUT: + plugin->input = (const float*)data; + break; + case BRANCH_OUTPUT1: + plugin->output1 = (float*)data; + break; + case BRANCH_OUTPUT2: + plugin->output2 = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Branch* plugin = (Branch*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_AudioPort && + port_type != plugin->uris.lv2_CVPort && + port_type != plugin->uris.lv2_ControlPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + switch (o->subject) { + case BRANCH_INPUT: + plugin->input_type = port_type; + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + return ret; +} + +static uint32_t +options_get(LV2_Handle instance, + LV2_Options_Option* options) +{ + const Branch* plugin = (const Branch*)instance; + uint32_t ret = 0; + for (LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT && + o->subject != BRANCH_OUTPUT1 && + o->subject != BRANCH_OUTPUT2) { + fprintf(stderr, "Bad subject %d\n", o->subject); + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + fprintf(stderr, "Bad key %d\n", o->subject); + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else { + o->size = sizeof(LV2_URID); + o->type = plugin->uris.atom_URID; + o->value = &plugin->input_type; + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Branch* plugin = (Branch*)malloc(sizeof(Branch)); + + map_uris(&plugin->uris, features); + plugin->input_type = plugin->uris.lv2_ControlPort; + + return (LV2_Handle)plugin; +} + +static void +runBranch_ia_oaoa(LV2_Handle instance, + uint32_t sample_count) +{ + Branch* plugin = (Branch*)instance; + + /* Input (array of floats of length sample_count) */ + const float* input = plugin->input; + + /* First Output (array of floats of length sample_count) */ + float* output1 = plugin->output1; + + /* Second Output (array of floats of length sample_count) */ + float* output2 = plugin->output2; + + float in; + + for (uint32_t s = 0; s < sample_count; ++s) { + in = input[s]; + + output1[s] = in; + output2[s] = in; + } +} + +static void +runBranch_ic_ococ(LV2_Handle instance, + uint32_t sample_count) +{ + Branch* plugin = (Branch*)instance; + + /* Input (float value) */ + const float input = *(plugin->input); + + /* First Output (pointer to float value) */ + float* output1 = plugin->output1; + + /* Second Output (pointer to float value) */ + float* output2 = plugin->output2; + + output1[0] = input; + output2[0] = input; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Branch* plugin = (Branch*)instance; + + if (plugin->input_type == plugin->uris.lv2_AudioPort || + plugin->input_type == plugin->uris.lv2_CVPort) { + runBranch_ia_oaoa(instance, sample_count); + } else { + runBranch_ic_ococ(instance, sample_count); + } +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { options_get, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/branch", + instantiate, + connect_port, + NULL, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/dahdsr.c b/src/dahdsr.c new file mode 100644 index 0000000..a4b9c65 --- /dev/null +++ b/src/dahdsr.c @@ -0,0 +1,416 @@ +/* + An LV2 plugin to generate DAHDSR envelopes Gate and (re)trigger + Copyright 2011 David Robillard + Copyright 2004 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "common.h" +#include "uris.h" + +#define DAHDSR_GATE 0 +#define DAHDSR_TRIGGER 1 +#define DAHDSR_DELAY 2 +#define DAHDSR_ATTACK 3 +#define DAHDSR_HOLD 4 +#define DAHDSR_DECAY 5 +#define DAHDSR_SUSTAIN 6 +#define DAHDSR_RELEASE 7 +#define DAHDSR_OUTPUT 8 + +typedef enum { + IDLE, + DELAY, + ATTACK, + HOLD, + DECAY, + SUSTAIN, + RELEASE +} DAHDSRState; + +typedef struct { + const float* gate; + const float* trigger; + const float* delay; + const float* attack; + const float* hold; + const float* decay; + const float* sustain; + const float* release; + float* output; + float srate; + float inv_srate; + float last_gate; + float last_trigger; + float from_level; + float level; + uint32_t delay_is_cv; + uint32_t attack_is_cv; + uint32_t hold_is_cv; + uint32_t decay_is_cv; + uint32_t sustain_is_cv; + uint32_t release_is_cv; + DAHDSRState state; + uint32_t samples; + URIs uris; +} Dahdsr; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Dahdsr* plugin = (Dahdsr*)instance; + + switch (port) { + case DAHDSR_GATE: + plugin->gate = (const float*)data; + break; + case DAHDSR_TRIGGER: + plugin->trigger = (const float*)data; + break; + case DAHDSR_DELAY: + plugin->delay = (const float*)data; + break; + case DAHDSR_ATTACK: + plugin->attack = (const float*)data; + break; + case DAHDSR_HOLD: + plugin->hold = (const float*)data; + break; + case DAHDSR_DECAY: + plugin->decay = (const float*)data; + break; + case DAHDSR_SUSTAIN: + plugin->sustain = (const float*)data; + break; + case DAHDSR_RELEASE: + plugin->release = (const float*)data; + break; + case DAHDSR_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Dahdsr* plugin = (Dahdsr*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + switch (o->subject) { + case DAHDSR_DELAY: + plugin->delay_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case DAHDSR_ATTACK: + plugin->attack_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case DAHDSR_HOLD: + plugin->hold_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case DAHDSR_DECAY: + plugin->decay_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case DAHDSR_SUSTAIN: + plugin->sustain_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case DAHDSR_RELEASE: + plugin->release_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Dahdsr* plugin = (Dahdsr*)malloc(sizeof(Dahdsr)); + if (!plugin) { + return NULL; + } + + plugin->srate = (float)sample_rate; + plugin->inv_srate = 1.0f / plugin->srate; + + plugin->delay_is_cv = 0; + plugin->attack_is_cv = 0; + plugin->hold_is_cv = 0; + plugin->decay_is_cv = 0; + plugin->sustain_is_cv = 0; + plugin->release_is_cv = 0; + + map_uris(&plugin->uris, features); + + return (LV2_Handle)plugin; +} + +static void +activate(LV2_Handle instance) +{ + Dahdsr* plugin = (Dahdsr*)instance; + + plugin->last_gate = 0.0f; + plugin->last_trigger = 0.0f; + plugin->from_level = 0.0f; + plugin->level = 0.0f; + plugin->state = IDLE; + plugin->samples = 0; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Dahdsr* plugin = (Dahdsr*)instance; + + /* Gate */ + const float* gate = plugin->gate; + + /* Trigger */ + const float* trigger = plugin->trigger; + + /* Delay Time (s) */ + const float* delay = plugin->delay; + + /* Attack Time (s) */ + const float* attack = plugin->attack; + + /* Hold Time (s) */ + const float* hold = plugin->hold; + + /* Decay Time (s) */ + const float* decay = plugin->decay; + + /* Sustain Level */ + const float* sustain = plugin->sustain; + + /* Release Time (s) */ + const float* release = plugin->release; + + /* Envelope Out */ + float* output = plugin->output; + + /* Instance Data */ + float srate = plugin->srate; + float inv_srate = plugin->inv_srate; + float last_gate = plugin->last_gate; + float last_trigger = plugin->last_trigger; + float from_level = plugin->from_level; + float level = plugin->level; + DAHDSRState state = plugin->state; + uint32_t samples = plugin->samples; + + float elapsed; + + for (uint32_t s = 0; s < sample_count; ++s) { + const float dl = delay[s * plugin->delay_is_cv]; + const float at = attack[s * plugin->attack_is_cv]; + const float hl = hold[s * plugin->hold_is_cv]; + const float dc = decay[s * plugin->decay_is_cv]; + const float st = sustain[s * plugin->sustain_is_cv]; + const float rl = release[s * plugin->release_is_cv]; + + /* Convert times into rates */ + const float del = dl > 0.0f ? inv_srate / dl : srate; + const float att = at > 0.0f ? inv_srate / at : srate; + const float hld = hl > 0.0f ? inv_srate / hl : srate; + const float dec = dc > 0.0f ? inv_srate / dc : srate; + const float rel = rl > 0.0f ? inv_srate / rl : srate; + + const float gat = gate[s]; + const float trg = trigger[s]; + const float sus = f_clip(st, 0.0f, 1.0f); + + /* Initialise delay phase if gate is opened and was closed, or + we received a trigger */ + if ((trg > 0.0f && !(last_trigger > 0.0f)) + || (gat > 0.0f && !(last_gate > 0.0f))) { + if (del < srate) { + state = DELAY; + } else if (att < srate) { + state = ATTACK; + } else { + state = hld < srate ? HOLD + : (dec < srate ? DECAY + : (gat > 0.0f ? SUSTAIN + : (rel < srate ? RELEASE + : IDLE))); + level = 1.0f; + } + samples = 0; + } + + /* Release if gate was open and now closed */ + if (state != IDLE && state != RELEASE + && last_gate > 0.0f && !(gat > 0.0f)) { + state = rel < srate ? RELEASE : IDLE; + samples = 0; + } + + if (samples == 0) { + from_level = level; + } + + /* Calculate level of envelope from current state */ + switch (state) { + case IDLE: + level = 0; + break; + case DELAY: + samples++; + elapsed = (float)samples * del; + if (elapsed > 1.0f) { + state = att < srate ? ATTACK + : (hld < srate ? HOLD + : (dec < srate ? DECAY + : (gat > 0.0f ? SUSTAIN + : (rel < srate ? RELEASE + : IDLE)))); + samples = 0; + } + break; + case ATTACK: + samples++; + elapsed = (float)samples * att; + if (elapsed > 1.0f) { + state = hld < srate ? HOLD + : (dec < srate ? DECAY + : (gat > 0.0f ? SUSTAIN + : (rel < srate ? RELEASE + : IDLE))); + level = 1.0f; + samples = 0; + } else { + level = from_level + elapsed * (1.0f - from_level); + } + break; + case HOLD: + samples++; + elapsed = (float)samples * hld; + if (elapsed > 1.0f) { + state = dec < srate ? DECAY + : (gat > 0.0f ? SUSTAIN + : (rel < srate ? RELEASE + : IDLE)); + samples = 0; + } + break; + case DECAY: + samples++; + elapsed = (float)samples * dec; + if (elapsed > 1.0f) { + state = gat > 0.0f ? SUSTAIN + : (rel < srate ? RELEASE + : IDLE); + level = sus; + samples = 0; + } else { + level = from_level + elapsed * (sus - from_level); + } + break; + case SUSTAIN: + level = sus; + break; + case RELEASE: + samples++; + elapsed = (float)samples * rel; + if (elapsed > 1.0f) { + state = IDLE; + level = 0.0f; + samples = 0; + } else { + level = from_level - elapsed * from_level; + } + break; + default: + /* Should never happen */ + level = 0.0f; + } + + output[s] = level; + + last_gate = gate[s]; + last_trigger = trigger[s]; + } + + plugin->last_gate = last_gate; + plugin->last_trigger = last_trigger; + plugin->from_level = from_level; + plugin->level = level; + plugin->state = state; + plugin->samples = samples; +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { NULL, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/dahdsr", + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/difference.c b/src/difference.c new file mode 100644 index 0000000..9e76e0a --- /dev/null +++ b/src/difference.c @@ -0,0 +1,188 @@ +/* + An LV2 plugin to calculate the difference of two signals. + Copyright 2011 David Robillard + Copyright 2004 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" +#include "vector_op.h" + +#define DIFFERENCE_MINUEND 0 +#define DIFFERENCE_SUBTRAHEND 1 +#define DIFFERENCE_DIFFERENCE 2 + +typedef struct { + const float* minuend; + const float* subtrahend; + float* difference; + uint32_t minuend_is_cv; + uint32_t subtrahend_is_cv; + uint32_t difference_is_cv; + URIs uris; +} Difference; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Difference* plugin = (Difference*)instance; + + switch (port) { + case DIFFERENCE_MINUEND: + plugin->minuend = (const float*)data; + break; + case DIFFERENCE_SUBTRAHEND: + plugin->subtrahend = (const float*)data; + break; + case DIFFERENCE_DIFFERENCE: + plugin->difference = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Difference* plugin = (Difference*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + switch (o->subject) { + case DIFFERENCE_MINUEND: + plugin->minuend_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case DIFFERENCE_SUBTRAHEND: + plugin->subtrahend_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + plugin->difference_is_cv = plugin->minuend_is_cv || plugin->subtrahend_is_cv; + return ret; +} + +static uint32_t +options_get(LV2_Handle instance, + LV2_Options_Option* options) +{ + const Difference* plugin = (const Difference*)instance; + uint32_t ret = 0; + for (LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT || + o->subject != DIFFERENCE_DIFFERENCE) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else { + o->size = sizeof(LV2_URID); + o->type = plugin->uris.atom_URID; + o->value = (plugin->difference_is_cv + ? &plugin->uris.lv2_CVPort + : &plugin->uris.lv2_ControlPort); + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Difference* plugin = (Difference*)malloc(sizeof(Difference)); + if (!plugin) { + return NULL; + } + + plugin->minuend_is_cv = 0; + plugin->subtrahend_is_cv = 0; + plugin->difference_is_cv = 0; + + map_uris(&plugin->uris, features); + + return (LV2_Handle)plugin; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + const Difference* const plugin = (Difference*)instance; + const float* const minuend = plugin->minuend; + const float* const subtrahend = plugin->subtrahend; + float* const difference = plugin->difference; + + VECTOR_OP(-, difference, + minuend, plugin->minuend_is_cv, + subtrahend, plugin->subtrahend_is_cv); +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { options_get, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/difference", + instantiate, + connect_port, + NULL, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/fmod.c b/src/fmod.c new file mode 100644 index 0000000..9284d9d --- /dev/null +++ b/src/fmod.c @@ -0,0 +1,199 @@ +/* + An LV2 plugin to modulate a frequency by a signal. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "math_func.h" +#include "uris.h" + +#define FMOD_FREQUENCY 0 +#define FMOD_MODULATOR 1 +#define FMOD_OUTPUT 2 + +typedef struct { + const float* frequency; + const float* modulator; + float* output; + uint32_t frequency_is_cv; + uint32_t modulator_is_cv; + uint32_t output_is_cv; + URIs uris; +} Fmod; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Fmod* plugin = (Fmod*)instance; + + switch (port) { + case FMOD_FREQUENCY: + plugin->frequency = (const float*)data; + break; + case FMOD_MODULATOR: + plugin->modulator = (const float*)data; + break; + case FMOD_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Fmod* plugin = (Fmod*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + + switch (o->subject) { + case FMOD_FREQUENCY: + plugin->frequency_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case FMOD_MODULATOR: + plugin->modulator_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + return ret; +} + +static uint32_t +options_get(LV2_Handle instance, + LV2_Options_Option* options) +{ + const Fmod* plugin = (const Fmod*)instance; + uint32_t ret = 0; + for (LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT || o->subject != FMOD_OUTPUT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else { + o->size = sizeof(LV2_URID); + o->type = plugin->uris.atom_URID; + o->value = (plugin->output_is_cv + ? &plugin->uris.lv2_CVPort + : &plugin->uris.lv2_ControlPort); + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Fmod* plugin = (Fmod*)malloc(sizeof(Fmod)); + + if (plugin) { + plugin->frequency_is_cv = 0; + plugin->modulator_is_cv = 0; + plugin->output_is_cv = 0; + map_uris(&plugin->uris, features); + } + + return (LV2_Handle)plugin; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Fmod* plugin = (Fmod*)instance; + + /* Frequency to Modulate (array of floats of length 1 or sample_count) */ + const float* frequency = plugin->frequency; + + /* LFO Input (array of floats of length 1 or sample_count) */ + const float* modulator = plugin->modulator; + + /* Output Frequency (array of floats of length 1 or sample_count) */ + float* output = plugin->output; + + if (!plugin->output_is_cv) { /* TODO: Avoid this branch */ + sample_count = 1; + } + + for (uint32_t s = 0; s < sample_count; ++s) { + const float freq = frequency[s * plugin->frequency_is_cv]; + const float mod = modulator[s * plugin->modulator_is_cv]; + const float scale = (float)EXPF(M_LN2 * mod); + + output[s] = scale * freq; + } +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { options_get, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/fmod", + instantiate, + connect_port, + NULL, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/include/common.h b/src/include/common.h new file mode 100644 index 0000000..26a405a --- /dev/null +++ b/src/include/common.h @@ -0,0 +1,54 @@ +/* + Common definitions. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef blop_common_h +#define blop_common_h + +#include "math_func.h" + +/* Handy constants and macros */ + +#ifndef SMALLEST_FLOAT +/** Smallest generated non-zero float, used for pre-empting denormals */ +#define SMALLEST_FLOAT (1.0 / (float)0xFFFFFFFF) +#endif + +/* + * Clip without branch (from http://musicdsp.org) + */ + +static inline float +f_min (float x, float a) +{ + return a - (a - x + FABSF (a - x)) * 0.5f; +} + +static inline float +f_max (float x, float b) +{ + return (x - b + FABSF (x - b)) * 0.5f + b; +} + +static inline float +f_clip (float x, float a, float b) +{ + return 0.5f * (FABSF (x - a) + a + b - FABSF (x - b)); +} + +#endif /* blop_common_h */ diff --git a/src/include/interpolate.h b/src/include/interpolate.h new file mode 100644 index 0000000..237008c --- /dev/null +++ b/src/include/interpolate.h @@ -0,0 +1,74 @@ +#ifndef blop_interpolate_h +#define blop_interpolate_h + +#include "blop_config.h" +#include "math_func.h" + +/** + Interpolate between p0 and n0 taking the previous (p1) and next (n1) points + into account, using a 3rd order polynomial (a.k.a. cubic spline). + @param interval Normalised time interval between intepolated sample and p0 + @param p1 Sample two previous to interpolated one + @param p0 Previous sample to interpolated one + @param n0 Sample following interpolated one + @param n1 Sample following n0 + @return Interpolated sample. + + Adapted from Steve Harris' plugin code + swh-plugins-0.2.7/ladspa-util.h::cube_interp + http://plugin.org.uk/releases/0.2.7/ +*/ +static inline float +interpolate_cubic(float interval, + float p1, + float p0, + float n0, + float n1) +{ + return p0 + 0.5f * interval * (n0 - p1 + + interval * (4.0f * n0 + 2.0f * p1 - 5.0f * p0 - n1 + + interval * (3.0f * (p0 - n0) - p1 + n1))); +} + +/** + Interpolate between p0 and n0 taking the previous (p1) and next (n1) points + into account, using a 5th order polynomial. + @param interval Normalised time interval between intepolated sample and p0 + @param p1 Sample two previous to interpolated one + @param p0 Previous sample to interpolated one + @param n0 Sample following interpolated one + @param n1 Sample following n0 + @return Interpolated sample. + + Adapted from http://www.musicdsp.org/archive.php?classid=5#62 +*/ +static inline float +interpolate_quintic(float interval, + float p1, + float p0, + float n0, + float n1) +{ + return p0 + 0.5f * interval * (n0 - p1 + + interval * (n0 - 2.0f * p0 + p1 + + interval * ( 9.0f * (n0 - p0) + 3.0f * (p1 - n1) + + interval * (15.0f * (p0 - n0) + 5.0f * (n1 - p1) + + interval * ( 6.0f * (n0 - p0) + 2.0f * (p1 - n1)))))); +} + +/** + Linear interpolation +*/ +static inline float +f_lerp (float value, + float v1, + float v2) +{ + value -= LRINTF (value - 0.5f); + value *= (v2 - v1); + value += v1; + + return value; +} + +#endif /* blop_interpolate_h */ diff --git a/src/include/lp4pole_filter.h b/src/include/lp4pole_filter.h new file mode 100644 index 0000000..310fbbe --- /dev/null +++ b/src/include/lp4pole_filter.h @@ -0,0 +1,137 @@ +/* + Header for lp4pole_filter struct, and functions to run instance. + Copyright 2011 David Robillard + Copyright 2003 Mike Rawes + + Originally originally appeared in CSound as Timo Tossavainen's (sp?) + implementation from the Stilson/Smith CCRMA paper. + + See http://musicdsp.org/archive.php?classid=3#26 + + Originally appeared in the arts softsynth by Stefan Westerfeld: + http://www.arts-project.org/ + + First ported to LADSPA by Reiner Klenk (pdq808[at]t-online.de) + + Tuning and stability issues (output NaN) and additional audio-rate + variant added by Mike Rawes (mike_rawes[at]yahoo.co.uk) + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef blop_lp4pole_filter_h +#define blop_lp4pole_filter_h + +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "common.h" + +typedef struct { + float f; + float coeff; + float fb; + float in1; + float in2; + float in3; + float in4; + float inv_nyquist; + float out1; + float out2; + float out3; + float out4; + float max_abs_in; +} LP4PoleFilter; + +/** + Allocate a new LP4PoleFilter instance. + @param sample_rate Intended playback (DAC) rate + @return Allocated LP4PoleFilter instance +*/ +LP4PoleFilter* lp4pole_new(double sample_rate); + +/** + Cleanup an existing LP4PoleFilter instance. + @param lpf Pointer to LP4PoleFilter instance allocated with initFilter +*/ +void lp4pole_cleanup(LP4PoleFilter* lpf); + +/** + Initialise filter. + @param lpf Pointer to LP4PoleFilter instance allocated with initFilter +*/ +void lp4pole_init(LP4PoleFilter* lpf); + +/** + Set up filter coefficients for given LP4Pole instance. + @param lpf Pointer to LP4PoleFilter instance + @param cutoff Cutoff frequency in Hz + @param resonance Resonance [Min=0.0, Max=4.0] +*/ +static inline void +lp4pole_set_params(LP4PoleFilter* lpf, + float cutoff, + float resonance) +{ + float fsqd; + float tuning; + + /* Normalise cutoff and find tuning - Magic numbers found empirically :) */ + lpf->f = cutoff * lpf->inv_nyquist; + tuning = f_clip(3.13f - (lpf->f * 4.24703592f), 1.56503274f, 3.13f); + + /* Clip to bounds */ + lpf->f = f_clip(lpf->f * tuning, lpf->inv_nyquist, 1.16f); + + fsqd = lpf->f * lpf->f; + lpf->coeff = fsqd * fsqd * 0.35013f; + + lpf->fb = f_clip(resonance, -1.3f, 4.0f) * (1.0f - 0.15f * fsqd); + + lpf->f = 1.0f - lpf->f; +} + +/** + Run given LP4PoleFilter instance for a single sample. + @param lpf Pointer to LP4PoleFilter instance + @param in Input sample + @return Filtered sample +*/ +static inline float +lp4pole_run(LP4PoleFilter* lpf, + float in) +{ + const float abs_in = fabsf(16.0f * in); /* ~24dB unclipped headroom */ + + lpf->max_abs_in = f_max(lpf->max_abs_in, abs_in); + + in -= lpf->out4 * lpf->fb; + in *= lpf->coeff; + + lpf->out1 = in + 0.3f * lpf->in1 + lpf->f * lpf->out1; /* Pole 1 */ + lpf->in1 = in; + lpf->out2 = lpf->out1 + 0.3f * lpf->in2 + lpf->f * lpf->out2; /* Pole 2 */ + lpf->in2 = lpf->out1; + lpf->out3 = lpf->out2 + 0.3f * lpf->in3 + lpf->f * lpf->out3; /* Pole 3 */ + lpf->in3 = lpf->out2; + lpf->out4 = lpf->out3 + 0.3f * lpf->in4 + lpf->f * lpf->out4; /* Pole 4 */ + lpf->in4 = lpf->out3; + + /* Simple hard clip to prevent NaN */ + lpf->out4 = f_clip(lpf->out4, -lpf->max_abs_in, lpf->max_abs_in); + + lpf->max_abs_in *= 0.999f; + + return lpf->out4; +} + +#endif /* blop_lp4pole_filter_h */ diff --git a/src/include/math_func.h b/src/include/math_func.h new file mode 100644 index 0000000..60f7ce0 --- /dev/null +++ b/src/include/math_func.h @@ -0,0 +1,48 @@ +/* + * Provide double fallbacks for environments lacking sinf and + * friends (e.g. Solaris) + */ + +#ifndef math_func_h +#define math_func_h + +#include <math.h> +#include "blop_config.h" + +#ifndef M_PI +# define M_PI 3.14159265358979323846 /* pi */ +#endif + +#ifndef M_LN10 +# define M_LN10 2.30258509299404568402 /* log_e(10) */ +#endif + +#ifndef M_LN2 +# define M_LN2 0.69314718055994530942 /* log_e(2) */ +#endif + +#ifdef HAVE_SINF +/* Use float functions */ +#define SINF(x) sinf(x) +#define COSF(x) cosf(x) +#define FABSF(x) fabsf(x) +#define FLOORF(x) floorf(x) +#define EXPF(x) expf(x) +#define POWF(x,p) powf(x,p) +#define COPYSIGNF(s,d) copysignf(s,d) +#define LRINTF(x) lrintf(x) + +#else +/* Use double functions */ +#define SINF(x) sin(x) +#define COSF(x) cos(x) +#define FABSF(x) fabs(x) +#define FLOORF(x) floor(x) +#define EXPF(x) exp(x) +#define POWF(x,p) pow(x) +#define COPYSIGNF(s,d) copysign(s,d) +#define LRINTF(x) lrint(x) + +#endif + +#endif diff --git a/src/include/uris.h b/src/include/uris.h new file mode 100644 index 0000000..0c35628 --- /dev/null +++ b/src/include/uris.h @@ -0,0 +1,59 @@ +/* + Common URIs used by plugins. + Copyright 2012 David Robillard + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef blop_uris_h +#define blop_uris_h + +#include <string.h> +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/urid/urid.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" + +typedef struct { + LV2_URID atom_URID; + LV2_URID lv2_AudioPort; + LV2_URID lv2_CVPort; + LV2_URID lv2_ControlPort; + LV2_URID morph_currentType; +} URIs; + +static inline void +map_uris(URIs* uris, + const LV2_Feature* const* features) +{ + LV2_URID_Map* map = NULL; + for (int i = 0; features[i]; ++i) { + if (!strcmp(features[i]->URI, LV2_URID__map)) { + map = (LV2_URID_Map*)features[i]->data; + break; + } + } + + if (map) { + uris->atom_URID = map->map(map->handle, LV2_ATOM__URID); + uris->lv2_AudioPort = map->map(map->handle, LV2_CORE__AudioPort); + uris->lv2_CVPort = map->map(map->handle, LV2_CORE__CVPort); + uris->lv2_ControlPort = map->map(map->handle, LV2_CORE__ControlPort); + uris->morph_currentType = map->map(map->handle, LV2_MORPH__currentType); + } else { + memset(uris, 0, sizeof(*uris)); + } +} + +#endif /* blop_uris_h */ diff --git a/src/include/vector_op.h b/src/include/vector_op.h new file mode 100644 index 0000000..f261ff8 --- /dev/null +++ b/src/include/vector_op.h @@ -0,0 +1,44 @@ +/* + Apply a C arithmetical operator to two sample buffers. + Copyright 2012-2014 David Robillard + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef BLOP_VECTOR_OP_H +#define BLOP_VECTOR_OP_H + +#define VECTOR_OP(op, output, input1, input1_is_cv, input2, input2_is_cv) \ + switch ((input1_is_cv << 1) + input2_is_cv) { \ + case 0: /* 00 (control * control) */ \ + output[0] = input1[0] op input2[0]; \ + break; \ + case 1: /* 01 (control * cv) */ \ + for (uint32_t s = 0; s < sample_count; ++s) { \ + output[s] = input1[0] op input2[s]; \ + } \ + break; \ + case 2: /* 10 (cv * control) */ \ + for (uint32_t s = 0; s < sample_count; ++s) { \ + output[s] = input1[s] op input2[0]; \ + } \ + break; \ + case 3: /* 11 (cv * cv) */ \ + for (uint32_t s = 0; s < sample_count; ++s) { \ + output[s] = input1[s] op input2[s]; \ + } \ + break; \ + } + +#endif /* BLOP_VECTOR_OP_H */ diff --git a/src/include/wavedata.h b/src/include/wavedata.h new file mode 100644 index 0000000..97b2986 --- /dev/null +++ b/src/include/wavedata.h @@ -0,0 +1,193 @@ +/* + Structures to represent a set of wavetables. + Copyright 2011 David Robillard + Copyright 2003 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef blop_wavedata_h +#define blop_wavedata_h + +#include "blop_config.h" +#include "math_func.h" +#include "interpolate.h" +#include "common.h" + +/* Functions identifying wavedata dlls */ +#define BLOP_DLSYM_SAWTOOTH "blop_get_sawtooth" +#define BLOP_DLSYM_SQUARE "blop_get_square" +#define BLOP_DLSYM_PARABOLA "blop_get_parabola" + +/* + * Structure holding a single segment of sample data + * along with information relating to playback. + */ +typedef struct { + unsigned long sample_count; /* Sample count */ + float* samples_lf; /* Sample data played back at amplitude + inversely proportional to frequency */ + float* samples_hf; /* Sample data played back at amplitude + proportional to frequency */ + unsigned long harmonics; /* Max harmonic content of sample data */ + + float phase_scale_factor; /* Phase scale factor for playback */ + float min_frequency; /* Minimum playback frequency */ + float max_frequency; /* Maximum playback frequency */ + float range_scale_factor; /* Blend scale factor for cross fading */ +} Wavetable; + +/* + * Structure holding the wavetable data and playback state + */ +typedef struct { + void* data_handle; /* Data DLL handle */ + unsigned long table_count; /* Number of wavetables in wavedata */ + Wavetable** tables; /* One or more wavetables, plus pair of + extra tables for frequency extremes */ + unsigned long* lookup; /* Wavetable lookup vector */ + unsigned long lookup_max; /* For clipping lookup indices */ + + float sample_rate; /* Sample rate */ + float nyquist; /* Nyquist rate (sample_rate / 2) */ + + /* Playback state */ + float frequency; /* Current playback frequency */ + float abs_freq; /* Absolute playback frequency */ + float xfade; /* Crossfade factor for fading */ + Wavetable* table; /* Wavetable to playback */ +} Wavedata; + +#ifdef __cplusplus +extern "C" { +#endif + +int wavedata_load(Wavedata* w, + const char* bundle_path, + const char* lib_name, + const char* wdat_descriptor_name, + double sample_rate); + +void wavedata_unload(Wavedata* w); + +/***************************************************************************** + * Description: Get interpolated sample from current wavetable in wavedata + * at given phase offset + * + * Arguments: w Wavedata containing playback state and data + * phase Phase offset [0.0, sample_rate] + * + * Returns: Interpolated sample + * + * Notes: Cubic (or quintic) interpolation requires four consecutive + * samples for operation: + * + * phase + * : + * p1 p0 : n0 n1 + * | | x | | + * : : + * <-o-> + * : + * interval + * + * Phase values less than one make p0 the first sample in + * the table - p1 will be the last sample, as a previous + * sample does not exist. To avoid checking for this case, + * a copy of the last sample is stored before the first + * sample in each table. + * Likewise, if the phase means p0 is the last sample, n0 + * and n1 will be the first and second samples respectively. + * Copies of these samples are stored after the last sample + * in each table. + * + *****************************************************************************/ +static inline float +wavedata_get_sample(Wavedata* w, + float phase) +{ + float* samples_hf = w->table->samples_hf; + float* samples_lf = w->table->samples_lf; + float p1, p0, n0, n1; + float phase_f; + long int index; + + /* Scale phase to map to position in wavetable */ + phase *= w->table->phase_scale_factor; + + /* Get position of first contributing sample (p1) */ + index = LRINTF((float)phase - 0.5f); + phase_f = (float)index; + + index %= w->table->sample_count; + + /* Cross-fade table pairs */ + /* Previous two samples */ + p1 = w->xfade * (samples_lf[index] - samples_hf[index]) + samples_hf[index]; + index++; + p0 = w->xfade * (samples_lf[index] - samples_hf[index]) + samples_hf[index]; + index++; + /* Next two samples */ + n0 = w->xfade * (samples_lf[index] - samples_hf[index]) + samples_hf[index]; + index++; + n1 = w->xfade * (samples_lf[index] - samples_hf[index]) + samples_hf[index]; + + /* Return interpolated sample */ + return interpolate_cubic(phase - phase_f, p1, p0, n0, n1); +} + +/***************************************************************************** + * Description: Get wavetable to use for playback frequency. + * + * Arguments: w Wavedata object (contains all table info) + * frequency Playback frequency + * + * Notes: The lookup vector used to determine the wavetable + * is indexed by harmonic number. + * + * The maximum playback frequency for a wavetable is + * determined by its harmonic content and the sample rate, + * and equals sample_rate / 2 / max_harmonic_in_table. + * + *****************************************************************************/ +static inline void +wavedata_get_table(Wavedata* w, + float frequency) +{ + unsigned long harmonic; + + w->frequency = frequency; + w->abs_freq = (float)FABSF((float)frequency); + + /* Get highest harmonic possible in frequency */ + harmonic = LRINTF(w->nyquist / w->abs_freq - 0.5f); + + /* Clip so lookup is within bounds */ + if (harmonic > w->lookup_max) { + harmonic = w->lookup_max; + } + + /* Set playback table */ + w->table = w->tables[w->lookup[harmonic]]; + + /* Get cross fade factor */ + w->xfade = f_max(w->table->max_frequency - w->abs_freq, 0.0f) * w->table->range_scale_factor; + w->xfade = f_min(w->xfade, 1.0f); +} + +#ifdef __cplusplus +} /* extern "C" { */ +#endif + +#endif /* blop_wavedata_h */ diff --git a/src/include/wdatutil.h b/src/include/wdatutil.h new file mode 100644 index 0000000..9a0810a --- /dev/null +++ b/src/include/wdatutil.h @@ -0,0 +1,141 @@ +/* + Code to generate wavedata dl containing pre-calculated wavetables. + Copyright 2011 David Robillard + Copyright 2003 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef blop_wdatutil_h +#define blop_wdatutil_h + +#include <stdio.h> +#include <stdint.h> +#include "math_func.h" +#include "wavedata.h" + +#define WAVE_TYPE_COUNT 3 + +extern const char* wave_names[]; +extern const char* wave_descriptions[]; +extern unsigned long wave_first_harmonics[]; +extern unsigned long wave_harmonic_intervals[]; + +/** Get actual maximum harmonic from given harmonic, h, and wavetype, w */ +#define ACTUAL_HARM(h, w) h - (h - wave_first_harmonics[w]) % wave_harmonic_intervals[w] + +/** Get minimum harmonic content in given wavetype, w */ +#define MIN_HARM(w) wave_first_harmonics[w] + +/** Get minimum extra harmonic content possible in given wavetype, w */ +#define MIN_EXTRA_HARM(w) wave_harmonic_intervals[w] + +/** Get frequency from MIDI note, n */ +#define FREQ_FROM_NOTE(n) 6.875f * POWF(2.0f, (float)(n + 3) / 12.0f) + +/** Get max harmonic from given frequency, f, at sample rate, r */ +#define HARM_FROM_FREQ(f, r) (unsigned long)((float)r / f / 2.0f) + +/* + * A single wavetable will have a range of pitches at which their samples + * may be played back. + * + * The upper bound is determined by the maximum harmonic present in the + * waveform - above this frequency, the higher harmonics will alias. + * + * The lower bound is chosen to be the higher bound of the previous wavetable + * (or a pre-defined limit if there is no such table). + */ + +typedef enum { + SAW, + SQUARE, + PARABOLA +} Wavetype; + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************* + * Description: Allocate new wavedata struct + * + * Arguments: sample_rate Sample rate to use when generating data + * + * Returns: Pointer to wavedata on success + * NULL (0) on failure + * + * Notes: No wavetables are allocated. Use wavedata_add_table + ******************************************************************************/ +Wavedata* wavedata_new(double sample_rate); + +/******************************************************************************* + * Description: Destroy allocated wavedata and any tables + * + * Arguments: w Wavedata struct to cleanup + ******************************************************************************/ +void wavedata_cleanup(Wavedata* w); + +/******************************************************************************* + * Description: Add new wavetable information to wavedata file object + * + * Arguments: w Wavedata to add table to + * sample_count Number of samples in wavetable + * harmonics Maximum harmonics present in table + * + * Returns: 0 on success + * -1 otherwise + ******************************************************************************/ +int wavedata_add_table(Wavedata* w, + uint32_t sample_count, + unsigned long harmonics); + +/******************************************************************************* + * Description: Initialise all wavetables in wavedata with a waveform + * generated from Fourier series. + * + * Arguments: w Wavedata to generate data for + * wavetype Wavetype to generate + * gibbs_comp Compensation for Gibbs' effect: + * 0.0: none (wave will overshoot) + * 1.0: full (wave will not overshoot) + * + * Notes: Compensation for Gibbs' Effect will reduce the degree + * of overshoot and ripple at the transitions. A value of 1.0 + * will pretty much eliminate it. + ******************************************************************************/ +void wavedata_generate_tables(Wavedata* w, + Wavetype wavetype, + float gibbs_comp); + +/******************************************************************************* + * Description: Write wavedata as a c header file + * + * Arguments: w Wavedata to write + * wdat_fp Pointer to output file + * prefix Prefix to use in declarations. If this is null + * declarations are prefixed with 'wdat'. + * + * Returns: 0 on success + * -1 otherwise + ******************************************************************************/ +int wavedata_write(Wavedata* w, + FILE* wdat_fp, + const char* prefix); + +#ifdef __cplusplus +} /* extern "C" { */ +#endif + +#endif /* blop_wdatutil_h */ diff --git a/src/interpolator.c b/src/interpolator.c new file mode 100644 index 0000000..e47fbe3 --- /dev/null +++ b/src/interpolator.c @@ -0,0 +1,144 @@ +/* + An LV2 plugin to generate a smooth audio signal from a control source. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" + +#define INTERPOLATOR_INPUT 0 +#define INTERPOLATOR_OUTPUT 1 + +/** + Mutated spline interpolator using only two previous samples and one next. + @param interval Normalised time interval between inteprolated sample and p0 + @param p1 Sample two previous to interpolated one + @param p0 Previous sample to interpolated one + @param n0 Sample following interpolated one + @return Interpolated sample. +*/ +static inline float +interpolate(float interval, + float p1, + float p0, + float n0) +{ + return p0 + 0.5f * interval * (n0 - p1 + + interval * (4.0f * n0 + 2.0f * p1 - 5.0f * p0 - n0 + + interval * (3.0f * (p0 - n0) - p1 + n0))); +} + +typedef struct { + const float* input; + float* output; + float p1; + float p0; +} Interpolator; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Interpolator* plugin = (Interpolator*)instance; + + switch (port) { + case INTERPOLATOR_INPUT: + plugin->input = (const float*)data; + break; + case INTERPOLATOR_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Interpolator* plugin = (Interpolator*)malloc(sizeof(Interpolator)); + if (!plugin) { + return NULL; + } + + return (LV2_Handle)plugin; +} + +static void +activate(LV2_Handle instance) +{ + Interpolator* plugin = (Interpolator*)instance; + + plugin->p1 = 0.0f; + plugin->p0 = 0.0f; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Interpolator* plugin = (Interpolator*)instance; + + /* Control Input (float value) */ + const float input = *(plugin->input); + + /* Interpolated Output (pointer to float value) */ + float* output = plugin->output; + + /* We use two previous values and the input as the 'next' one */ + float p1 = plugin->p1; + float p0 = plugin->p0; + + const float inv_scount = 1.0f / (float)sample_count; + + for (uint32_t s = 0; s < sample_count; ++s) { + const float interval = (float)s * inv_scount; + + output[s] = interpolate(interval, p1, p0, input); + } + + plugin->p1 = p0; + plugin->p0 = input; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/interpolator", + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + NULL, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/lp4pole.c b/src/lp4pole.c new file mode 100644 index 0000000..7d2eb6b --- /dev/null +++ b/src/lp4pole.c @@ -0,0 +1,206 @@ +/* + An LV2 plugin simulating a 4 pole low pass resonant filter. + Copyright 2011 David Robillard + Copyright 2003 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "lp4pole_filter.h" +#include "common.h" +#include "uris.h" + +#define LP4POLE_CUTOFF 0 +#define LP4POLE_RESONANCE 1 +#define LP4POLE_INPUT 2 +#define LP4POLE_OUTPUT 3 + +typedef struct { + const float* cutoff; + const float* resonance; + const float* input; + float* output; + LP4PoleFilter* lpf; + uint32_t cutoff_is_cv; + uint32_t resonance_is_cv; + URIs uris; +} Lp4pole; + +static void +cleanup(LV2_Handle instance) +{ + Lp4pole* plugin = (Lp4pole*)instance; + + lp4pole_cleanup(plugin->lpf); + + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Lp4pole* plugin = (Lp4pole*)instance; + + switch (port) { + case LP4POLE_CUTOFF: + plugin->cutoff = (const float*)data; + break; + case LP4POLE_RESONANCE: + plugin->resonance = (const float*)data; + break; + case LP4POLE_INPUT: + plugin->input = (const float*)data; + break; + case LP4POLE_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Lp4pole* plugin = (Lp4pole*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + + switch (o->subject) { + case LP4POLE_CUTOFF: + plugin->cutoff_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case LP4POLE_RESONANCE: + plugin->resonance_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Lp4pole* plugin = (Lp4pole*)malloc(sizeof(Lp4pole)); + + if (plugin) { + plugin->lpf = lp4pole_new(sample_rate); + if (!plugin->lpf) { + free(plugin); + return NULL; + } + plugin->cutoff_is_cv = 0; + plugin->resonance_is_cv = 0; + map_uris(&plugin->uris, features); + } + + return (LV2_Handle)plugin; +} + +static void +activate(LV2_Handle instance) +{ + Lp4pole* plugin = (Lp4pole*)instance; + + lp4pole_init(plugin->lpf); +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Lp4pole* plugin = (Lp4pole*)instance; + + /* Cutoff Frequency (array of floats of length 1 or sample_count) */ + const float* cutoff = plugin->cutoff; + + /* Resonance (array of floats of length 1 or sample_count) */ + const float* resonance = plugin->resonance; + + /* Input (array of floats of length sample_count) */ + const float* input = plugin->input; + + /* Output (pointer to float value) */ + float* output = plugin->output; + + /* Instance data */ + LP4PoleFilter* lpf = plugin->lpf; + + for (uint32_t s = 0; s < sample_count; ++s) { + const float co = cutoff[s * plugin->cutoff_is_cv]; + const float res = resonance[s * plugin->resonance_is_cv]; + const float in = input[s]; + + /* TODO: There is no branching in this function. + Would it actually be faster to check if co or res has changed? + */ + lp4pole_set_params(lpf, co, res); + + output[s] = lp4pole_run(lpf, in); + } +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { NULL, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/lp4pole", + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/lp4pole_filter.c b/src/lp4pole_filter.c new file mode 100644 index 0000000..7d54691 --- /dev/null +++ b/src/lp4pole_filter.c @@ -0,0 +1,55 @@ +/* + lp4pole filter admin. + Copyright 2011 David Robillard + Copyright 2003 Mike Rawes + + See lp4pole_filter.h for history + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "lp4pole_filter.h" + +LP4PoleFilter* +lp4pole_new(double sample_rate) +{ + LP4PoleFilter* lpf; + + lpf = (LP4PoleFilter*)malloc(sizeof(LP4PoleFilter)); + + if (lpf) { + lpf->inv_nyquist = 2.0f / sample_rate; + lp4pole_init(lpf); + } + + return lpf; +} + +void +lp4pole_cleanup(LP4PoleFilter* lpf) +{ + if (lpf) { + free(lpf); + } +} + +void +lp4pole_init(LP4PoleFilter* lpf) +{ + lpf->in1 = lpf->in2 = lpf->in3 = lpf->in4 = 0.0f; + lpf->out1 = lpf->out2 = lpf->out3 = lpf->out4 = 0.0f; + lpf->max_abs_in = 0.0f; +} diff --git a/src/product.c b/src/product.c new file mode 100644 index 0000000..007d853 --- /dev/null +++ b/src/product.c @@ -0,0 +1,187 @@ +/* + An LV2 plugin to calculate the product of two signals. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" +#include "vector_op.h" + +#define PRODUCT_MULTIPLICAND 0 +#define PRODUCT_MULTIPLIER 1 +#define PRODUCT_PRODUCT 2 + +typedef struct { + const float* input1; + const float* input2; + float* output; + uint32_t input1_is_cv; + uint32_t input2_is_cv; + uint32_t output_is_cv; + URIs uris; +} Product; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Product* plugin = (Product*)instance; + + switch (port) { + case PRODUCT_MULTIPLICAND: + plugin->input1 = (const float*)data; + break; + case PRODUCT_MULTIPLIER: + plugin->input2 = (const float*)data; + break; + case PRODUCT_PRODUCT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Product* plugin = (Product*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + switch (o->subject) { + case PRODUCT_MULTIPLICAND: + plugin->input1_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case PRODUCT_MULTIPLIER: + plugin->input2_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + plugin->output_is_cv = plugin->input1_is_cv || plugin->input2_is_cv; + return ret; +} + +static uint32_t +options_get(LV2_Handle instance, + LV2_Options_Option* options) +{ + const Product* plugin = (const Product*)instance; + uint32_t ret = 0; + for (LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT || o->subject != PRODUCT_PRODUCT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else { + o->size = sizeof(LV2_URID); + o->type = plugin->uris.atom_URID; + o->value = (plugin->output_is_cv + ? &plugin->uris.lv2_CVPort + : &plugin->uris.lv2_ControlPort); + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Product* plugin = (Product*)malloc(sizeof(Product)); + if (!plugin) { + return NULL; + } + + plugin->input1_is_cv = 0; + plugin->input2_is_cv = 0; + plugin->output_is_cv = 0; + + map_uris(&plugin->uris, features); + + return (LV2_Handle)plugin; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + const Product* const plugin = (Product*)instance; + const float* const input1 = plugin->input1; + const float* const input2 = plugin->input2; + float* const output = plugin->output; + + VECTOR_OP(*, output, + input1, plugin->input1_is_cv, + input2, plugin->input2_is_cv); +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { options_get, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/product", + instantiate, + connect_port, + NULL, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/pulse.c b/src/pulse.c new file mode 100644 index 0000000..29e1001 --- /dev/null +++ b/src/pulse.c @@ -0,0 +1,225 @@ +/* + An LV2 plugin to generate a bandlimited variable pulse waveform. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" +#include "wavedata.h" + +#define PULSE_FREQUENCY 0 +#define PULSE_PULSEWIDTH 1 +#define PULSE_OUTPUT 2 + +typedef struct { + const float* frequency; + const float* pulsewidth; + float* output; + float phase; + uint32_t frequency_is_cv; + uint32_t pulsewidth_is_cv; + Wavedata wdat; + URIs uris; +} Pulse; + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Pulse* plugin = (Pulse*)instance; + + switch (port) { + case PULSE_FREQUENCY: + plugin->frequency = (const float*)data; + break; + case PULSE_PULSEWIDTH: + plugin->pulsewidth = (const float*)data; + break; + case PULSE_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Pulse* plugin = (Pulse*)malloc(sizeof(Pulse)); + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + + switch (o->subject) { + case PULSE_FREQUENCY: + plugin->frequency_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case PULSE_PULSEWIDTH: + plugin->pulsewidth_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Pulse* plugin = (Pulse*)malloc(sizeof(Pulse)); + if (!plugin) { + return NULL; + } + + if (wavedata_load(&plugin->wdat, bundle_path, "sawtooth_data", + BLOP_DLSYM_SAWTOOTH, sample_rate)) { + free(plugin); + return 0; + } + + plugin->frequency_is_cv = 0; + plugin->pulsewidth_is_cv = 0; + map_uris(&plugin->uris, features); + wavedata_get_table(&plugin->wdat, 440.0); + + return (LV2_Handle)plugin; +} + +static void +cleanup(LV2_Handle instance) +{ + Pulse* plugin = (Pulse*)instance; + + wavedata_unload(&plugin->wdat); + free(instance); +} + +static void +activate(LV2_Handle instance) +{ + Pulse* plugin = (Pulse*)instance; + + plugin->phase = 0.0f; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Pulse* plugin = (Pulse*)instance; + + /* Frequency (array of float of length sample_count) */ + const float* frequency = plugin->frequency; + + /* Pulse Width (array of float of length sample_count) */ + const float* pulsewidth = plugin->pulsewidth; + + /* Output (pointer to float value) */ + float* output = plugin->output; + + /* Instance data */ + Wavedata* wdat = &plugin->wdat; + float phase = plugin->phase; + + float last_pwidth = pulsewidth[0]; + float pwidth = f_clip(last_pwidth, 0.0f, 1.0f); + float dc_shift = 1.0 - (2.0 * pwidth); + float phase_shift = pwidth * wdat->sample_rate; + + for (uint32_t s = 0; s < sample_count; ++s) { + const float freq = frequency[s * plugin->frequency_is_cv]; + if (freq != wdat->frequency) { + /* Frequency changed, look up table to play */ + wavedata_get_table(wdat, freq); + } + + const float this_pwidth = pulsewidth[s * plugin->pulsewidth_is_cv]; + if (this_pwidth != last_pwidth) { + /* Pulsewidth changed, recalculate */ + last_pwidth = this_pwidth; + pwidth = f_clip(this_pwidth, 0.0f, 1.0f); + dc_shift = 1.0f - (2.0f * pwidth); + phase_shift = pwidth * wdat->sample_rate; + } + + /* Get samples from sawtooth and phase shifted inverted sawtooth, + with approriate DC offset */ + output[s] = wavedata_get_sample(wdat, phase) + - wavedata_get_sample(wdat, phase + phase_shift) + + dc_shift; + + /* Update phase, wrapping if necessary */ + phase += wdat->frequency; + if (phase < 0.0f) { + phase += wdat->sample_rate; + } else if (phase > wdat->sample_rate) { + phase -= wdat->sample_rate; + } + } + plugin->phase = phase; +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { NULL, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/pulse", + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/quantiser.c b/src/quantiser.c new file mode 100644 index 0000000..ed3ae1d --- /dev/null +++ b/src/quantiser.c @@ -0,0 +1,461 @@ +/* + An LV2 plugin to quantise an input to a set of fixed values. + Copyright 2011 David Robillard + Copyright 2003 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "math_func.h" +#include "common.h" + +#define QUANTISER_RANGE_MIN 0 +#define QUANTISER_RANGE_MAX 1 +#define QUANTISER_MATCH_RANGE 2 +#define QUANTISER_MODE 3 +#define QUANTISER_COUNT 4 +#define QUANTISER_VALUE_START 5 +#define QUANTISER_INPUT (QUANTISER_MAX_INPUTS + 5) +#define QUANTISER_OUTPUT (QUANTISER_MAX_INPUTS + 6) +#define QUANTISER_OUTPUT_CHANGED (QUANTISER_MAX_INPUTS + 7) + +typedef struct { + const float* min; + const float* max; + const float* match_range; + const float* mode; + const float* count; + const float* values[QUANTISER_MAX_INPUTS]; + const float* input; + float* output_changed; + float* output; + float svalues[QUANTISER_MAX_INPUTS + 2]; + float temp[QUANTISER_MAX_INPUTS + 2]; + float last_found; +} Quantiser; + +/* + * f <= m <= l +*/ +static inline void +merge(float* v, + int f, + int m, + int l, + float* temp) +{ + int f1 = f; + int l1 = m; + int f2 = m + 1; + int l2 = l; + int i = f1; + + while ((f1 <= l1) && (f2 <= l2)) { + if (v[f1] < v[f2]) { + temp[i] = v[f1]; + f1++; + } else { + temp[i] = v[f2]; + f2++; + } + i++; + } + while (f1 <= l1) { + temp[i] = v[f1]; + f1++; + i++; + } + while (f2 <= l2) { + temp[i] = v[f2]; + f2++; + i++; + } + for (i = f; i <= l; i++) { + v[i] = temp[i]; + } +} + +/* + * Recursive Merge Sort + * Sort elements in unsorted vector v +*/ +static inline void +msort(float* v, + int f, + int l, + float* temp) +{ + int m; + + if (f < l) { + m = (f + l) / 2; + msort(v, f, m, temp); + msort(v, m + 1, l, temp); + merge(v, f, m, l, temp); + } +} + +/* + * Binary search for nearest match to sought value in + * ordered vector v of given size +*/ +static inline int +fuzzy_bsearch(float* v, + int size, + float sought) +{ + int f = 0; + int l = size - 1; + int m = ((l - f) / 2); + + while ((l - f) > 1) { + if (v[m] < sought) { + f = (l - f) / 2 + f; + } else { + l = (l - f) / 2 + f; + } + + m = ((l - f) / 2 + f); + } + + if (sought < v[m]) { + if (m > 0) { + if (FABSF(v[m] - sought) > FABSF(v[m - 1] - sought)) { + m--; + } + } + } else if (m < size - 1) { + if (FABSF(v[m] - sought) > FABSF(v[m + 1] - sought)) { + m++; + } + } + + return m; +} + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +activate(LV2_Handle instance) +{ + Quantiser* plugin = (Quantiser*)instance; + + plugin->last_found = 0.0f; +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Quantiser* plugin = (Quantiser*)instance; + + switch (port) { + case QUANTISER_RANGE_MIN: + plugin->min = (const float*)data; + break; + case QUANTISER_RANGE_MAX: + plugin->max = (const float*)data; + break; + case QUANTISER_MATCH_RANGE: + plugin->match_range = (const float*)data; + break; + case QUANTISER_MODE: + plugin->mode = (const float*)data; + break; + case QUANTISER_COUNT: + plugin->count = (const float*)data; + break; + case QUANTISER_INPUT: + plugin->input = (const float*)data; + break; + case QUANTISER_OUTPUT: + plugin->output = (float*)data; + break; + case QUANTISER_OUTPUT_CHANGED: + plugin->output_changed = (float*)data; + break; + default: + if (port >= QUANTISER_VALUE_START && port < QUANTISER_OUTPUT) { + plugin->values[port - QUANTISER_VALUE_START] = (float*)data; + } + break; + } +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Quantiser* plugin = (Quantiser*)malloc(sizeof(Quantiser)); + + return (LV2_Handle)plugin; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Quantiser* plugin = (Quantiser*)instance; + + /* Range Min (float value) */ + float min = *(plugin->min); + + /* Range Max (float value) */ + float max = *(plugin->max); + + /* Match Range (float value) */ + const float match_range = FABSF(*(plugin->match_range)); + + /* Mode (float value) */ + const float mode = *(plugin->mode); + + /* Count (float value) */ + const float count = *(plugin->count); + + /* Input (array of float of length sample_count) */ + const float* input = plugin->input; + + /* Output (array of float of length sample_count) */ + float* output = plugin->output; + + /* Output Changed (array of float of length sample_count) */ + float* output_changed = plugin->output_changed; + + /* Instance Data */ + float* temp = plugin->temp; + float* values = plugin->svalues; + float last_found = plugin->last_found; + + int md = LRINTF(mode); + int n = LRINTF(count); + int i; + float in; + float out_changed; + float range; + float offset; + float found = last_found; + int found_index = 0; + + /* Clip count if out of range */ + n = n < 1 ? 1 : (n > QUANTISER_MAX_INPUTS ? QUANTISER_MAX_INPUTS : n); + + /* Swap min and max if wrong way around */ + if (min > max) { + range = min; + min = max; + max = range; + } + range = max - min; + + /* Copy and sort required values */ + for (i = 0; i < n; i++) { + values[i + 1] = *(plugin->values[i]); + } + + msort(values, 1, n, temp); + + /* Add wrapped extremes */ + values[0] = values[n] - range; + values[n + 1] = values[1] + range; + + if (md < 1) { + /* Extend mode */ + for (uint32_t s = 0; s < sample_count; ++s) { + in = input[s]; + + if (range > 0.0f) { + if ((in < min) || (in > max)) { + offset = FLOORF((in - max) / range) + 1.0f; + offset *= range; + in -= offset; + + /* Quantise */ + found_index = fuzzy_bsearch(values, n + 2, in); + + /* Wrapped */ + if (found_index == 0) { + found_index = n; + offset -= range; + } else if (found_index == n + 1) { + found_index = 1; + offset += range; + } + + found = values[found_index]; + + /* Allow near misses */ + if (match_range > 0.0f) { + if (in < (found - match_range)) { + found -= match_range; + } else if (in > (found + match_range)) { + found += match_range; + } + } + found += offset; + } else { + /* Quantise */ + found_index = fuzzy_bsearch(values, n + 2, in); + if (found_index == 0) { + found_index = n; + found = values[n] - range; + } else if (found_index == n + 1) { + found_index = 1; + found = values[1] + range; + } else { + found = values[found_index]; + } + + if (match_range > 0.0f) { + if (in < (found - match_range)) { + found -= match_range; + } else if (in > (found + match_range)) { + found += match_range; + } + } + } + } else { + /* Min and max the same, so only one value to quantise to */ + found = min; + } + + /* Has quantised output changed? */ + if (FABSF(found - last_found) > 2.0001f * match_range) { + out_changed = 1.0f; + last_found = found; + } else { + out_changed = 0.0f; + } + + output[s] = found; + output_changed[s] = out_changed; + } + } else if (md == 1) { + /* Wrap mode */ + for (uint32_t s = 0; s < sample_count; ++s) { + in = input[s]; + + if (range > 0.0f) { + if ((in < min) || (in > max)) { + in -= (FLOORF((in - max) / range) + 1.0f) * range; + } + + /* Quantise */ + found_index = fuzzy_bsearch(values, n + 2, in); + if (found_index == 0) { + found_index = n; + } else if (found_index == n + 1) { + found_index = 1; + } + + found = values[found_index]; + + /* Allow near misses */ + if (match_range > 0.0f) { + if (in < (found - match_range)) { + found -= match_range; + } else if (in > (found + match_range)) { + found += match_range; + } + } + } else { + /* Min and max the same, so only one value to quantise to */ + found = min; + } + + /* Has quantised output changed? */ + if (FABSF(found - last_found) > match_range) { + out_changed = 1.0f; + last_found = found; + } else { + out_changed = 0.0f; + } + + output[s] = found; + output_changed[s] = out_changed; + } + } else { + /* Clip mode */ + for (uint32_t s = 0; s < sample_count; ++s) { + in = input[s]; + + if (range > 0.0f) { + /* Clip to range */ + if (in < min) { + found_index = 1; + } else if (in > max) { + found_index = n; + } else { + /* Quantise */ + found_index = fuzzy_bsearch(values + 1, n, in) + 1; + } + + found = values[found_index]; + + /* Allow near misses */ + if (match_range > 0.0f) { + if (in < (found - match_range)) { + found -= match_range; + } else if (in > (found + match_range)) { + found += match_range; + } + } + } else { + /* Min and max the same, so only one value to quantise to */ + found = min; + } + + /* Has quantised output changed? */ + if (FABSF(found - last_found) > match_range) { + out_changed = 1.0f; + last_found = found; + } else { + out_changed = 0.0f; + } + + output[s] = found; + output_changed[s] = out_changed; + } + } + plugin->last_found = last_found; +} + +static const LV2_Descriptor descriptor = { + QUANTISER_URI, + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + NULL +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/random.c b/src/random.c new file mode 100644 index 0000000..45d8de8 --- /dev/null +++ b/src/random.c @@ -0,0 +1,237 @@ +/* + An LV2 plugin to generate a random wave of varying frequency and smoothness. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include <time.h> +#include "math_func.h" +#include "common.h" +#include "uris.h" + +#define RANDOM_FREQUENCY 0 +#define RANDOM_SMOOTH 1 +#define RANDOM_OUTPUT 2 + +typedef struct { + const float* frequency; + const float* smooth; + float* output; + float nyquist; + float inv_nyquist; + float phase; + float value1; + float value2; + uint32_t frequency_is_cv; + uint32_t smooth_is_cv; + URIs uris; +} Random; + +float inv_rand_max; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Random* plugin = (Random*)instance; + + switch (port) { + case RANDOM_FREQUENCY: + plugin->frequency = (const float*)data; + break; + case RANDOM_SMOOTH: + plugin->smooth = (const float*)data; + break; + case RANDOM_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Random* plugin = (Random*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + + switch (o->subject) { + case RANDOM_FREQUENCY: + plugin->frequency_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case RANDOM_SMOOTH: + plugin->smooth_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Random* plugin = (Random*)malloc(sizeof(Random)); + if (!plugin) { + return NULL; + } + + srand((int)time((time_t*)0)); + + inv_rand_max = 2.0f / (float)RAND_MAX; + + plugin->nyquist = (float)sample_rate / 2.0f; + plugin->inv_nyquist = 1.0f / plugin->nyquist; + + plugin->value1 = rand() * inv_rand_max - 1.0f; + plugin->value2 = rand() * inv_rand_max - 1.0f; + + plugin->frequency_is_cv = 0; + plugin->smooth_is_cv = 0; + + map_uris(&plugin->uris, features); + + return (LV2_Handle)plugin; +} + +static void +activate(LV2_Handle instance) +{ + Random* plugin = (Random*)instance; + + plugin->phase = 0.0f; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Random* plugin = (Random*)instance; + + /* Frequency (Hz) (array of floats of length 1 or sample_count) */ + const float* frequency = plugin->frequency; + + /* Wave smoothness (array of floats of length 1 or sample_count) */ + const float* smooth = plugin->smooth; + + /* Output (array of floats of length sample_count) */ + float* output = plugin->output; + + /* Instance data */ + float nyquist = plugin->nyquist; + float inv_nyquist = plugin->inv_nyquist; + float phase = plugin->phase; + float value1 = plugin->value1; + float value2 = plugin->value2; + + float result; + + for (uint32_t s = 0; s < sample_count; ++s) { + const float freq = f_clip(frequency[s * plugin->frequency_is_cv], + 0.0f, nyquist); + + const float smth = f_clip(smooth[s * plugin->smooth_is_cv], + 0.0f, 1.0f); + + const float interval = (1.0f - smth) * 0.5f; + + if (phase < interval) { + result = 1.0f; + } else if (phase > (1.0f - interval)) { + result = -1.0f; + } else if (interval > 0.0f) { + result = COSF((phase - interval) / smth * M_PI); + } else { + result = COSF(phase * M_PI); + } + + result *= (value2 - value1) * 0.5f; + result -= (value2 + value1) * 0.5f; + + output[s] = result; + + phase += freq * inv_nyquist; + if (phase > 1.0f) { + phase -= 1.0f; + value1 = value2; + value2 = (float)rand() * inv_rand_max - 1.0f; + } + } + + plugin->phase = phase; + plugin->value1 = value1; + plugin->value2 = value2; +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { NULL, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/random", + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/ratio.c b/src/ratio.c new file mode 100644 index 0000000..30873c2 --- /dev/null +++ b/src/ratio.c @@ -0,0 +1,202 @@ +/* + An LV2 plugin to calculate the ratio of two signals. + Copyright 2011 David Robillard + Copyright 2004 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "math_func.h" +#include "common.h" +#include "uris.h" + +#define RATIO_NUMERATOR 0 +#define RATIO_DENOMINATOR 1 +#define RATIO_OUTPUT 2 + +typedef struct { + const float* numerator; + const float* denominator; + float* output; + uint32_t numerator_is_cv; + uint32_t denominator_is_cv; + uint32_t output_is_cv; + URIs uris; +} Ratio; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Ratio* plugin = (Ratio*)instance; + + switch (port) { + case RATIO_NUMERATOR: + plugin->numerator = (const float*)data; + break; + case RATIO_DENOMINATOR: + plugin->denominator = (const float*)data; + break; + case RATIO_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Ratio* plugin = (Ratio*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + switch (o->subject) { + case RATIO_NUMERATOR: + plugin->numerator_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case RATIO_DENOMINATOR: + plugin->denominator_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + plugin->output_is_cv = plugin->numerator_is_cv || plugin->denominator_is_cv; + return ret; +} + +static uint32_t +options_get(LV2_Handle instance, + LV2_Options_Option* options) +{ + const Ratio* plugin = (const Ratio*)instance; + uint32_t ret = 0; + for (LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT || o->subject != RATIO_OUTPUT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else { + o->size = sizeof(LV2_URID); + o->type = plugin->uris.atom_URID; + o->value = (plugin->output_is_cv + ? &plugin->uris.lv2_CVPort + : &plugin->uris.lv2_ControlPort); + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Ratio* plugin = (Ratio*)malloc(sizeof(Ratio)); + + if (plugin) { + plugin->numerator_is_cv = 0; + plugin->denominator_is_cv = 0; + plugin->output_is_cv = 0; + + map_uris(&plugin->uris, features); + } + + return (LV2_Handle)plugin; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Ratio* plugin = (Ratio*)instance; + + /* Numerator (array of floats of length sample_count) */ + const float* numerator = plugin->numerator; + + /* Denominator (array of floats of length sample_count) */ + const float* denominator = plugin->denominator; + + /* Output (array of floats of length sample_count) */ + float* output = plugin->output; + + if (!plugin->output_is_cv) { /* TODO: Avoid this branch */ + sample_count = 1; + } + + for (uint32_t s = 0; s < sample_count; ++s) { + const float n = numerator[s * plugin->numerator_is_cv]; + float d = denominator[s * plugin->denominator_is_cv]; + + d = COPYSIGNF(f_max(FABSF(d), 1e-16f), d); + + output[s] = n / d; + } +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { options_get, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/ratio", + instantiate, + connect_port, + NULL, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/sawtooth.c b/src/sawtooth.c new file mode 100644 index 0000000..31c9057 --- /dev/null +++ b/src/sawtooth.c @@ -0,0 +1,194 @@ +/* + An LV2 plugin to generate a bandlimited sawtooth waveform. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" +#include "wavedata.h" + +#define SAWTOOTH_FREQUENCY 0 +#define SAWTOOTH_OUTPUT 1 + +typedef struct { + const float* frequency; + float* output; + float phase; + uint32_t frequency_is_cv; + Wavedata wdat; + URIs uris; +} Sawtooth; + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Sawtooth* plugin = (Sawtooth*)instance; + + switch (port) { + case SAWTOOTH_FREQUENCY: + plugin->frequency = (const float*)data; + break; + case SAWTOOTH_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Sawtooth* plugin = (Sawtooth*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + + switch (o->subject) { + case SAWTOOTH_FREQUENCY: + plugin->frequency_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Sawtooth* plugin = (Sawtooth*)malloc(sizeof(Sawtooth)); + if (!plugin) { + return NULL; + } + + if (wavedata_load(&plugin->wdat, bundle_path, "sawtooth_data", + BLOP_DLSYM_SAWTOOTH, sample_rate)) { + free(plugin); + return 0; + } + + plugin->frequency_is_cv = 0; + map_uris(&plugin->uris, features); + wavedata_get_table(&plugin->wdat, 440.0); + + return (LV2_Handle)plugin; +} + +static void +cleanup(LV2_Handle instance) +{ + Sawtooth* plugin = (Sawtooth*)instance; + + wavedata_unload(&plugin->wdat); + free(instance); +} + +static void +activate(LV2_Handle instance) +{ + Sawtooth* plugin = (Sawtooth*)instance; + + plugin->phase = 0.0f; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Sawtooth* plugin = (Sawtooth*)instance; + + /* Frequency (array of float of length 1 or sample_count) */ + const float* frequency = plugin->frequency; + + /* Output (pointer to float value) */ + float* output = plugin->output; + + /* Instance data */ + Wavedata* wdat = &plugin->wdat; + float phase = plugin->phase; + + for (uint32_t s = 0; s < sample_count; s++) { + const float freq = frequency[s * plugin->frequency_is_cv]; + if (freq != wdat->frequency) { + /* Frequency changed, look up table to play */ + wavedata_get_table(wdat, freq); + } + + output[s] = wavedata_get_sample(wdat, phase); + + /* Update phase, wrapping if necessary */ + phase += wdat->frequency; + if (phase < 0.0f) { + phase += wdat->sample_rate; + } else if (phase > wdat->sample_rate) { + phase -= wdat->sample_rate; + } + } + plugin->phase = phase; +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { NULL, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/sawtooth", + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/sequencer.c b/src/sequencer.c new file mode 100644 index 0000000..939401b --- /dev/null +++ b/src/sequencer.c @@ -0,0 +1,216 @@ +/* + An LV2 plugin to simulate an analogue style step sequencer. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "math_func.h" +#include "common.h" + +#define SEQUENCER_GATE 0 +#define SEQUENCER_TRIGGER 1 +#define SEQUENCER_LOOP_POINT 2 +#define SEQUENCER_RESET 3 +#define SEQUENCER_VALUE_GATE_CLOSED 4 +#define SEQUENCER_VALUE_START 5 +#define SEQUENCER_OUTPUT (SEQUENCER_MAX_INPUTS + 5) + +typedef struct { + const float* gate; + const float* trigger; + const float* loop_steps; + const float* reset; + const float* value_gate_closed; + const float* values[SEQUENCER_MAX_INPUTS]; + float* output; + float srate; + float inv_srate; + float last_gate; + float last_trigger; + float last_value; + unsigned int step_index; +} Sequencer; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Sequencer* plugin = (Sequencer*)instance; + + switch (port) { + case SEQUENCER_GATE: + plugin->gate = (const float*)data; + break; + case SEQUENCER_TRIGGER: + plugin->trigger = (const float*)data; + break; + case SEQUENCER_LOOP_POINT: + plugin->loop_steps = (const float*)data; + break; + case SEQUENCER_OUTPUT: + plugin->output = (float*)data; + break; + case SEQUENCER_RESET: + plugin->reset = (const float*)data; + break; + case SEQUENCER_VALUE_GATE_CLOSED: + plugin->value_gate_closed = (const float*)data; + break; + default: + if (port >= SEQUENCER_VALUE_START && port < SEQUENCER_OUTPUT) { + plugin->values[port - SEQUENCER_VALUE_START] = (const float*)data; + } + break; + } +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Sequencer* plugin = (Sequencer*)malloc(sizeof(Sequencer)); + if (!plugin) { + return NULL; + } + + plugin->srate = (float)sample_rate; + plugin->inv_srate = 1.0f / plugin->srate; + + return (LV2_Handle)plugin; +} + +static void +activate(LV2_Handle instance) +{ + Sequencer* plugin = (Sequencer*)instance; + + plugin->last_gate = 0.0f; + plugin->last_trigger = 0.0f; + plugin->last_value = 0.0f; + plugin->step_index = 0; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Sequencer* plugin = (Sequencer*)instance; + + /* Gate */ + const float* gate = plugin->gate; + + /* Step Trigger */ + const float* trigger = plugin->trigger; + + /* Loop Steps */ + const float loop_steps = *(plugin->loop_steps); + + /* Reset to Value on Gate Close */ + const float reset = *(plugin->reset); + + /* Value used when gate closed */ + float value_gate_closed = *(plugin->value_gate_closed); + + /* Step Values */ + float values[SEQUENCER_MAX_INPUTS]; + + /* Output */ + float* output = plugin->output; + + float last_gate = plugin->last_gate; + float last_trigger = plugin->last_trigger; + float last_value = plugin->last_value; + + unsigned int step_index = plugin->step_index; + unsigned int loop_index = LRINTF(loop_steps); + int rst = reset > 0.0f; + int i; + + loop_index = loop_index == 0 ? 1 : loop_index; + loop_index = (loop_index > SEQUENCER_MAX_INPUTS) + ? SEQUENCER_MAX_INPUTS + : loop_index; + + for (i = 0; i < SEQUENCER_MAX_INPUTS; i++) { + values[i] = *(plugin->values[i]); + } + + for (uint32_t s = 0; s < sample_count; ++s) { + if (gate[s] > 0.0f) { + if (trigger[s] > 0.0f && !(last_trigger > 0.0f)) { + if (last_gate > 0.0f) { + step_index++; + if (step_index >= loop_index) { + step_index = 0; + } + } else { + step_index = 0; + } + } + + output[s] = values[step_index]; + + last_value = values[step_index]; + } else { + if (rst) { + output[s] = value_gate_closed; + } else { + output[s] = last_value; + } + + step_index = 0; + } + last_gate = gate[s]; + last_trigger = trigger[s]; + } + + plugin->last_gate = last_gate; + plugin->last_trigger = last_trigger; + plugin->last_value = last_value; + plugin->step_index = step_index; +} + +static const LV2_Descriptor descriptor = { + SEQUENCER_URI, + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + NULL +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/square.c b/src/square.c new file mode 100644 index 0000000..0136124 --- /dev/null +++ b/src/square.c @@ -0,0 +1,195 @@ +/* + An LV2 plugin to generate a bandlimited square waveform. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" +#include "wavedata.h" + +#define SQUARE_FREQUENCY 0 +#define SQUARE_OUTPUT 1 + +typedef struct { + const float* frequency; + float* output; + float phase; + uint32_t frequency_is_cv; + Wavedata wdat; + URIs uris; +} Square; + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Square* plugin = (Square*)instance; + + switch (port) { + case SQUARE_FREQUENCY: + plugin->frequency = (const float*)data; + break; + case SQUARE_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Square* plugin = (Square*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + + switch (o->subject) { + case SQUARE_FREQUENCY: + plugin->frequency_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Square* plugin = (Square*)malloc(sizeof(Square)); + if (!plugin) { + return NULL; + } + + if (wavedata_load(&plugin->wdat, bundle_path, "square_data", + BLOP_DLSYM_SQUARE, sample_rate)) { + free(plugin); + return NULL; + } + + plugin->frequency_is_cv = 0; + map_uris(&plugin->uris, features); + wavedata_get_table(&plugin->wdat, 440.0); + + return (LV2_Handle)plugin; +} + +static void +cleanup(LV2_Handle instance) +{ + Square* plugin = (Square*)instance; + + wavedata_unload(&plugin->wdat); + free(instance); +} + +static void +activate(LV2_Handle instance) +{ + Square* plugin = (Square*)instance; + + plugin->phase = 0.0f; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Square* plugin = (Square*)instance; + + /* Frequency (array of float of length sample_count) */ + const float* frequency = plugin->frequency; + + /* Output (pointer to float value) */ + float* output = plugin->output; + + /* Instance data */ + Wavedata* wdat = &plugin->wdat; + float phase = plugin->phase; + + for (uint32_t s = 0; s < sample_count; ++s) { + const float freq = frequency[s * plugin->frequency_is_cv]; + if (freq != wdat->frequency) { + /* Frequency changed, look up table to play */ + wavedata_get_table(wdat, freq); + } + + /* Get interpolated sample */ + output[s] = wavedata_get_sample(wdat, phase); + + /* Update phase, wrapping if necessary */ + phase += wdat->frequency; + if (phase < 0.0f) { + phase += wdat->sample_rate; + } else if (phase > wdat->sample_rate) { + phase -= wdat->sample_rate; + } + } + plugin->phase = phase; +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { NULL, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/square", + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/sum.c b/src/sum.c new file mode 100644 index 0000000..3023733 --- /dev/null +++ b/src/sum.c @@ -0,0 +1,185 @@ +/* + An LV2 plugin to calculate the sum of two signals. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" +#include "vector_op.h" + +#define SUM_INPUT1 0 +#define SUM_INPUT2 1 +#define SUM_OUTPUT 2 + +typedef struct { + const float* input1; + const float* input2; + float* output; + uint32_t input1_is_cv; + uint32_t input2_is_cv; + uint32_t output_is_cv; + URIs uris; +} Sum; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Sum* plugin = (Sum*)instance; + + switch (port) { + case SUM_INPUT1: + plugin->input1 = (const float*)data; + break; + case SUM_INPUT2: + plugin->input2 = (const float*)data; + break; + case SUM_OUTPUT: + plugin->output = (float*)data; + break; + } +} +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Sum* plugin = (Sum*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + switch (o->subject) { + case SUM_INPUT1: + plugin->input1_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case SUM_INPUT2: + plugin->input2_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + plugin->output_is_cv = plugin->input1_is_cv || plugin->input2_is_cv; + return ret; +} + +static uint32_t +options_get(LV2_Handle instance, + LV2_Options_Option* options) +{ + const Sum* plugin = (const Sum*)instance; + uint32_t ret = 0; + for (LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT || o->subject != SUM_OUTPUT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else { + o->size = sizeof(LV2_URID); + o->type = plugin->uris.atom_URID; + o->value = (plugin->output_is_cv + ? &plugin->uris.lv2_CVPort + : &plugin->uris.lv2_ControlPort); + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Sum* plugin = (Sum*)malloc(sizeof(Sum)); + + if (plugin) { + plugin->input1_is_cv = 0; + plugin->input2_is_cv = 0; + plugin->output_is_cv = 0; + + map_uris(&plugin->uris, features); + } + + return (LV2_Handle)plugin; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + const Sum* const plugin = (Sum*)instance; + const float* const input1 = plugin->input1; + const float* const input2 = plugin->input2; + float* const output = plugin->output; + + VECTOR_OP(+, output, + input1, plugin->input1_is_cv, + input2, plugin->input2_is_cv); +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { options_get, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/sum", + instantiate, + connect_port, + NULL, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/sync_pulse.c b/src/sync_pulse.c new file mode 100644 index 0000000..0f24c80 --- /dev/null +++ b/src/sync_pulse.c @@ -0,0 +1,213 @@ +/* + An LV2 plugin to generate a non-bandlimited variable-pulse waveform with gate + for trigger and sync. + Copyright 2011 David Robillard + Copyright 2003 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" +#include "common.h" + +#define SYNCPULSE_FREQUENCY 0 +#define SYNCPULSE_PULSEWIDTH 1 +#define SYNCPULSE_GATE 2 +#define SYNCPULSE_OUTPUT 3 + +typedef struct { + const float* frequency; + const float* pulsewidth; + const float* gate; + float* output; + float srate; + float phase; + uint32_t frequency_is_cv; + uint32_t pulsewidth_is_cv; + URIs uris; +} SyncPulse; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + SyncPulse* plugin = (SyncPulse*)instance; + + switch (port) { + case SYNCPULSE_FREQUENCY: + plugin->frequency = (const float*)data; + break; + case SYNCPULSE_PULSEWIDTH: + plugin->pulsewidth = (const float*)data; + break; + case SYNCPULSE_GATE: + plugin->gate = (const float*)data; + break; + case SYNCPULSE_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + SyncPulse* plugin = (SyncPulse*)malloc(sizeof(SyncPulse)); + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + + switch (o->subject) { + case SYNCPULSE_FREQUENCY: + plugin->frequency_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case SYNCPULSE_PULSEWIDTH: + plugin->pulsewidth_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + SyncPulse* plugin = (SyncPulse*)malloc(sizeof(SyncPulse)); + + if (plugin) { + plugin->srate = (float)sample_rate; + plugin->frequency_is_cv = 0; + plugin->pulsewidth_is_cv = 0; + map_uris(&plugin->uris, features); + } + + return (LV2_Handle)plugin; +} + +static void +activate(LV2_Handle instance) +{ + SyncPulse* plugin = (SyncPulse*)instance; + + plugin->phase = 0.0f; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + SyncPulse* plugin = (SyncPulse*)instance; + + /* Frequency (array of float of length sample_count) */ + const float* frequency = plugin->frequency; + + /* Pulse Width (array of float of length sample_count) */ + const float* pulsewidth = plugin->pulsewidth; + + /* Gate (array of float of length sample_count) */ + const float* gate = plugin->gate; + + /* Output (pointer to float value) */ + float* output = plugin->output; + + /* Instance data */ + float phase = plugin->phase; + float srate = plugin->srate; + + for (uint32_t s = 0; s < sample_count; ++s) { + if (gate[s] > 0.0f) { + const float freq = frequency[s * plugin->frequency_is_cv]; + const float pw = pulsewidth[s * plugin->pulsewidth_is_cv]; + const float pwidth = f_clip(pw, 0.0f, 1.0f) * srate; + + if (phase < pwidth) { + output[s] = 1.0f; + } else { + output[s] = -1.0f; + } + + phase += freq; + if (phase < 0.0f) { + phase += srate; + } else if (phase > srate) { + phase -= srate; + } + } else { + output[s] = 0.0f; + phase = 0.0f; + } + } + + plugin->phase = phase; +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { NULL, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/sync_pulse", + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/sync_square.c b/src/sync_square.c new file mode 100644 index 0000000..38fdaf5 --- /dev/null +++ b/src/sync_square.c @@ -0,0 +1,201 @@ +/* + An LV2 plugin to generate a non-bandlimited square waveform with gate for + trigger and sync. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" + +#define SYNCSQUARE_FREQUENCY 0 +#define SYNCSQUARE_GATE 1 +#define SYNCSQUARE_OUTPUT 2 + +typedef struct { + const float* frequency; + const float* gate; + float* output; + float srate; + float nyquist; + float phase; + uint32_t frequency_is_cv; + URIs uris; +} SyncSquare; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + SyncSquare* plugin = (SyncSquare*)instance; + + switch (port) { + case SYNCSQUARE_FREQUENCY: + plugin->frequency = (const float*)data; + break; + case SYNCSQUARE_GATE: + plugin->gate = (const float*)data; + break; + case SYNCSQUARE_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + SyncSquare* plugin = (SyncSquare*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + + switch (o->subject) { + case SYNCSQUARE_FREQUENCY: + plugin->frequency_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + SyncSquare* plugin = (SyncSquare*)malloc(sizeof(SyncSquare)); + if (!plugin) { + return NULL; + } + + plugin->srate = (float)sample_rate; + plugin->nyquist = (float)(sample_rate / 2.0f); + plugin->frequency_is_cv = 0; + map_uris(&plugin->uris, features); + + return (LV2_Handle)plugin; +} + +static void +activate(LV2_Handle instance) +{ + SyncSquare* plugin = (SyncSquare*)instance; + + plugin->phase = 0.0f; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + SyncSquare* plugin = (SyncSquare*)instance; + + /* Frequency (array of float of length 1 or sample_count) */ + const float* frequency = plugin->frequency; + + /* Gate (array of float of length sample_count) */ + const float* gate = plugin->gate; + + /* Output (pointer to float value) */ + float* output = plugin->output; + + /* Instance data */ + float phase = plugin->phase; + float srate = plugin->srate; + float nyquist = plugin->nyquist; + + for (uint32_t s = 0; s < sample_count; ++s) { + if (gate[s] > 0.0f) { + const float freq = frequency[s * plugin->frequency_is_cv]; + + if (phase < nyquist) { + output[s] = 1.0f; + } else { + output[s] = -1.0f; + } + + phase += freq; + if (phase < 0.0f) { + phase += srate; + } else if (phase > srate) { + phase -= srate; + } + } else { + output[s] = 0.0f; + phase = 0.0f; + } + } + + plugin->phase = phase; +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { NULL, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/sync_square", + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/tracker.c b/src/tracker.c new file mode 100644 index 0000000..dd628bc --- /dev/null +++ b/src/tracker.c @@ -0,0 +1,245 @@ +/* + An LV2 plugin to shape a signal in various ways. + Copyright 2011 David Robillard + Copyright 2003 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "common.h" +#include "uris.h" + +#define TRACKER_GATE 0 +#define TRACKER_HATTACK 1 +#define TRACKER_HDECAY 2 +#define TRACKER_LATTACK 3 +#define TRACKER_LDECAY 4 +#define TRACKER_INPUT 5 +#define TRACKER_OUTPUT 6 + +typedef struct { + const float* gate; + const float* hattack; + const float* hdecay; + const float* lattack; + const float* ldecay; + const float* input; + float* output; + float coeff; + float last_value; + uint32_t hattack_is_cv; + uint32_t hdecay_is_cv; + uint32_t lattack_is_cv; + uint32_t ldecay_is_cv; + URIs uris; +} Tracker; + +static void +cleanup(LV2_Handle instance) +{ + free(instance); +} + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Tracker* plugin = (Tracker*)instance; + + switch (port) { + case TRACKER_GATE: + plugin->gate = (const float*)data; + break; + case TRACKER_HATTACK: + plugin->hattack = (const float*)data; + break; + case TRACKER_HDECAY: + plugin->hdecay = (const float*)data; + break; + case TRACKER_LATTACK: + plugin->lattack = (const float*)data; + break; + case TRACKER_LDECAY: + plugin->ldecay = (const float*)data; + break; + case TRACKER_INPUT: + plugin->input = (const float*)data; + break; + case TRACKER_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Tracker* plugin = (Tracker*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + + switch (o->subject) { + case TRACKER_HATTACK: + plugin->hattack_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case TRACKER_HDECAY: + plugin->hdecay_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case TRACKER_LATTACK: + plugin->lattack_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case TRACKER_LDECAY: + plugin->ldecay_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Tracker* plugin = (Tracker*)malloc(sizeof(Tracker)); + if (!plugin) { + return NULL; + } + + plugin->coeff = 2.0f * M_PI / (float)sample_rate; + + plugin->hattack_is_cv = 0; + plugin->hdecay_is_cv = 0; + plugin->lattack_is_cv = 0; + plugin->ldecay_is_cv = 0; + + map_uris(&plugin->uris, features); + + return (LV2_Handle)plugin; +} + +static void +activate(LV2_Handle instance) +{ + Tracker* plugin = (Tracker*)instance; + + plugin->last_value = 0.0f; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Tracker* plugin = (Tracker*)instance; + + /* Gate (array of floats of length sample_count) */ + const float* gate = plugin->gate; + + /* Gate High Attack Rate (array of floats of length 1 or sample_count) */ + const float* hattack = plugin->hattack; + + /* Gate High Decay Rate (array of floats of length 1 or sample_count) */ + const float* hdecay = plugin->hdecay; + + /* Gate Low Attack Rate (array of floats of length 1 or sample_count) */ + const float* lattack = plugin->lattack; + + /* Gate Low Decay Rate (array of floats of length 1 or sample_count) */ + const float* ldecay = plugin->ldecay; + + /* Input (array of floats of length sample_count) */ + const float* input = plugin->input; + + /* Output (array of floats of length sample_count) */ + float* output = plugin->output; + + /* Instance Data */ + float coeff = plugin->coeff; + float last_value = plugin->last_value; + + for (uint32_t s = 0; s < sample_count; ++s) { + const float in = input[s]; + const float ha = hattack[s * plugin->hattack_is_cv]; + const float hd = hdecay[s * plugin->hdecay_is_cv]; + const float la = lattack[s * plugin->lattack_is_cv]; + const float ld = ldecay[s * plugin->ldecay_is_cv]; + + float rate; + if (gate[s] > 0.0f) { + rate = in > last_value ? ha : hd; + } else { + rate = in > last_value ? la : ld; + } + + rate = f_min(1.0f, rate * coeff); + last_value = last_value * (1.0f - rate) + in * rate; + + output[s] = last_value; + } + + plugin->last_value = last_value; +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { NULL, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/tracker", + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/triangle.c b/src/triangle.c new file mode 100644 index 0000000..09c01c2 --- /dev/null +++ b/src/triangle.c @@ -0,0 +1,232 @@ +/* + An LV2 plugin to generate a bandlimited slope-variable triangle waveform. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include "lv2/lv2plug.in/ns/ext/morph/morph.h" +#include "lv2/lv2plug.in/ns/ext/options/options.h" +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "uris.h" +#include "wavedata.h" + +#define TRIANGLE_FREQUENCY 0 +#define TRIANGLE_SLOPE 1 +#define TRIANGLE_OUTPUT 2 + +typedef struct { + const float* frequency; + const float* slope; + float* output; + float phase; + float min_slope; + float max_slope; + uint32_t frequency_is_cv; + uint32_t slope_is_cv; + Wavedata wdat; + URIs uris; +} Triangle; + +static void +connect_port(LV2_Handle instance, + uint32_t port, + void* data) +{ + Triangle* plugin = (Triangle*)instance; + + switch (port) { + case TRIANGLE_FREQUENCY: + plugin->frequency = (const float*)data; + break; + case TRIANGLE_SLOPE: + plugin->slope = (const float*)data; + break; + case TRIANGLE_OUTPUT: + plugin->output = (float*)data; + break; + } +} + +static uint32_t +options_set(LV2_Handle instance, + const LV2_Options_Option* options) +{ + Triangle* plugin = (Triangle*)instance; + uint32_t ret = 0; + for (const LV2_Options_Option* o = options; o->key; ++o) { + if (o->context != LV2_OPTIONS_PORT) { + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } else if (o->key != plugin->uris.morph_currentType) { + ret |= LV2_OPTIONS_ERR_BAD_KEY; + } else if (o->type != plugin->uris.atom_URID) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + } else { + LV2_URID port_type = *(const LV2_URID*)(o->value); + if (port_type != plugin->uris.lv2_ControlPort && + port_type != plugin->uris.lv2_CVPort) { + ret |= LV2_OPTIONS_ERR_BAD_VALUE; + continue; + } + + switch (o->subject) { + case TRIANGLE_FREQUENCY: + plugin->frequency_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + case TRIANGLE_SLOPE: + plugin->slope_is_cv = (port_type == plugin->uris.lv2_CVPort); + break; + default: + ret |= LV2_OPTIONS_ERR_BAD_SUBJECT; + } + } + } + return ret; +} + +static LV2_Handle +instantiate(const LV2_Descriptor* descriptor, + double sample_rate, + const char* bundle_path, + const LV2_Feature* const* features) +{ + Triangle* plugin = (Triangle*)malloc(sizeof(Triangle)); + if (!plugin) { + return NULL; + } + + if (wavedata_load(&plugin->wdat, bundle_path, "parabola_data", + BLOP_DLSYM_PARABOLA, sample_rate)) { + free(plugin); + return 0; + } + + plugin->min_slope = 2.0f / plugin->wdat.sample_rate; + plugin->max_slope = 1.0f - plugin->min_slope; + + plugin->frequency_is_cv = 0; + plugin->slope_is_cv = 0; + + map_uris(&plugin->uris, features); + wavedata_get_table(&plugin->wdat, 440.0); + + return (LV2_Handle)plugin; +} + +static void +cleanup(LV2_Handle instance) +{ + Triangle* plugin = (Triangle*)instance; + + wavedata_unload(&plugin->wdat); + free(instance); +} + +static void +activate(LV2_Handle instance) +{ + Triangle* plugin = (Triangle*)instance; + + plugin->phase = 0.0f; +} + +static void +run(LV2_Handle instance, + uint32_t sample_count) +{ + Triangle* plugin = (Triangle*)instance; + + /* Frequency (array of float of length 1 or sample_count) */ + const float* frequency = plugin->frequency; + + /* Slope (array of float of length 1 or sample_count) */ + const float* slope = plugin->slope; + + /* Output (pointer to float value) */ + float* output = plugin->output; + + /* Instance data */ + Wavedata* wdat = &plugin->wdat; + float phase = plugin->phase; + const float min_slope = plugin->min_slope; + const float max_slope = plugin->max_slope; + + float last_slope = slope[0]; + float slp = f_clip(last_slope, min_slope, max_slope); + float phase_shift = slp * wdat->sample_rate; + float scale = 1.0f / (8.0f * (slp - (slp * slp))); + + for (uint32_t s = 0; s < sample_count; ++s) { + const float freq = frequency[s * plugin->frequency_is_cv]; + if (freq != wdat->frequency) { + /* Frequency changed, look up table to play */ + wavedata_get_table(wdat, freq); + } + + const float this_slope = slope[s * plugin->slope_is_cv]; + if (this_slope != last_slope) { + /* Slope changed, recalculate */ + last_slope = this_slope; + slp = f_clip(this_slope, min_slope, max_slope); + phase_shift = slp * wdat->sample_rate; + scale = 1.0f / (8.0f * (slp - (slp * slp))); + } + + /* Get samples from parabola and phase shifted inverted parabola, + and scale to compensate */ + output[s] = (wavedata_get_sample(wdat, phase) + - wavedata_get_sample(wdat, phase + phase_shift)) * scale; + + /* Update phase, wrapping if necessary */ + phase += wdat->frequency; + if (phase < 0.0f) { + phase += wdat->sample_rate; + } else if (phase > wdat->sample_rate) { + phase -= wdat->sample_rate; + } + } + plugin->phase = phase; +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_Options_Interface options = { NULL, options_set }; + if (!strcmp(uri, LV2_OPTIONS__interface)) { + return &options; + } + return NULL; +} + +static const LV2_Descriptor descriptor = { + "http://drobilla.net/plugins/blop/triangle", + instantiate, + connect_port, + activate, + run, + NULL, + cleanup, + extension_data, +}; + +LV2_SYMBOL_EXPORT const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + switch (index) { + case 0: return &descriptor; + default: return NULL; + } +} diff --git a/src/wavedata.c b/src/wavedata.c new file mode 100644 index 0000000..910577f --- /dev/null +++ b/src/wavedata.c @@ -0,0 +1,79 @@ +/* + Oscillator wave data loading. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" +#include "blop_config.h" +#include "wavedata.h" + +#ifdef _WIN32 +# include <windows.h> +# define dlopen(path, flags) LoadLibrary(path) +# define dlclose(lib) FreeLibrary((HMODULE)lib) +# define dlsym(lib, sym) GetProcAddress((HMODULE)lib, sym) +# define snprintf _snprintf +#else +# include <dlfcn.h> +#endif + +int +wavedata_load(Wavedata* w, + const char* bundle_path, + const char* lib_name, + const char* wdat_descriptor_name, + double sample_rate) +{ + const size_t bundle_len = strlen(bundle_path); + const size_t lib_name_len = strlen(lib_name); + const size_t ext_len = strlen(BLOP_SHLIB_EXT); + const size_t path_len = bundle_len + lib_name_len + ext_len + 2; + int retval = -1; + + char* lib_path = (char*)malloc(path_len); + snprintf(lib_path, path_len, "%s%s%s", + bundle_path, lib_name, BLOP_SHLIB_EXT); + + void* handle = dlopen(lib_path, RTLD_NOW); + free(lib_path); + + if (handle) { + // Avoid pedantic warnings about fetching functions with dlsym + typedef void (*VoidFunc)(void); + typedef VoidFunc (*VoidFuncGetter)(void*, const char*); + VoidFuncGetter dlfunc = (VoidFuncGetter)dlsym; + + typedef int (*DescFunc)(Wavedata*, unsigned long); + DescFunc desc_func = (DescFunc)dlfunc(handle, wdat_descriptor_name); + if (desc_func) { + retval = desc_func(w, (unsigned long)sample_rate); + w->data_handle = handle; + return retval; + } + } + + return retval; +} + +void +wavedata_unload(Wavedata* w) +{ + dlclose(w->data_handle); +} diff --git a/src/wavegen.c b/src/wavegen.c new file mode 100644 index 0000000..c722e04 --- /dev/null +++ b/src/wavegen.c @@ -0,0 +1,310 @@ +/* + A program to generate c header files containing pre-calculated wavedata. + Copyright 2011 David Robillard + Copyright 2002 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <getopt.h> +#include "wdatutil.h" +#include "wavedata.h" +#include "common.h" + +static void +usage(void) +{ + int i; + + fprintf(stderr, "\n"); + fprintf(stderr, "Generate bandlimited wavedata and write as c header file\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Usage: wavegen -w <Wavename> -r <Sample Rate> -f <Note> -s <Note Step>\n"); + fprintf(stderr, " -m <Samples> [-o <Output Filename>] [-p <Prefix>]\n"); + fprintf(stderr, " [-g <Factor>] [-q] [-t] [-h]\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -w, --wave Name of wave to generate (case insensitive)\n"); + fprintf(stderr, " -r, --rate Intended playback rate in Samples/Second\n"); + fprintf(stderr, " -f, --first First MIDI note to generate table for\n"); + fprintf(stderr, " -s, --step Number of MIDI notes to skip for next table\n"); + fprintf(stderr, " -m, --min Minimum table size in samples\n"); + fprintf(stderr, " -o, --output Output Filename, name of file to output\n"); + fprintf(stderr, " If not given, output is to stdout\n"); + fprintf(stderr, " -p, --prefix Prefix for declarations in header\n"); + fprintf(stderr, " -g, --gibbs Compensate for Gibbs' effect\n"); + fprintf(stderr, " -q, --quiet Surpress stderr output\n"); + fprintf(stderr, " -t, --test Don't actually generate data\n"); + fprintf(stderr, " -h, --help Print this text and exit\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Supported waves:\n"); + + for (i = 0; i < WAVE_TYPE_COUNT; i++) { + fprintf(stderr, " %s (%s)\n", wave_names[i], wave_descriptions[i]); + } + + fprintf(stderr, "\n"); + fprintf(stderr, "Gibbs' Effect\n"); + fprintf(stderr, " Gibbs' effect causes overshoot in waves generated from finite\n"); + fprintf(stderr, " Fourier Series. Compensation can be applied, which will result in\n"); + fprintf(stderr, " a waveform that sounds slightly less bright.\n"); + fprintf(stderr, " Use the --gibbs option to set degree of compensatation, from 0.0\n"); + fprintf(stderr, " (no compensation) to 1.0 (full compensation)\n"); + fprintf(stderr, "\n"); +} + +/** + Create bandlimited wavedata header files for various + waveforms +*/ +int +main(int argc, + char** argv) +{ + int option_index; + int opt; + const char* options = "w:r:f:s:m:o:p:g:qth"; + struct option long_options[] = { + { "wave", 1, 0, 'w' }, + { "rate", 1, 0, 'r' }, + { "first", 1, 0, 'f' }, + { "step", 1, 0, 's' }, + { "min", 1, 0, 'm' }, + { "output", 1, 0, 'o' }, + { "prefix", 0, 0, 'p' }, + { "gibbs", 1, 0, 'g' }, + { "quiet", 0, 0, 'q' }, + { "test", 0, 0, 't' }, + { "help", 0, 0, 'h' }, + { 0, 0, 0, 0 } + }; + int wavetype = -1; + long sample_rate = -1; + long first_note = -1; + long note_step = -1; + long min_table_size = -1; + const char* filename = NULL; + FILE* file; + const char* prefix = NULL; + float gibbs = 0.0f; + int quiet = 0; + int test = 0; + + Wavedata* w; + float freq; + uint32_t sample_count; + unsigned long max_harmonic_hf; + unsigned long max_harmonic_lf; + unsigned long i; + + size_t strcmplen; + size_t len1; + size_t len2; + + /* Parse arguments */ + if (argc == 1) { + usage(); + exit(-1); + } + + opterr = 0; + while ((opt = getopt_long(argc, argv, options, long_options, &option_index)) != -1) { + switch (opt) { + case 'w': + for (i = 0; i < WAVE_TYPE_COUNT; i++) { + len1 = strlen(optarg); + len2 = strlen(wave_names[i]); + strcmplen = len1 < len2 ? len1 : len2; + + if (!strncmp(optarg, wave_names[i], strcmplen)) { + wavetype = i; + } + } + if (wavetype == -1) { + fprintf(stderr, "Unrecognised option for Wave: %s\n", optarg); + exit(-1); + } + break; + case 'r': + sample_rate = (long)atoi(optarg); + break; + case 'f': + first_note = (long)atoi(optarg); + break; + case 's': + note_step = (long)atoi(optarg); + break; + case 'm': + min_table_size = (long)atoi(optarg); + break; + case 'o': + filename = optarg; + break; + case 'p': + prefix = optarg; + break; + case 'g': + gibbs = atof(optarg); + break; + case 'q': + quiet = -1; + break; + case 't': + test = -1; + break; + case 'h': + usage(); + exit(0); + break; + default: + usage(); + exit(-1); + } + } + + /* Check basic arguments */ + if (wavetype == -1) { + if (!quiet) { + fprintf(stderr, "No wavetype specified.\n"); + } + exit(-1); + } + + if (sample_rate == -1) { + if (!quiet) { + fprintf(stderr, "No sample rate specified.\n"); + } + exit(-1); + } + + if (first_note == -1) { + if (!quiet) { + fprintf(stderr, "No first note specified.\n"); + } + exit(-1); + } + + if (note_step == -1) { + if (!quiet) { + fprintf(stderr, "No note step specified.\n"); + } + exit(-1); + } + + if (min_table_size == -1) { + if (!quiet) { + fprintf(stderr, "No minimum table size specified.\n"); + } + exit(-1); + } + + if (gibbs < 0.0f || gibbs > 1.0f) { + if (!quiet) { + fprintf(stderr, "Gibbs compensation clamped to [0.0, 1.0]\n"); + fprintf(stderr, " Supplied value: %.2f\n", gibbs); + } + gibbs = gibbs < 0.0f ? 0.0f : gibbs; + gibbs = gibbs > 1.0f ? 1.0f : gibbs; + if (!quiet) { + fprintf(stderr, " Clamped to: %.2f\n", gibbs); + } + } + + if (note_step < 1) { + if (!quiet) { + fprintf(stderr, "Using minimum note step of 1\n"); + } + note_step = 1; + } + + /* Get file to write to */ + if (!filename) { + file = stdout; + } else { + file = fopen(filename, "w"); + } + + w = wavedata_new(sample_rate); + + if (!w) { + if (!quiet) { + fprintf(stderr, "Unable to create wavedata\n"); + } + + exit(-1); + } + + freq = FREQ_FROM_NOTE(first_note); + max_harmonic_lf = HARM_FROM_FREQ(freq, sample_rate); + max_harmonic_hf = max_harmonic_lf; + + for (i = 0; max_harmonic_hf > MIN_HARM(wavetype); i += note_step) { + freq = FREQ_FROM_NOTE(first_note + i + note_step); + max_harmonic_hf = HARM_FROM_FREQ(freq, sample_rate); + + max_harmonic_hf = ACTUAL_HARM(max_harmonic_hf, wavetype); + max_harmonic_lf = ACTUAL_HARM(max_harmonic_lf, wavetype); + + while (max_harmonic_lf == max_harmonic_hf) { + i += note_step; + freq = FREQ_FROM_NOTE(first_note + i + note_step); + max_harmonic_hf = HARM_FROM_FREQ(freq, sample_rate); + max_harmonic_hf = ACTUAL_HARM(max_harmonic_hf, wavetype); + } + + if (max_harmonic_lf > MIN_EXTRA_HARM(wavetype)) { + sample_count = max_harmonic_lf * 2; + sample_count = sample_count < min_table_size ? min_table_size : sample_count; + + if (wavedata_add_table(w, sample_count, max_harmonic_lf)) { + if (!quiet) { + fprintf(stderr, "Could not add wavetable to wavedata\n"); + } + + wavedata_cleanup(w); + exit(-1); + } + } + max_harmonic_lf = max_harmonic_hf; + } + + if (!quiet) { + fprintf(stderr, "\n"); + fprintf(stderr, "Generating %s wave\n", wave_names[wavetype]); + fprintf(stderr, " Sample Rate: %ld\n", sample_rate); + if (gibbs > 0.0f) { + fprintf(stderr, " Gibbs' compensation factor: %+.2f\n\n", gibbs); + } + } + + wavedata_generate_tables(w, (Wavetype)wavetype, gibbs); + + if (!test) { + if (wavedata_write(w, file, prefix)) { + if (!quiet) { + fprintf(stderr, "Could not write to file %s!\n\n", filename); + } + } else { + if (!quiet) { + fprintf(stderr, "Written to file %s\n\n", filename); + } + } + } + + wavedata_cleanup(w); + + return 0; +} diff --git a/src/wdatutil.c b/src/wdatutil.c new file mode 100644 index 0000000..86b5fb0 --- /dev/null +++ b/src/wdatutil.c @@ -0,0 +1,679 @@ +/* + Code to generate wavedata for bandlimited waveforms. + Copyright 2011-2014 David Robillard + Copyright 2003 Mike Rawes + + This 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 software 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 software. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include "common.h" +#include "math_func.h" +#include "wavedata.h" +#include "wdatutil.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void generate_sine(float* samples, + uint32_t sample_count); +void generate_sawtooth(float* samples, + uint32_t sample_count, + unsigned long harmonics, + float gibbs_comp); +void generate_square(float* samples, + uint32_t sample_count, + unsigned long harmonics, + float gibbs_comp); +void generate_parabola(float* samples, + uint32_t sample_count, + unsigned long harmonics, + float gibbs_comp); + +#ifdef __cplusplus +} /* extern "C" { */ +#endif + +const char* wave_names[] = { + "saw", + "square", + "parabola" +}; + +const char* wave_descriptions[] = { + "Sawtooth Wave", + "Square Wave", + "Parabola Wave" +}; + +unsigned long wave_first_harmonics[] = { + 1, + 1, + 1 +}; + +unsigned long wave_harmonic_intervals[] = { + 1, + 2, + 1 +}; + +Wavedata* +wavedata_new(double sample_rate) +{ + Wavedata* w; + + w = (Wavedata*)malloc(sizeof(Wavedata)); + + if (!w) { + return 0; + } + + w->data_handle = 0; + w->table_count = 0; + w->tables = 0; + w->lookup = 0; + w->lookup_max = 0; + w->sample_rate = (float)sample_rate; + w->nyquist = w->sample_rate * 0.5f; + + return w; +} + +void +wavedata_cleanup(Wavedata* w) +{ + unsigned long ti; + Wavetable* t; + + for (ti = 0; ti < w->table_count; ti++) { + t = w->tables[ti]; + if (t) { + if (t->samples_hf) { + free(t->samples_hf); + } + + if (t->samples_lf) { + free(t->samples_lf); + } + + free(t); + } + } + + free(w); +} + +int +wavedata_add_table(Wavedata* w, + uint32_t sample_count, + unsigned long harmonics) +{ + Wavetable** tables; + Wavetable* t; + size_t bytes; + + t = (Wavetable*)malloc(sizeof(Wavetable)); + + if (!t) { + return -1; + } + + /* Extra 3 samples for interpolation */ + bytes = (sample_count + 3) * sizeof(float); + + t->samples_lf = (float*)malloc(bytes); + + if (!t->samples_lf) { + free(t); + return -1; + } + + t->samples_hf = (float*)malloc(bytes); + + if (!t->samples_hf) { + free(t->samples_lf); + free(t); + return -1; + } + + bytes = (w->table_count + 1) * sizeof(Wavetable*); + if (w->table_count == 0) { + tables = (Wavetable**)malloc(bytes); + } else { + tables = (Wavetable**)realloc(w->tables, bytes); + } + + if (!tables) { + free(t); + return -1; + } + + t->sample_count = sample_count; + t->harmonics = harmonics; + + if (w->lookup_max < harmonics) { + w->lookup_max = harmonics; + } + + tables[w->table_count] = t; + w->tables = tables; + w->table_count++; + + return 0; +} + +void +wavedata_generate_tables(Wavedata* w, + Wavetype wavetype, + float gibbs_comp) +{ + Wavetable* t; + float* samples_lf; + float* samples_hf; + unsigned long h_lf; + unsigned long h_hf; + unsigned long i; + + for (i = 0; i < w->table_count; i++) { + t = w->tables[i]; + + h_lf = t->harmonics; + + if (i < w->table_count - 1) { + h_hf = w->tables[i + 1]->harmonics; + } else { + h_hf = 1; + } + + samples_lf = t->samples_lf; + samples_hf = t->samples_hf; + samples_lf++; + samples_hf++; + + switch (wavetype) { + case SAW: + generate_sawtooth(samples_lf, t->sample_count, h_lf, gibbs_comp); + generate_sawtooth(samples_hf, t->sample_count, h_hf, gibbs_comp); + break; + case SQUARE: + generate_square(samples_lf, t->sample_count, h_lf, gibbs_comp); + generate_square(samples_hf, t->sample_count, h_hf, gibbs_comp); + break; + case PARABOLA: + generate_parabola(samples_lf, t->sample_count, h_lf, gibbs_comp); + generate_parabola(samples_hf, t->sample_count, h_hf, gibbs_comp); + break; + } + + /* Basic denormalization */ + for (uint32_t s = 0; s < t->sample_count; s++) { + samples_lf[s] = FABSF(samples_lf[s]) < SMALLEST_FLOAT ? 0.0 : samples_lf[s]; + } + + samples_lf--; + samples_lf[0] = samples_lf[t->sample_count]; + samples_lf[t->sample_count + 1] = samples_hf[1]; + samples_lf[t->sample_count + 2] = samples_hf[2]; + + for (uint32_t s = 0; s < t->sample_count; s++) { + samples_hf[s] = FABSF(samples_hf[s]) < SMALLEST_FLOAT ? 0.0 : samples_hf[s]; + } + + samples_hf--; + samples_hf[0] = samples_hf[t->sample_count]; + samples_hf[t->sample_count + 1] = samples_hf[1]; + samples_hf[t->sample_count + 2] = samples_hf[2]; + } +} + +static void +wavedata_write_prototype(FILE* wdat_fp, + const char* data_name) +{ + fprintf(wdat_fp, "__attribute__((visibility(\"default\")))\n"); + fprintf(wdat_fp, "int\n"); + fprintf( + wdat_fp, + "blop_get_%s (Wavedata * w, unsigned long sample_rate)", + data_name); +} + +int +wavedata_write(Wavedata* w, + FILE* wdat_fp, + const char* data_name) +{ + Wavetable* t = 0; + unsigned long table_count; + unsigned long i; + unsigned long j; + unsigned long s; + int column; + /* + * Extra table at end + */ + table_count = w->table_count + 1; + + fprintf(wdat_fp, "#include \"lv2/lv2plug.in/ns/lv2core/lv2.h\"\n"); + fprintf(wdat_fp, "#include <stdio.h>\n"); + fprintf(wdat_fp, "#include \"wavedata.h\"\n"); + fprintf(wdat_fp, "\n"); + /* + * Function prototype + */ + wavedata_write_prototype(wdat_fp, data_name); + fprintf(wdat_fp, ";\n\n"); + /* + * Fixed data and tables + */ + fprintf(wdat_fp, "unsigned long ref_count = 0;\n"); + fprintf(wdat_fp, "unsigned long first_sample_rate = 0;\n"); + fprintf(wdat_fp, "unsigned long table_count = %ld;\n", table_count); + fprintf(wdat_fp, "Wavetable tables[%ld];\n", table_count); + fprintf(wdat_fp, "Wavetable * ptables[%ld];\n", table_count); + fprintf(wdat_fp, "unsigned long lookup[%ld];\n", w->lookup_max + 1); + fprintf(wdat_fp, "unsigned long lookup_max = %ld;\n", w->lookup_max); + fprintf(wdat_fp, "\n"); + /* + * Sample data + * Each table has an extra 3 samples for interpolation + */ + for (i = 0; i < w->table_count; i++) { + t = w->tables[i]; + + fprintf(wdat_fp, "static float samples_lf_%ld[%ld] = {\n", i, t->sample_count + 3); + + column = 0; + for (s = 0; s < t->sample_count + 3 - 1; s++, column++) { + if (column == 5) { + fprintf(wdat_fp, "\n"); + column = 0; + } + fprintf(wdat_fp, "%+.8ef,", t->samples_lf[s]); + } + + if (column == 5) { + fprintf(wdat_fp, "\n"); + } + + fprintf(wdat_fp, "%+.8ef\n", t->samples_lf[s]); + fprintf(wdat_fp, "};\n"); + fprintf(wdat_fp, "\n"); + + fprintf(wdat_fp, "static float samples_hf_%ld[%ld] = {\n", i, t->sample_count + 3); + + column = 0; + for (s = 0; s < t->sample_count + 3 - 1; s++, column++) { + if (column == 5) { + fprintf(wdat_fp, "\n"); + column = 0; + } + fprintf(wdat_fp, "%+.8ef,", t->samples_hf[s]); + } + + if (column == 5) { + fprintf(wdat_fp, "\n"); + } + + fprintf(wdat_fp, "%+.8ef\n", t->samples_hf[s]); + fprintf(wdat_fp, "};\n"); + fprintf(wdat_fp, "\n"); + } + + fprintf(wdat_fp, "float samples_zero[%ld];\n", t->sample_count + 3); + fprintf(wdat_fp, "\n"); + /* + * Function to get Wavedata - the sample rate is needed to calculate + * frequencies and related things + */ + wavedata_write_prototype(wdat_fp, data_name); + fprintf(wdat_fp, "\n{\n"); + fprintf(wdat_fp, "\tWavetable * t;\n"); + fprintf(wdat_fp, "\tunsigned long ti;\n"); + fprintf(wdat_fp, "\n"); + /* + * Sample rate must be > 0 + */ + fprintf(wdat_fp, "\tif (sample_rate == 0)\n"); + fprintf(wdat_fp, "\t\treturn -1;\n"); + fprintf(wdat_fp, "\n"); + /* + * First time call - set up all sample rate dependent data + */ + fprintf(wdat_fp, "\tif (first_sample_rate == 0)\n"); + fprintf(wdat_fp, "\t{\n"); + fprintf(wdat_fp, "\t\tfirst_sample_rate = sample_rate;\n"); + fprintf(wdat_fp, "\t\tw->sample_rate = (float) sample_rate;\n"); + fprintf(wdat_fp, "\t\tw->nyquist = w->sample_rate / 2.0f;\n"); + fprintf(wdat_fp, "\t\tw->table_count = table_count;\n"); + fprintf(wdat_fp, "\t\tw->tables = ptables;\n"); + fprintf(wdat_fp, "\t\tw->lookup = lookup;\n"); + fprintf(wdat_fp, "\t\tw->lookup_max = lookup_max;\n"); + fprintf(wdat_fp, "\n"); + fprintf(wdat_fp, "\t\tfor (ti = 1; ti < table_count - 1; ti++)\n"); + fprintf(wdat_fp, "\t\t{\n"); + fprintf(wdat_fp, "\t\t\tt = ptables[ti];\n"); + fprintf(wdat_fp, + "\t\t\tt->min_frequency = w->nyquist / (float) (ptables[ti - 1]->harmonics);\n"); + fprintf(wdat_fp, "\t\t\tt->max_frequency = w->nyquist / (float) (t->harmonics);\n"); + fprintf(wdat_fp, "\t\t}\n"); + fprintf(wdat_fp, "\n"); + fprintf(wdat_fp, "\t\tt = w->tables[0];\n"); + fprintf(wdat_fp, "\t\tt->min_frequency = 0.0f;\n"); + fprintf(wdat_fp, "\t\tt->max_frequency = ptables[1]->min_frequency;\n"); + fprintf(wdat_fp, "\n"); + fprintf(wdat_fp, "\t\tt = ptables[table_count - 1];\n"); + fprintf(wdat_fp, "\t\tt->min_frequency = ptables[w->table_count - 2]->max_frequency;\n"); + fprintf(wdat_fp, "\t\tt->max_frequency = w->nyquist;\n"); + fprintf(wdat_fp, "\t\n"); + fprintf(wdat_fp, "\t\tfor (ti = 0; ti < w->table_count; ti++)\n"); + fprintf(wdat_fp, "\t\t{\n"); + fprintf(wdat_fp, "\t\t\tt = w->tables[ti];\n"); + fprintf(wdat_fp, "\t\t\tt->phase_scale_factor = (float) (t->sample_count) / w->sample_rate;\n"); + fprintf(wdat_fp, + "\t\t\tt->range_scale_factor = 1.0f / (t->max_frequency - t->min_frequency);\n"); + fprintf(wdat_fp, "\t\t}\n"); + fprintf(wdat_fp, "\n"); + fprintf(wdat_fp, "\t\treturn 0;\n"); + fprintf(wdat_fp, "\t}\n"); + /* + * Already called at least once, so just set up wavedata + */ + fprintf(wdat_fp, "\telse if (sample_rate == first_sample_rate)\n"); + fprintf(wdat_fp, "\t{\n"); + fprintf(wdat_fp, "\t\tw->sample_rate = (float) sample_rate;\n"); + fprintf(wdat_fp, "\t\tw->nyquist = w->sample_rate / 2.0f;\n"); + fprintf(wdat_fp, "\t\tw->table_count = table_count;\n"); + fprintf(wdat_fp, "\t\tw->tables = ptables;\n"); + fprintf(wdat_fp, "\t\tw->lookup = lookup;\n"); + fprintf(wdat_fp, "\t\tw->lookup_max = lookup_max;\n"); + fprintf(wdat_fp, "\n"); + fprintf(wdat_fp, "\t\treturn 0;\n"); + fprintf(wdat_fp, "\t}\n"); + /* + * Sample rate does not match, so fail + * + * NOTE: This means multiple sample rates are not supported + * This should not present any problems + */ + fprintf(wdat_fp, "\telse\n"); + fprintf(wdat_fp, "\t{\n"); + fprintf(wdat_fp, "\t\treturn -1;\n"); + fprintf(wdat_fp, "\t}\n"); + fprintf(wdat_fp, "}\n"); + fprintf(wdat_fp, "\n"); + /* + * _init() + * Assemble tables and lookup + */ + fprintf(wdat_fp, "static void\n"); + fprintf(wdat_fp, "__attribute__ ((constructor))\n"); + fprintf(wdat_fp, "init (void)\n"); + fprintf(wdat_fp, "{\n"); + fprintf(wdat_fp, "\tunsigned long max_harmonic;\n"); + fprintf(wdat_fp, "\tunsigned long ti;\n"); + fprintf(wdat_fp, "\tunsigned long li;\n"); + fprintf(wdat_fp, "\n"); + + for (i = 0; i < w->table_count; i++) { + t = w->tables[i]; + + fprintf(wdat_fp, "\ttables[%ld].sample_count = %ld;\n", i, t->sample_count); + fprintf(wdat_fp, "\ttables[%ld].samples_lf = samples_lf_%ld;\n", i, i); + fprintf(wdat_fp, "\ttables[%ld].samples_hf = samples_hf_%ld;\n", i, i); + fprintf(wdat_fp, "\ttables[%ld].harmonics = %ld;\n", i, t->harmonics); + fprintf(wdat_fp, "\n"); + } + /* + * Last table - uses same sample data as previous table for lf data, + * and zeroes for hf data + */ + i = w->table_count - 1; + j = i + 1; + t = w->tables[i]; + /* + * Zero silent samples + */ + fprintf(wdat_fp, "\tfor (uint32_t s = 0; s < %ld; s++)\n", t->sample_count + 3); + fprintf(wdat_fp, "\t\tsamples_zero[s] = 0.0f;\n"); + fprintf(wdat_fp, "\n"); + + fprintf(wdat_fp, "\ttables[%ld].sample_count = %ld;\n", j, t->sample_count); + fprintf(wdat_fp, "\ttables[%ld].samples_lf = samples_hf_%ld;\n", j, i); + fprintf(wdat_fp, "\ttables[%ld].samples_hf = samples_zero;\n", j); + fprintf(wdat_fp, "\ttables[%ld].harmonics = 1;\n", j); + fprintf(wdat_fp, "\n"); + /* + * Get pointers to each wavetable and put them in the pointer array + */ + fprintf(wdat_fp, "\tfor (ti = 0; ti < table_count; ti++)\n"); + fprintf(wdat_fp, "\t\tptables[ti] = &tables[ti];\n"); + fprintf(wdat_fp, "\n"); + /* + * Shift all sample offsets forward by one sample + * !!! NO! Don't! + fprintf (wdat_fp, "\tfor (ti = 0; ti < table_count; ti++)\n"); + fprintf (wdat_fp, "\t{\n"); + fprintf (wdat_fp, "\t\tptables[ti]->samples_lf++;\n"); + fprintf (wdat_fp, "\t\tptables[ti]->samples_hf++;\n"); + fprintf (wdat_fp, "\t}\n"); + fprintf (wdat_fp, "\n"); + */ + /* + * Table lookup vector indexed by harmonic + * Add lookup data to vector + */ + fprintf(wdat_fp, "\tli = 0;"); + fprintf(wdat_fp, "\n"); + fprintf(wdat_fp, "\tfor (ti = table_count - 1; ti > 0; ti--)\n"); + fprintf(wdat_fp, "\t{\n"); + fprintf(wdat_fp, "\t\tmax_harmonic = ptables[ti]->harmonics;\n"); + fprintf(wdat_fp, "\n"); + fprintf(wdat_fp, "\t\tfor ( ; li <= max_harmonic; li++)\n"); + fprintf(wdat_fp, "\t\t\tlookup[li] = ti;\n"); + fprintf(wdat_fp, "\t}\n"); + fprintf(wdat_fp, "\n"); + fprintf(wdat_fp, "\tfor ( ; li <= lookup_max; li++)\n"); + fprintf(wdat_fp, "\t\tlookup[li] = 0;\n"); + fprintf(wdat_fp, "}\n"); + + return 0; +} + +void +generate_sawtooth(float* samples, + uint32_t sample_count, + unsigned long harmonics, + float gibbs_comp) +{ + double phase_scale = 2.0 * M_PI / (double)sample_count; + float scale = 2.0f / M_PI; + unsigned long i; + unsigned long h; + double mhf; + double hf; + double k; + double m; + double phase; + double partial; + + if (gibbs_comp > 0.0f) { + /* Degree of Gibbs Effect compensation */ + mhf = (double)harmonics; + k = M_PI * (double)gibbs_comp / mhf; + + for (i = 0; i < sample_count; i++) { + samples[i] = 0.0f; + } + + for (h = 1; h <= harmonics; h++) { + hf = (double)h; + + /* Gibbs Effect compensation - Hamming window */ + /* Modified slightly for smoother fade at highest frequencies */ + m = 0.54 + 0.46 * cos((hf - 0.5 / mhf) * k); + + for (i = 0; i < sample_count; i++) { + phase = (double)i * phase_scale; + partial = (m / hf) * sin(phase * hf); + samples[i] += (float)partial; + } + } + + for (i = 0; i < sample_count; i++) { + samples[i] *= scale; + } + } else { + /* Allow overshoot */ + for (i = 0; i < sample_count; i++) { + phase = (double)i * phase_scale; + samples[i] = 0.0f; + + for (h = 1; h <= harmonics; h++) { + hf = (double)h; + partial = (1.0 / hf) * sin(phase * hf); + samples[i] += (float)partial; + } + samples[i] *= scale; + } + } +} + +void +generate_square(float* samples, + uint32_t sample_count, + unsigned long harmonics, + float gibbs_comp) +{ + double phase_scale = 2.0 * M_PI / (double)sample_count; + float scale = 4.0f / M_PI; + unsigned long i; + unsigned long h; + double mhf; + double hf; + double k; + double m; + double phase; + double partial; + + if (gibbs_comp > 0.0f) { + /* Degree of Gibbs Effect compensation */ + mhf = (double)harmonics; + k = M_PI * (double)gibbs_comp / mhf; + + for (i = 0; i < sample_count; i++) { + samples[i] = 0.0f; + } + + for (h = 1; h <= harmonics; h += 2) { + hf = (double)h; + + /* Gibbs Effect compensation - Hamming window */ + /* Modified slightly for smoother fade at highest frequencies */ + m = 0.54 + 0.46 * cos((hf - 0.5 / pow(mhf, 2.2)) * k); + + for (i = 0; i < sample_count; i++) { + phase = (double)i * phase_scale; + partial = (m / hf) * sin(phase * hf); + samples[i] += (float)partial; + } + } + + for (i = 0; i < sample_count; i++) { + samples[i] *= scale; + } + } else { + /* Allow overshoot */ + for (i = 0; i < sample_count; i++) { + phase = (double)i * phase_scale; + samples[i] = 0.0f; + + for (h = 1; h <= harmonics; h += 2) { + hf = (double)h; + partial = (1.0 / hf) * sin(phase * hf); + samples[i] += (float)partial; + } + samples[i] *= scale; + } + } +} + +void +generate_parabola(float* samples, + uint32_t sample_count, + unsigned long harmonics, + float gibbs_comp) +{ + double phase_scale = 2.0 * M_PI / (double)sample_count; + float scale = 2.0f / (M_PI * M_PI); + unsigned long i; + unsigned long h; + //double mhf; + double hf; + //double k; + //double m; + double phase; + double partial; + double sign; + + if (gibbs_comp > 0.0f) { + /* Degree of Gibbs Effect compensation */ + //mhf = (double)harmonics; + //k = M_PI * (double)gibbs_comp / mhf; + + for (i = 0; i < sample_count; i++) { + samples[i] = 0.0f; + } + + sign = -1.0; + + for (h = 1; h <= harmonics; h++) { + hf = (double)h; + + /* Gibbs Effect compensation - Hamming window */ + /* Modified slightly for smoother fade at highest frequencies */ + //m = 0.54 + 0.46 * cos((hf - 0.5 / mhf) * k); + + for (i = 0; i < sample_count; i++) { + phase = (double)i * phase_scale; + partial = (sign * 4.0 / (hf * hf)) * cos(phase * hf); + samples[i] += (float)partial; + } + sign = -sign; + } + + for (i = 0; i < sample_count; i++) { + samples[i] *= scale; + } + } else { + /* Allow overshoot */ + for (i = 0; i < sample_count; i++) { + phase = (double)i * phase_scale; + samples[i] = 0.0f; + sign = -1.0; + + for (h = 1; h <= harmonics; h++) { + hf = (double)h; + partial = (sign * 4.0 / (hf * hf)) * cos(phase * hf); + samples[i] += (float)partial; + sign = -sign; + } + samples[i] *= scale; + } + } +} @@ -1,16 +1,169 @@ #!/usr/bin/env python +# encoding: latin-1 +# Thomas Nagy, 2005-2017 +# +""" +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: -# Minimal waf script for projects that include waflib directly +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. -from waflib import Context, Scripting +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. -import inspect -import os +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. -def main(): - script_path = os.path.abspath(inspect.getfile(inspect.getmodule(main))) - project_path = os.path.dirname(script_path) - Scripting.waf_entry_point(os.getcwd(), Context.WAFVERSION, project_path) +THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +""" + +import os, sys, inspect + +VERSION="2.0.4" +REVISION="7cbb714529fb8ebf6acd59fd281ce525" +GIT="x" +INSTALL='' +C1='#/' +C2='#,' +C3='#*' +cwd = os.getcwd() +join = os.path.join + + +WAF='waf' +def b(x): + return x +if sys.hexversion>0x300000f: + WAF='waf3' + def b(x): + return x.encode() + +def err(m): + print(('\033[91mError: %s\033[0m' % m)) + sys.exit(1) + +def unpack_wafdir(dir, src): + f = open(src,'rb') + c = 'corrupt archive (%d)' + while 1: + line = f.readline() + if not line: err('run waf-light from a folder containing waflib') + if line == b('#==>\n'): + txt = f.readline() + if not txt: err(c % 1) + if f.readline() != b('#<==\n'): err(c % 2) + break + if not txt: err(c % 3) + txt = txt[1:-1].replace(b(C1), b('\n')).replace(b(C2), b('\r')).replace(b(C3), b('\x00')) + + import shutil, tarfile + try: shutil.rmtree(dir) + except OSError: pass + try: + for x in ('Tools', 'extras'): + os.makedirs(join(dir, 'waflib', x)) + except OSError: + err("Cannot unpack waf lib into %s\nMove waf in a writable directory" % dir) + + os.chdir(dir) + tmp = 't.bz2' + t = open(tmp,'wb') + try: t.write(txt) + finally: t.close() + + try: + t = tarfile.open(tmp) + except: + try: + os.system('bunzip2 t.bz2') + t = tarfile.open('t') + tmp = 't' + except: + os.chdir(cwd) + try: shutil.rmtree(dir) + except OSError: pass + err("Waf cannot be unpacked, check that bzip2 support is present") + + try: + for x in t: t.extract(x) + finally: + t.close() + + for x in ('Tools', 'extras'): + os.chmod(join('waflib',x), 493) + + if sys.hexversion<0x300000f: + sys.path = [join(dir, 'waflib')] + sys.path + import fixpy2 + fixpy2.fixdir(dir) + + os.remove(tmp) + os.chdir(cwd) + + try: dir = unicode(dir, 'mbcs') + except: pass + try: + from ctypes import windll + windll.kernel32.SetFileAttributesW(dir, 2) + except: + pass + +def test(dir): + try: + os.stat(join(dir, 'waflib')) + return os.path.abspath(dir) + except OSError: + pass + +def find_lib(): + src = os.path.abspath(inspect.getfile(inspect.getmodule(err))) + base, name = os.path.split(src) + + #devs use $WAFDIR + w=test(os.environ.get('WAFDIR', '')) + if w: return w + + #waf-light + if name.endswith('waf-light'): + w = test(base) + if w: return w + err('waf-light requires waflib -> export WAFDIR=/folder') + + dirname = '%s-%s-%s' % (WAF, VERSION, REVISION) + for i in (INSTALL,'/usr','/usr/local','/opt'): + w = test(i + '/lib/' + dirname) + if w: return w + + #waf-local + dir = join(base, (sys.platform != 'win32' and '.' or '') + dirname) + w = test(dir) + if w: return w + + #unpack + unpack_wafdir(dir, src) + return dir + +wafdir = find_lib() +sys.path.insert(0, wafdir) if __name__ == '__main__': - main() + + from waflib import Scripting + Scripting.waf_entry_point(cwd, VERSION, wafdir) + +#==> +#BZh91AY&SYÝÚcš¤ÿÿÿ°ÐÿÿÿÿÿÿÿÿÿÿÿE ‚„ 0Á#*ˆ¨bD{Ô´@#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*\ú¦Õ¶£XkP;šK²j¶WÝÎIÓi½Û¶ÍQ«Ðj®ÌÞpä_xÜú}xk{o»S©KÕ{w¾^÷Û»çsµ“Ox¤Œ€#,i¥ënî¶#,ܧ*ÞÀâô»vÏvw-¹½†KÐß;<Æ'»v6õÛÀî{¥uökÂYJSÓ»»½íóÛï¾W½€õÞ×Ç‹ÝÎÝÞéÜ#¯½XM·ßg#*#*#*#*4o`›#**¸¡ÃÓ¡ÝÍîà#/{³Ý0ÓÛ¹è;ÙG–ë Ð4(ë¾õí£röõéé£G¶ »ÒB¨¡‘£l=ìp#/ª¢‚T¤€ ¹ƒvÑ$ºÅP¢…$óÝ×mì#,PÞ¾ÚïMhìÃëîÏÔï±åÜ5ͺé+“¸+v0Ûˆšë®÷ßuסõví#*]»î_v«§¯MïnºÔx9›Ü½Ï5õ’{y̻﷧·¾ÚêúÙö‰»rõöÞž·Ývs·6Ù³¯q›¾÷»GEûSÞŰaIU$E ô#,[w6š£ÞÎöwunÝw'mÖƒÒã'»p{eÓ*"•Sžï{—è#* iTˆ*^ÁȘè¼ÎBãh÷»Öñ«E÷»î÷{¾gß}÷ÃÈô}€i^ùÎH´Ç§rÊ5N ô#,ÛÞ»©VÍd¾gx÷AÐ{yíx4×ÜæàÎXúN»öq×G»jöó{Zè‰í÷½ÔUO·vîgÞ< =â[iâñkâ>åöÛwUºwF滜ÜbÇ^÷n÷{»£&mßcyV÷.뻤¹®îRíëzò¾ÕÜÅ ÖÑÎæmÛ¯phØ»zˆÉÐÑÎÁkSkÎ7¶ë>·væÆíÇϽíï=ì{ÛêÇÞÞª½‹î»ìÄïu³˜¶ôdz×{Iæ½KÍÚ.Ûsx¶#*#,ÎÙz÷µ:·±öw±ÞÝÛWŽˆP (* ¨„’FÚÛ—iÐ娥Z#,Mlλ})îô:íäé Ú7q›oO+Õ ©Û•”SŽ^=æP§{ÞºÝG!»&o»¾ÛÍð#*ÕÔ€#*%o=ÛtæÝ÷7/|ö]Žw•÷]Û}Æö½ÝÇuÇc}Ö™Ï{ÞUÎé#,º÷kÒïpzù4úò9zÏG•˜6&®tØ0eb¹Ý·×lxœïßoy½mŸ#*I:2öãGk#*÷¶xtûg§Õ}Á£z.Á϶ç³ï©¬ÜÛ®å˜fÅæàõ·mßu³ZÍw>/sË«+:íç¾¾{壹ÎÁ°3]ÀäôÝO{nÇÞiåiï7nº®°G.ÓÂÝ/T·ws«™:oU½³žÎ`UompUVž÷;2½{³Ë0lzÞm°‡wŽy§W××ßGÛOœúö#,ñîÞÚ’¥7rÝöû¯sã7»tÀ€ôÂìnLjW;±çìÝš{ܰ^ðiÕ5¤ê·.ׯW†}ç»ë€n·ˆ@èšÅì¹@zíyWžÚûâf¯ºÊ¾ƒ #*èÙîó^ç^÷ufØg[Þ+“³5Ø…g·¦¹}îW¯.·[G‘¨Š*Ý9ªé;iJÙÝÚûóZ™÷}ëÆuYgÊÛ‘&3Ùç#,œÇSß-Úñî‰îri5¾¨Ù[2}ö×Þ¹Ü0SY¯{·gs¶'=㺆_'¾÷;>ÖÔ`;wn:xº¼¼o(÷6¯·ÅÁ¦ˆ#*€@4#*CF€y4hIéLQä€#Ôõ<¦‚S@„ òÕ=¦©ú§”ýQ£Fž£&F†Pi #*#*#*#* ˆMFiO"SMSñM¦£Òšd5¦›ÒCÒh#*#*Ð#*#*“Õ)"&D#,E7©””ôÔÓA‘ #*hzš#*É#*#*#*#*B#*#*ÈÚhLbOF“52jyOPd¨#,#*#* 54ÄȦ#B2)ä'é6©êyOHf£Ôzƒ@#*€#*?þùëÛV»‰]΃r¶®ä¿NÕ¥Ô"b#ãµkºA0Œ…¨Õ–Ù—½VÚåmµFTÅ ‰î=¾ÿu±î¬^þò^X¬WjÅZÆó!nžoôÚåÉ.ø®\ãxiqªøÖ÷r¶^A<é‘1UnÐ%_ЍD B# Gg[ñ&üZüLY©wsZQǬÜÍ—g8âZZ®fø3$7›×SY¾ªb@ˆÑ>ýÕ·äB·Ä(R1Xª#/De[Y6Õ™¶´–µbô¶×!jÔD”#/£Pd£!\ç9a (ƒ¡XL#*¨9D,¨EÄQ@õÀ #,‚Ûi«Wv§E±X·µÝµ&ÚÖÛkß[m¶©™™%šM16"X ¢Ii653%„Õ2Æ@3JQ¥ÛIŒ4I@M-KE±¨0¶ŒÒY4²1a-„#/61R”i#*5K4ÅŒLb¥bÉ›H¤Ù-Q%–ZSµDBËHlÐL(ÍF5£QZ0#/ƒI²"„©6)Œ” †Æ™¦ZF0"”Ú5)FÂ[M¶²Ö´ RT3bM™&BQdÛM¶šmjJ6RTÖÆZ–Ù•2Òe2Q#`Y¡ÍY¢’RÆ‚–E1L„ÆÐ‰2¢Í#h¤ÂX¨BÆÅ&¤1šTD)ˆ£b…ˆÊcÐÈŒ’6¤Á‹,D³4%(@D2’R4iY@fhÈ ‘DRÉY61£bZEˆd²‘cYJHM‰)20R‰ŒšC1 ©4iŒi2²*,I‰™KLE3#*ØÛ$3b$Æi¦l$ÂÄmI° ,¬!$”›DDšŒPRBX‚DÑ ŠAD °TDÃ(c$¤#P™D¤¬jf£b°–“RD“ˆKJT IKbH²Ì¢‘fI¢lÊDlb$Ø™J3dL6Í1’¥,XÅHli¤4b#R²Y#`²¤&‰²HH&¤DHÙ¦¤-BHK2›(ÊZ)3HÚ#AÒÆ‰mL‰#,(4–c!²RYLE‚i”Å(£FaƒQM#/LTH2HaRf0$’4hÄD†XLPFÉ2¦f¬ÆŠ¥*‰DLÈjF˜…"3b¥#,²š6HÑD¤’M’(ÔÀÆM›#S4XØŠi2“2˜¥‘•›L‰XˆÁS2Ô¤Ó$†2ˆ¤54Z[FÍJ”É…1)#$dÉ)Y4XÉXŒeIÌEcI¢M&Êj6ME’H¡¤l ˆÆ –Í&&ÐhÑSi ¤Ê(‹fCfD’›%24 ™²d&¬ÙXµ’ÀdÄše’$±mÆ Ö#/e°¤I„£‰”jK0”Í4¦#,’²šS&´hI1JLf¡–M‘L)eF™aÒ ¡)3F‰¶ÔªÚ0IBjfŒ¦FÍ(¤”ÌDVƒR–À¥š,Å&˜ÊË*l²lA¦[fŒL1MˆÊQ,4„¥¯ÜktBjj‘FŒÚ(ÅF¶ ’hÒj6²H¥”¨•#,Ñ4´…FÆÂ6I¨ÚÈŒ´j2ÉŒ£$YL©1¤A†&f”Öf¬bM*ÆÔRŒšaÆU$™‘šÂÆÐ(iYE2dËI¨6,ÛE±HÑSeÚÈ™dU1¬ÔS#/lØÊLͲ[M,&4mh±dF¶M2²%L²›Y5¢›e)M1iŠÔ$d¤mEŠVX“I©%*#hªÁµA£Em*"Ål[I¬”[Q´TTš±4ÉbÄTEj,2Ñ« ÚM%#,šÔ0’ŠA6ƒ-)&)Zk±£i‰¬j’Á¢ÚH-S[lÓJ¨HL¦jjÉ¢M‘‰”´Š,‘[RÖmŒR›M²Í*c4Ój™m¥RÉ&f©R1f˜[BA™’e²Æ„ÓÒY6ÊÊ´kD²ŒaF*,H`‰˜Ðb“,,D‰Ú#, ŒCe´ÍS0!*(dÚŠÉ4ѲdÑE‘#,–)ÙH6DVjE‘™’XRQf)˜š…fHDeb›I’ˆÆ²#*%!¦DÉ!¨É€ÐÒÆQ4š‚ȘZBh2PËEŠ&”Ȧ4–i@Ö”„Lb˜JY&Y!5Œ‘Q¦ZŒQ³)$£ …Œ…Qe+#L6Š“’Œ›#RE¥„Š2mFƒFÌdѤٔٔ”³6™IX¦#,#,HÔC’ZŠ£f´fˆÔ4T¦“a¦6XÖe£@‘Œ„LR#,16$©-&P£e4ÅI¶JeF ªeM’ÉL¡1Q&’@D¡¥+2KhÚÈ…¦f@È•a!²ÌQɱ³HØ£D#,f“d36&"jHH54[ QQ¨£±™l4˜b„”24²dlb”Al ¨+,²Y…X´fJl¡*Hƒm QXÑ&‹¥Q¢ƒb‚#&¤ª5L%ÂÂ#,R”51¦l¥Qª#Ji¥¢‹d¶dZ$Z‹ØŒ¥U-4UÆ“E’Ä‘M2•”+QH12J›ˆ™¤«Q°IŠ™¨©-0¦,ÒÔd¬ZÚLRViT‰DÐ6%2”Ô–$’ÅIFÉ¢HŒIT”†¨¤™cVd#,5R¦TÄSmIY-’4…4“Q ˆÁDÙZM¢ÙI,l˜ÒcFÑ‹’FÕ(K-б&ÖŠ´e(ÚJ©BÔ[F¤¢Å"š$¦F`Li©PjfÉ3j5IbÕ%K6ÒkBV€‹cRTQ$[b™¶imEccZ‹m&dË(„²ÙX–ÑTY•Q´ÙQJj”S’ƒ#)52P64X"M(ÄÒf±¶53bH±I[M²šk-FѬf‘¨ÉF‹%¶ZÖ)*1%ІXÑQM$21’U±m‹LÕ´cZËISC-l¥’Úš›d-¨ÓV&Œ¢ˆ‹FÒJ(6ÍI¨Û›6TE ¢1$™I2#"ˆÈIÊÙöÿÕ©?ÙüTþÇ÷žf„ŸáþPV‘ %XÀ=–¾+ûZ=5йX4i6zºõ:Å\kû¶,bƘ5#q’÷ofªlþß¼‚6Ñé¢;ÜœbQ `ÅA‚áÑÆ—DÕ$ªªª‚®Œ¤{Ïãê½^Úÿ5ÚËñ.¿Ñýž/ò6ÚkÆ@nx%„ŒEôsÑ£ýÛlvÚE‡¯×N-ÁÖZX%'uÑÝêŧlNNï2##‰F61ukŽÏEcýÓ—Z|Ä£'ütz䬚€I¥áv7§^šèÏepòrhë²wB*35S4™³(¶‘Vª©"ñן‘Ög5r#&ÃßµÌV÷x3Fe:ãK™@¤¤)€‰$HÅæ×bÈkÒ3ˆ`Wd@ÛLå¹dfôÜÒX,‘’‹×ž¼†@Öö¯þ,?ÎÀ7p‡ÓXѧÐnk¦Ä¿2æ’Wz H±b‚>ï÷Vˆv¼^˜D˳b(¦¦Ð¤Y;øä¬±É"˜Ò¼lÑ1ʤ”á÷éW‰AþáÄ,x»¡j4A¡¬°Ý³Ü}Ÿè×§C•=”+9P[îãF€ÑÖèæî]P ¬smžbŽr車esn–CEsnžw6*'×uôKol[í~…x¿\Še|\ŠÛÅÍã¤Oöµ^9ÍÂøüûZë¬;÷Ì!³iå”#6Ìzeq#,¶Ó`7¯ÇçZ÷oOvÛsI´guÊ<sm±‹ª#/CLÕ‰l¦h…0X#/´£®¹]çv9GJåÌ”RëºH‹M14 eÔÿ¾qf©‰5JE èQR"ÃR°ZwmŒºdâ2Õ‚¿*)ÕSOÖÔÁ¥mOÅ鉼"WûjR2sÓª€¨â¡ÿ"j˜ˆdf$“í©‹™4¶‚1Æw×Ó8æ†k–¹¿úG ¡cŠ"©l¶‰÷UuÞãb§z£MzõØä‘A‘LÞ³‚‰àK+:+«'ß«æ\§0rpÕ{x˜F»¾ôfÚ]FrÅ|OªÎi)—Ÿ‡±·ÝÎgÚѬƒ#/Ô`òªŠS÷kõ¿SžwÐÁíNÍÚÝ95ò¨STëF¸ÚTj/&[:5䢒~N1mË&³!<ØY*2®ŠVe‹)…°´æÒ wQJ#/9Ï+ÇÜü±S¢¹Hº&¬²ª>Ü]Á¤¡ $}Ì¡_hM>]adMŽCRßó°úš¬[Òé™ýGhfLRùõ×ãë¢:eˆošÛµ|Q8((UFx¡ÄZXÇ-'“3{iXžlï‡áïºÞ½ù×SFÈTQWË&£xÚ¹Vÿk÷{y1§ÖêM¯erÉ„ýç×üÞ¯¹íÖ)Ý[›JOÃùþmzQ²&1‰$ÔR|Ôa6àAqŠ3Éž¹`ÎÞÍ;–=.4\·5ÛÎû7¯[”’ÚJ‡½Ü±h¯×-ÖEõQKH ¨ÎTi®AOh•WG\£bѲUô¾ú¼bÐh$òhUE‚‘v£×z{q^Zms#*Éójb¡HÓ–µ%ˆþ5]#/"1Íkf¬üL ‚õ´>º$¨ÅFHŒŠj lÖÍL+ž÷/#,A#”…K–¾<êäåÓkæå—à °dÕSƒºTx¦7J)”"’ê)ë½ZÈ߯®x:&þ”äå—§uØ1fÂj/•×Eñká+Æø9i-Ý“…âb-#/ŸÆ(ÑÝ¢4¶ÒÓV¾Ô¥Ý„S²ŠŸFÇÉlV–ŠEFRpg©˜L’5ª:T ©:ö·çAëÛ? {áÓ%Yáðçy7¾ø„jÅÄ(‹'/õYêÏ?®!kÁ4ntáAb3Q½ç˜wEúC<Bc²î 2‚Ó×™%lœH:‹k•II˜Q™F”ÏÎéæÃâ»ÉÂvCPIÝ…;´CþVx¾T_^àé;Òwa¼‘òÕZdnDF"#âÐ<¨§¥M«£Ût{ïžûð³…QÈz䬥tñÍûòP3T%!«enbÞçÜÕu6ãZ÷Ì$¹cr#‹4Ñ,íaöå¦È0ƒg‚Ô†~ô[»ç ú>Zo_9œTbtNlžLÑÛçÆÎxQçTîPëUæPœ¹ß80âè¢shú²…;Óõõ¾¿“©¨Í‘0Οx¶ÌµêùÍBúgŠä¾UPµ:ƒÆq‰=Þ”§Óh„PíOÑ‹!jÂ3ÞOzüÚÌ8`³a#,îBÉô;¨#/÷#5K~5Ûa$^l¡zÇóŒf:ãÓ4KåQŽÑ©1é}©Ò‡Î\_'„W¯ÝÆoxÃp‰z27W3†\2¶çhömï)Œ®O±R4?¶c²=vñúöÖ˜jV£_–RuÚvT9¥ ,U†(ÿgÛíîÉ ¥ 6bᓺª]§Î0+6H#/B…!¬/;©Èä¶.<Ñ:zxºº/숡ÇL!ST×ÂŽlÏ#/Òè)ø³®ÙÝ!ƒJ‡Õ-"܆0#+‰È£×á”Æœ‚ÊØiÐztVÐÞu™ú¦Â>®þwµÕHا>®G豑ä=×”ÅQJ±Üöݽ;,š<ê¦ÙÓÅÀ ŒúH&ÚÛ:á1úEßNœÕáÒÖ«ƒ¶*#,·©4ÑãÔâí4<kÜíÝBAopÔ¡x4ða¸v”„ÿ²àø ¬¹×¾*ߟ‹áã²IeTÓ·á×KIóëJEÖ• N¿)z.ÞGr\ÓÒƒºùsŒ_©¨ì"~;ýHé³ÝŸ9ñé¦q„ÜŸ˜„±GßÛŸ‘Î×T -ñ#,®>.™iÍÈùœ @ï+[qþj/m˜ÛCZÐwÅ"œ3vDsSBþ?*ŸÌõéÍÆ£µœÍ_}7íöâúd6CU"¦é>ù_×ÞzúW^¾½ÌI0UJÙ²…D©}îño?¢i÷;Ü®½uؼÙKÛP @ˆ¨‡Þ”)†Œð²Ýšòi™euKTW?ùl²*‹¡<*<ïúî¿'òÿ®êZ|ÿ?ÇV¿¢¾ör[y'ÙEZ((ªE¾Ê)Ÿ6x ùöæñÇòûp«ž•7sf±GrŸ¶|†ØíĨ{«K$O÷šÛWʸIM¸—ó¤`ýU55Á)™ïÅÌxÔÒëæ—aÃLlÀY¬ÒÖLa>ìµ»Òf~T”þGÈÏ]ÃE‘¶Î¡B.¿4»)†¬û“«•Y–£ÎÇ,e„?<®Ñ^ÓÌä‹“„¿Ž„`Ýf3yÑüé´,ŸÄw[ºÄ8G àDL4vzÖèã¥<6ÛÃ;rûì8°:°(m)UER`gìÜ}TT^&j¬#/b‘dm§eٜǟfá£øuuO»~Ýð=´B(û˜U^;vŃ8™“֯ȱ£Î(×ÔM¾†ý‘xôܶ»°0¤NóOÖâmL3Âßi™e×´”ˆv³åì––%#/]L‚޼Ü厰¡Hlê!Ð~7=ÓjøqC"±*™—Í®£† ÁáPË|o|Ã)”…FgÇ‘Œ¦_bBøÕ/krSÛåµÌ>£çF7̹–ÀAAîÚ€»Ó]¼kxÌÄES#/z¥¶×eÝ0ðMó HêÚbØqJ}™É)I¥t½›“µ™!ž"Tm¶³óUAä>6ƒ]¬ŽqœÔc8`Bü©Ùâæ½zÙ¨Cà Æ#,¾•OnlàÊTˆŒ^•%"Ñ[z±|ùÙz'+?Ù<*š#,°;–ž)rÊPV&ìêÊŒ,¶sÛnÏÝÃdt¾Lo˜aÄ4VÍ2’q¸ùö÷ÙAóÄMX¿$™Ë+£–ާô[þ‘&yÖYñ¯;f™Š+”ßcŒã=ºrõãƒùÑKêìæÏH„ÈánÇ+Ò#¯³Ô΄2L‹J\85ˆ±%®ƒ±ØOÿuؽ;®wyÑÌqÌâGag,¼¦2:LçÑeEÄãçN,ã¤á¾tß>‘oÛm鯙¥5 ËÚcÉ#,3D…D3[ÿ1g¸øhrÁB(ªÆ¡º²,é8^Õs5¯˜Âa#,…‚+Tîºûºiªö›[ž–Lýî×—DîK%ws«å’Pýóó(,EYoUeðÍÍs’[ËD8Y…B,U„Ò‘Ëö!£v²¹hð°*/Ò´)R-šÔ¸¹–¦Qä/g1$†.º´ÛÅ#,øÑ‡ƒ£†Ü'‡@»J?‘”èЛ+êž_žã2@Z¾n9wiL„Ïáå4%å:ÕQn:úVfXʇ½¸^{ÎzÐö¢Vòã`[¦ü·vÇêzXT/šÍÆß^ñ(œGo,¿‹ô»©ûLH…¨x±D|eðåïÄ«ñåp¿žPOlÙ…äRª9Ƥ®¦Ö}RQŽ®v¸öz>¾<ÁÝ)óvØNéÇp¼;)¢8¶>å(ˆ½1ðÏ»2“ú?vºúÖÇ,ë<Pú<ߎ§íûq#,®‡Î}ïlíüñzµFN!µe±V&5Oò‡bð¥Óžc¹ŒA÷Në ²™c:–öQŽukB…•TpòÅÉò@WJøPy=½ü2ݘ÷̰Ò#,j¤¾^Þ›ð!œ¢íûhÊoÒ3c®4äDª¢>,`Æ®;[’èõC®¹ÓL7ªRðÕt«ÁOÅ”¤P×^ÇMjë)oáTøs¬ÚÏ-ZëüÝ0aC7rs‰Ôs¦÷^º§«÷2mŠu¡V±F{(–‘‡ƒöü(õæËMêéÝ,ð*xC¡„ªb߬7i [;H–§R9‡B^×ó¿;¥wV—¿[pØœgG¶¨™åYTòXGÃmw’ sÁ&sµÅ¯Wkˆ< ”%”Ö˜÷YGòV‹|C—ni<·ìˆû“ª½Aq«”®Ô £SÖbί¾,g_¼soøUÊlm‚‡nü?¢(†‡ð¡XÔâFŒT&]ªËÛùþüO3J;Y¬ ‹?LÛØ•U–'+ !¨I+ˆå϶ƒ*~‡‚i蜣)àÒ§$?}nÍOh¶}È]ë»òï屌W«TñMœÊˆ«ø÷{·rfª•ìͼ)òN/ÐvSo¬_ëò¬¾Ñh6C¢9OU¾û#,;ógz„ͱIüuró¯ñ£3?žÎÜÈB>‰ª[o®øíAúã-ýú˜Ê¿xQhVô¿•M–ÿâwÔ¨bj•Á¢†plXŸ/£oõsÒ`Øßf5Ÿ^éŒÁÇZ’¹Þ‹XŠ"ÍÙ]Ù W,V6¦ý`“õ0+ÖºòáàÄ£÷¶n‚~ʘM{ò`²ÞF#/ò®vP¢}Sµ˜ÄæÛXñÚ¸s,³TX*#/‘RlÂOÀ£y@Q}xÒ#*ùúv¸újWë4梌^lM(k•‰ðÌ"s—8ñwÎ|±¡E¸ Ýšá9t%2& DbÅbÖ˜ÁŠ•u.ì[а7]J=¹©è”ÌUçèêÌÕAüšì“§flóaÇZ˜,Þª¢pacVBµªæî™œ-B&Zj H³â6U’´ODßTX[¿w?†¸\®èã.j8Ú…Ù<‹>PÍö&ºL®zYÛ.°ú\¢’»¥•Ÿ‘qÖ{õs6½Ýˆ´úMŽ^ì¯"áW`Ø¢f OŽ^ùXÚ6ø{mõŸ#/FŽŽ¹#7ìî¡(ü‚¬}ØßìÃ3*0i0¶ïo N?Lª<M`¨¨šþDÁx¤ƒPj'5$84©Õ˜Î-]Ô=·Z e"35%w[£yë÷=qëªö»Õ)YSWŽÝÛ›Äír)qÕw']e}$XUbŒ'Ö±m1Rßéû|lõŽ@!×àîmøÙÅùlVëFðíbIÄ©$—$Èã%…ëi·ê+oðÛþæ$Œ´GoðôÝ’Þ«süô3jPNœ¾<¸ÆîùžÞÃôôQ¤É«ÑDÕx}ßïùÄÿŽ\¢õ<Š5Ÿ&µ³Ï"Þ|0c?¢¤èLÍ=BÁÛ, îIö0š3ꇃ«/JÑ(×6_}½Õ×Ê2¥1²lÛà“B#,Ÿeã¹52)áÖ3¹oÓ¶24äÕ«ñm®ö-GÕ Ðzµüús®âÛèÄØ¡$çwOË\ÓÄQ¢0`h´0}$@5*øúY(E+êdX(–#/-(Ä8¦D<‡²Åœ[àçò»e¾ñd<Yãz63T¬j^TËâÐý¨¶Â¶„E+=B`äŸcjÎu‹ŽŠD“5‘¦…DºQq{×yS¥ï6höeGŒZ«ó™—‘g¹@‹–¯»ÏVûø¹üÖªiøuxýwv³Ä‡¹÷½jÖËðüÙv@l7’¥ÞEÛv‡Ûô‹¦nö¼?¦³£â×ÚÏ|§Ç8èåèÅHàFúaºq¿‰£4Ú¾×QòJH¢¬¤ÑA&ü%ƦíT „#,yQ|¡º+µiþØ&‡wj§‘hÒü’G²Ìüñ#,×p#,µY;z@å¥mãóÍs4ÑX8Œ ìÎë«‘¿CoÍÁht‘§ü8Ÿ‡‡ŒÙ„wW3¿öݸd#/V#/ÌÑêJoìÍ^^÷‚¦X.ž5‡ª¢šEî®â¬ ·T‡³:€•›Ãì@øùú~ÐÁ`øóßTâùWGvƒë™Âá?Çήyü†Å/_H‰s”÷M³÷|-çD~Ò#,eÔèÏdÁøç=ƒe²°ÜÆm5Jõ‚#/\eÚ´ñKœ" %`ÁƒSg¡2d–TK†ç|õ5ëÏ·„û¿UoÏ”ùeŸ-…ïSʦ¾g(^ÔþØTI@¼3ŠÐIR$0$X=+p_(®,·éµº1¹¯ûoVzÔºýöÇG–ÅíóFzîåV’é(&\RdPù]ƒóï™k…ª¼rmšoF#,1UÌÈúyx«å#Ètò¶ÌVÝT½ƒÛEH3½OȈ½J MFþÝ´ÿ7‡ Ûlq‚@¤¢ÍUcPð®2аp5ÿ5NÞGm3Ñ»[»¼ûØ'®iŽYÄ2‘Kóm6àö‹þýŸõ×e#>ì”Rùrñ¾#/é€Ù""0=ô õÑÓèÎÊÑ ‡ûà†Þt<$!&©ÓcºË——«Íòòí×å͉*÷iÿ4Ãñò®«y±Ö×5Ük@ÛñFŽIS[Àu‘Ùí˜ðƒ@MãÕYÁa@°ð¤#,üÔtÖ2£–—Ü‚Q7ÎS™³%‘,ë¢ÿô‡'ÄJ´rùCONÉ×£˜êí‹€´r¸F–|¦W“íÒ¡½<`u¬ï^·XNźiDb¼·ÍyÔgï×(í«ê„]G‚ä£P¹ab‹¸YŠÚ:DÀ–¿» GA~;Zùf@¿ôGIÖ–DyÚí ÝŠCK6»ÕyµÒ>í®{•#,^ÈìHÎ#…jž1{D,êœ_âëa®Jƒ`Ä(…F¶r”/r³Å~ztÄ›Ðt¨&ëå¤-gÔÛ…X[ÅŒð6ÕDnvôÏŸÃ–ÚÆÍ@I‹óª']¨òš+'^ç¦x©CšnC{qe¼‹,#/J"\ÇoÚõÁÓŸ:î;Ô3À!ÞåÔ:ä{p^ÍZ2r]pé"³¹”8ôã lvŽ…±ÊOúk[œ_ÁF×Q_Õœ€‡>°:怤ï–ܾ¾L¼H™°'*X>£êzúÀó‘åÿÔÓ‰#£’ï?õ„}ÝLàðBI ‚UmNg³K(d1ëGKÕ“ÄSw’ä“À%ŸÔïÌØaà#r\/*¸û#/9Î[Ùú|ö9rèÞ~•Û»ô¨&ï#,P“/ðý#*”#*”ˆ=¿×¾hOò\·½—<Åvú+¬ìÊÿ.Š[>¦ãâúìù<uÈÁ¦°Iù¬%/—¯ mÕe-Ë¡‡aÏÙ«Õ㪡ÝìÆÀ/_ódp—?2¯w¶Ì">BzëØ½ŒC¯ ܪJ(°!#/,MÔÆy§ñj:”"µ í B‚ 'Óùë¿›ñk‚&Ýêlß`þõè|üq^3mTÇÈ8R±“ôb]¢_“…«[Õÿª#,ÍQGh*"BŽØÝs‡ÿáË3 ×ß*ÊéE̹iãT&b",ƒöŸmH€#/ÞëàæŠŒ½#,£§2#®Øœ“§îõ™œ«¿^ñ\ÿo§ŒŽ¿gÊgôE»íq¦¢‚ÛY à3ÖÿU®‘+ûÎSL|gÔ»68Q4@¹è D.j›tW6!?RÙŽ}«eøäkÐìJloM#,‡êJ#/zdm/v–Æßvxˆf²_Z‚[>zúè)邇ä}®`] Ù«Ù8$üÞÚÂt¨›å—û~pû¿ìÔuÍp¡Ð0-wÂ1ŽûuÃß,{7‚¦f ×fÙSåðÚ¦X¬¾)â ´„ü°sú¹O4@/?Y³þÁ+œ.é$\|¿[Ð#*éþY#P‹Ñø‡¬»-HóMÑôÖç¸.C¡²›ÞßNáö|¾§Œy.®û/ç鏨¦våßbJ܉Èj]Óý’>ë'_ï>¯ß Q¡ô룶Y¡§£áÃ+w]PïœH>ûøzÔ#,šãg¯¢d1H÷ÿdc’ƾ,Õ~B"ÑYñÌ=Ñöôôë×íñ¢ëŠh Š@©Aà×iU€ìróßpn•›Ü‰.ëniü¼sñxÎ<XɺQTéî=9éý+;JkÛ~s_‘ûûñûìI¸eôËAb™ˆ„<ã‚Åÿ};0êœÝúyiáÓ—ù8“§gx`Mj—k¶èAb]—v÷p#üåÅ]]ËAyžßÕ·¯.§ þ;3ÚyK¢ª]q-ÂB`¶¶C»¶Ñü4Y:E\ÀÌŸK"KQ”Óxoîäx`P ’…¾íÎ"”[†Wæš/Pý˸G#*©F!)qIÑfâNÓÏåïí©\ègдãós-çý˜ŠL2Þ9É+D˜#ƒˆLÎo{<8itñͰrµ“@úâÀ@’,~nÿ3Ïb°p–Fmèâ]ðþ-#/!Î#/rfžöÙjµÛëåôt™Diô¢›j¥c´(ñ–¨/ðhªïY‚÷|¢¸ß¯?[³G©-;ìb‚6Ö‰4d‚Û#,¯hªcW¦~ãj#,0Î_ÇÊ©!WúI%¸N¾|µ4°I³3‹ÄóŠ¿›?ûm‰ è·uèCƒSŽª8¶ÆAi*së|ÊF,DÔ3Î$÷M¤Ø°Œ^]~ìœ-¼d7àè‡ÆájN™ü{ÈPe>HË)~Tw’ÂÜ‘Bc~=6ÃaÑÒw÷‰4UUH#/Âr[“EÆçt¾6¹æøÞŽæ"ö#*ßãEâ±ýs0 –#*CÍ%Á7Äý›i\š€T¤Œ=Ú™îÃð«…p2óÎÈzc Fk#iÄî•Ð1sNFÉ÷¯§@ÛJÜä°¿Ei˜£o޾Íiâ½_C‡Ï´ÆïO·ÿ‚vð³¾MD6㱋͗ŸlY,'yŒf)VÕûÞíRzNša£É¤ƒÛ¶©~¥y:&)Þ<ͺ⛪`תËV°…S8çtn_od›å|>839 #,fçÓZIQ³¶ª„±ÈFGF!´ê¾°ÞüßåqmÄ?AÄ/p™Ú7ýMHI%õÁ®\jÁQ3±ñ¸)_ô{½VD¹4›a}“-±Ap"ÆéƯIÌÞj¿ð=è4ß!äi"F/cÇhí8²¿ÉaÆî[õ™M&G>ö)Œ¬Žˆñ⬒…¸ïà7T㦒`h_Uñ?´óA¬¯úî†Jô#)&…4œü#ëÄ:*7å¥6ÂfŽŒ.†žªÅ'¬ÌIL„°5uîP!]{í¶¾¦Á#,ôsÄ÷‚ˆr“$Å.3&=ßÖoÓj“ÂmÓœð;’aתÍcFm=MAbÐ#†éUD`o]h/uãOŸÈ宓¤ h&¬Opšˆq¡Í w)Œ…DË.îrÇÖDTDRÄô©å¡6”\®:`Ìh1ÓJ? q¯-<Ä|*¡´:sk‡åL†=þyÏeÏ@ÜUá*1•E‚ƒVÚ^oZ+bÌC¦AUÎUhÌX5û?@Qè¬@Ô‚PÚ6°u~{f”Õñµ3O7ø(޵jå#òÛÍì?ÛwäÆþ¿Ú?#*¤ÀnóY?ÀÅ‚êBù·ñÌÌ2È3m$þjן˜@º#‘·ihQgbåGÃ<<¸iƒ(‘•í"Q‡f1áEС`ƒ÷-ªÑHÓy©é¦UW‡Þ©F!kj„|:ëÍ;iUâàÎÇ0)1- #*2#/6c=$Ç7jœÜÁ™óeLÖa$A6.”aQAJg}D$ëžÊ:S·EÚ=eépÞÏÂBå:3£Ï¬µXæÂöó~Õׯզ߼ñßD¦?’\,éÙ„h,÷g#&œïÓ[…Ž‹À‹#/#0+iÉœÙ=IÐõ*¶`ûh±†ˆÚRË0IRp´Mù‹„i[”ˆzxž.:à‡F»/(áÁ¹Ýl^ø;Ùßc¯ÉV-S¹ÞgÞCXA·–hîC£.˜sèhr'3u—¸JaÍ–…BPó×O«v)×?W-K·*o7ÍÝtÑêúöÊYÕzÜòÇ#,JBG¬vv©»†²^æþâMÒa-pIÙðÍÇŸ_–5ë€î–Ý.éƒ+Û‘Öê£SÎ*Ë&ßVQdóáýŽš®¯§¶Lí¸¢Ró‘àpLÂªŠ¡®#*ü_ò÷2–Qc>vKU¾œOÎ_å!öÓ>Å=NÕ:ìúÕ¯óG”éÝ·¶¡qmà¦pèÔUØäíS•ÐB}j:ÈP׌Ұ;ÅÝ@{j!Y»dº¡a‰zî×wžKµÅ§ŽÃ1€7H¸msX¢Š<>>zâ°{,ÀæzHófÑ_>WÒ¥zßFãì\ Ã0ÓN„Qdj uT,f%à³Ï3™e˜ŽQ#=š÷`˜š&#,*‘Zi@6²;È™ Ã{†¢ŠEòóò×2lÞ#½Ã,c¸¹hÔ$l;^Õp‘^Ñ¥bÈžÒ‹O(Dþ3²§,v<WGÇò€Êɸפ0u¹VO)r™ n)¤›Õ¤–¡u ÍraØÀ°!ÞÛîp/ÎzDœq“ƒ†á{MdÀ~—µCt·ìçš,0p¨¨S"Ðoœ*ñ“!WTðCyp2b2£k“Æëuç¬4ImÇ0XjkT£®µ‘‘‘éqíÚ+ b!Èj#,§Ôš#çÑᎦ”oöɽªsµmÌq÷÷ôœ”´ìåsþ\ã¡kΔ }°Â±A' ?EÛ``,\;ßGéIHYz$Ìð©2SgÒëdGJZÓoý¿ÞÕäÒ‰Èlîí(PÞ{>è•cº.uYÁ8cÆ#,µw3s³0Ìܤ‚éW‘ÛÆ v+!£@÷jhê1m&pÁD5ÐÔ:ÚdJ0(Ä0ÃçhÐØ‰ý0¨ŒÄ#,¥Ë#6PºËlˆÇYbD0Nè÷Õn)±vö~´ìÿ«¿^6äRðŲ#/2J`±@GPÀÃ.ªº½{õ· ‹cLŒQ`š1 ²e!£%°Y`]Q5Cž[…dÍÐ1‚É˨Eb+aQW¡ÍJmdŠ£h·ÃçÛèõ÷;RîX‹$ê€àÕÓ–ë ¥ú53#*ñZ3+Š12“˜Nó¨ôÊh¦5`±|]£m„Ê—sV÷$ïAÞÚr+q›eeé°„º,å€#*DÅ‘1è¨8íÍ‚pðvîò§òÐ4Ù•NMÖÓÙñV"tpÁÒ€ÜOº5â1”A”ËÃF±ýÇÁÌz,uèý,–g«ë|Ç¡þ~ªŠä6Èò¼„Þö޵S¶!tm#/mD¼ ùHõ£œ¦È³.ŽTKB™m#/Ú)HË#cJX†ìƒ’£[ÔÁ¯«açsÇŸê©rÚÑ8r&Aõ…r®¹Š¥‰ÁµZ¦}òÖnb:^;QM…MølÎÁò»’µgŽSâ7}„;LØA"A#»ãQ'â+v“8Y)ETßB‡ýƒÕº~1‹Û&ÂôJ)—špÂåJÜ£Åâ¤cI·“É¡’f(L| Yœ,gR¯õ¹Ù(@æ Q4°…#/FÌd«lǪ#*cWéÐÖgÄÊI%]-¢à~ÍV’§é5Ζsë´ËÈkrMj’ˆ(©ÂDÄ#,Éâq#lø©.ÝŒ‘ü3²éƒ#/ß°§éÈÁ–btÞ®pš¨¬ãfˆÂuXT¢ÖžÄ±`Œ–Ÿæ÷ÿv{„#,#,^)sËŸç¯øËæ×ÝiÄxBœº¥ri€4ùë:-#_b‘¸….U»1¹÷¾Ååð/:1±zcõ{64#*ÂTÁb%…2lí&YY›9t¦jb¢Â¬1M#µ’Pȳ"$èëE„4“€ë#®bšjŠ1Ò(£‚Þ66 “x†[ü.…ÀMH†Ò+J‡,µÆŠ) PÞ]°J"íECF•‹#¡FFà™"d´©0ÔV†ÜŒêÈÔDcÓ1iHÛb!‹M).É/éçŠÆïã.M3#*œ†„›ÜŸáQMæJ祃Çr+åΟŸ<ùóÇE1¤ÞEÁCJá^°òÔJXÇžt{šî¼ß:œK¬/¬÷Yîóªz §no¶µ|áî>Ú|÷NF7”‚S•"ÝËÐÏùéÅUÕúïµ2Œ£×‹Ü9ÜLá¸ãL–[!§s\†‰`¶V+²ùo.ÊœSïÃ<ûK1Æp&ݱh†MŸV>7"<úôQ·èrÐ,”$¹NÝ®Xk|\ùŸ^ñ{¤(3Ç9§èu!Ç.󎺸Hñ.>Y¦è¤`í…fKLµíQe¤w|«;TD¦»„øCørš›nC¾#/6_)t©òØm²£kÛßTiÛ6nÍÁ€çÄÌVõ£Š‡‘µg"ª0–0Xw$|¤h”èÌT;KŸ ûó:»:/GêÇãÛt™1Üy’@Ê`Ÿæ™]¸‹,.%’?èN5ðÑ=ÛÝn³}‰´†?2Ä(áa0R£è¥x¶D±¯g_>x8¯‹œF‰ÚtõË÷ÆlªuÕªžC’¢Ò¡ó{爽ªcu$\P”`Çp¹Œj¢~yµy玟–`cöxÎÀöìêç‚„Œ"dhgÒèÒÛ—&U¤ˆÅ+5PÅ1{;*ݵ—4þÏ´›êdÚ2‘OSª\¬’TÂ'\‹Ïz@þ½uÎ8dù»ßgÜy;öSÝŠ09ïÅ_×_=¦Óÿh8ˆ:i|)qÍz[}¿ÝÕ/Z 킬`º×ã\!Ñ\~²0劄Ü4Šlr̈;·ºýjòNmÁ,‡[ØÍe˜ì›±¯S®î…#,x*¶™tƒc%hÃwX«]6#W5É6¢·-·MY¥»¬ù{MyÞµÄaŒdv–Èx±êÒ/€¶`ÐD¡’Ö³÷«£·í©µ´ÇOÄ-ª·Ëf7ªÆ°ÓzêéúÖl“VSÝô#/ƒê}CÚͤPO¼)A7z<:ýõ¾ÎUËåÒrô³Oâ}¯ßÒSÐt"Àë*.=#,_TÚnßç/k#*ÓÏuz»@ÍC†°:okª:fu°5gèÃóÜ?wï¼Í¿ÉŽÞÏg½êƒ§•$9Dý08ÃÒüó>'§æÒ ‡³ùyº9e—¿“¹rÐ1ö`€‰i@ š{Óƒ¬å Ô×ù‹µÓê‹OÏCˆŠ7ß_ ÓŸïÜogox½‰{ÖØoô_”¥Œ#Œ±¥ñírÄàJì#/ACšQ¤]q¢½”4|ŠD÷ËküÝ©ãä_ØÓܺ»Lè0IcÝÏÃòý’çìú¸%|Ør#*äEP-F³72²1NÈ#/{Ç rùŸº–0›77ªwõt[KÕg Úœ ܖϯV~Êãæãë¿d¶zH¨µµ ã#,çÅÃÓñzÉSû|¿~+íŸ&bè·¯Â^»ÄÇæfÄúu²Aàjf.*£%^y½#/@ê—Ñgâ2Óu2–©øœ“»!ü%ÙYÉÕõêDÎÕÍô8.Ò㸅UG3ƒ)@Ä«]°±Üµ…»vîwêÜÁÛ¬?ÞM" }Ãþ#/ówˆÈ zŠÞ2‡®eS:¸!61ÐŒb·¯&dt“ÃQµBN€Ó¥Í3ƒ¬}ÿ·wêTe4vëPL_ïZ²ú¿oÃRmûþ¿·çæ·¡RüY*ªUT¦Ž¿6»ð…š©Üá õŸ®Q÷òúß³_£ØfôÈvØê‡š>Œ-ß󷥒¡E±êvذE3jK&‰˜€Í•,eí8ÌMlUýÒôvݨ£Yn¦Š”0)…ª ö~S‹Ú¿¼?´ó¿wÜsãŸWüGPÿ(šo6ç¬ÞpL¸~¼pÚŠ`ª¦’a[Ö)(G#/iŸõ¹–,E`ÅÊ»®Ô³9ˤü‹`ß›8ñúçð*ãÇøy?yþJaÜtX¡EáñŠO¥Sh)Ïç¸Uq>”ß'åV„Ê(ËËHÄÝ'Þ”T@?Ä) J©‡‹à {Ò“ö2MYL˜Ñ#/-óÕËêV¾Ïó:½”mשWËxB ꂈ#/nUECÊ#,ˤµût˜ûg+æÙ©ZgTÅ–ÿmVZøŠÔ#,Ò‚“ª…IåæVÒÿ,D@'Ó- ZWüÊàà¼\É¡¿ƒ’èZ˜s.\e—úå§ñjÅ‹çƒà{K¨ucBfD%ÏyZØ¢Âù ò6·ÀlWoÅPuˆùKJ"K;¡|Æe•ÏGOBäq(Ê/På#/”Š#,«©ÔÛËß™ÏòS]èhl§!ï¦é$<5ÂbŒ9¤À§²Oò¥®+é×NXjÛ|>úæòOš>!(¾T(`£î¹4ãU1R(¼P &ÂdÜ‚ÅZZ‡eÖh;jÿá#,S8êçt¿¥Í'Ú’èãÁ¥œ(èeþF’(pMÝ(¬$*áýv¢,QVÉüéI&Ã7ìÿåĨ {X)::|¾ãîå›kþï6?IæùíþæýŽüà#ìíú~Ÿ¨Yëè_'žgÔy¡ýÝd…¼Ao;¿_³oHÛ;1ˆºØv_hþØðµ63Àð=Oý+³Óòh”Ãõ¸ýrÈ¿#*.øÄJÀý¦¸-‡>p»èGád?Gx}¹wØÁ¶ô“n‰#,]ß².˜€äAÉ2Gƒñw2í¼_×e´§1”‡9½Æ…|tß4½íùÁGåÝ|m6%¨X×Ì¿(§öÓqãøD;‹/!ÖåîÿHðÈÛuVW?÷j¿½ÏÔM—r¹+©‡/ç¤i^4ÆDÞUHIêžÎ¿žÜ¶€¨¿•0c¾€ô÷^¥ïPÊí8jßuÖÑnv5åã( H†T9ðl+œ±pf!žƒ†3”Ñ"RXfß•‹´¹ÎçÕGûû/ãTYÅ»Nœ#òÇÉž¿TÁšW‹§•À馛µlÊï)#,¤)#/¨ó°p¸X2Ö@xä—T]Ṉ̃)iYÂÅ‘ØGÚ;ǬOꈇî÷{¶}zØÇøƒÈR(ÿÈž†ÅãMhª£”¡‡÷þ«Ö¾Áˆ¨ÕbJ`€”˜“Ý:üâ“ÖœV'—Då;ytí+,ìÙ“¹˜`)‹©l6º8•ÑR48¿NBgÆôÕxˆYþè–A#*¾Ïó䆕ûûç¿`FS©v~>}ë¡<®—íiÍ)fjè=WX›2²ÍœÌ/!@W¸1:T®‰ñðÆ{Å=Ö9@ý°:† i9#̳¦sX&ba ’„ÇiWx¨ÃWâÁ÷aô»’Á„•Éa…~B‘F±Â,åå$DF¨ "…àý*©ë]ˆiçþÿ{¤E&%Ÿ Kbø`–vû€öûÓ*ýõOÙF×JÔJ&,«3Ç馬´Õ…D”U2ãb#}=©ýcôw0ÏV6ëÍ~_ÇãŽî:œñ3ÆË€ÄŽ+út0¶jˆbWÖ¬I®˜—¦#/ÕáZÕ|2âÄþ®žOŸçÚ«¢˜#/O9v‹²´´ó«xÓÎÀO¿4»¶ž“ÊþÎ<ÿ‡bÿ`0ÿ-¬#,;ûkúA·óòêC©“akÁ,–0¤´…”À-`!,òO)#*Œ˜O$…AE@7ý»~ó}´„ˆ©jù #*£Ü‰"‚ 2è뇙˜±Û¿·ÿÓ³Çêû¼Üôø¾ï¹Çã6né—ÛÑñ>êe©)³ëûí¶ÎNOWé³Üìç쵂½vºñ§Õ1¤¥«]çEË]Ž÷2-‚~þõï÷Ï~Ûí±ù[£³_ßÛúFi¿wËN_«’ñ W¦1œ´sh›#/nµíü¿ÁùOµª\-ó/§½n_O=ÏÉõh¥õ;Ü5û0råŠû¥7ùH´x;wχNaïÛíü;GF±«Ö[öf!ɧgëýßkÏŒXµ.FO‹céÝ:ËVΟV· Ø>/¾Þ·ç¸exÐ=rañvÉ)¹=ÿÎ_T‚üèô ó¤q#ió}þ¨g%ÓäÚöêϧ\§ÄÄ[Ž<Ãï׿ÑôyÿßœÇZ–¨¦êÑŸ»#^6ûí¬øáÔ¼¸w_ì²mðíòA°…úqçr;¾ÊløáF3…¶xÂNþª8:=ÿ6Ïȵ§£N)Õ>Ïë;ci«jÞñÕ®gº¼û·P¾çÌkXõ?¡Þgä-À-ÄqG:>ä±»«ã;0ß‚ÙÚÑØ<²s¢E§Ÿ÷jùÛ#*n²Í’¶ÎØ›l½€ÝϰƱÙɲ˜—¦Þ,>èØ9;¼û¼Öö¬š¦xã´[·”B.`±s6ºV03/{ž®iû~G8˜Ù§m’w/·Ÿ—öù¸óáçßÃØwn&éc½Þ’%ñü\#]ïúïÃÉlxql÷í¹¡æPÜÅ-“uÜz÷Lpã_}ëÃãº{ÓÖq!ÞŽ :xA<f¬R§»™EJ¸lÿƒžnäø½;Î|¬±®½óì${¹5Œ”u+¿cÆÿ¸&±Ÿ£Óн¿°ÏäóùGÄì˜|ØŒö_IÄwrfñ]ƒE²öwï•ÿ`úy(;ב.9-íÚúvÚîÊÞ½¯¿#,¢ë>¬òª¿Ü¾*ìÂ.õåÁ“íáý<ÒðªwÃ&Ç‘v÷èûƒgé8¨ 5½Û¦Ï?Û7‹ô¶Î]8Ë’Ô—+|C°GE?NþŸÓ\}\aï8gjŽ¯æ¢…4Þdzïú[ðÛÏŸÕÿvæ=ø»ã^Tö‡Ñ h³ôkÚ]§+ãŠ'ú…£ûs«í¾#*I/üLuüÏÕ„zùG'ÏÏý7g#/3£·àï£J,@—1]ÁGf]ß]¿¡Ù#,Ú™}ë`ú¶qwÕÑXÙ³ã–s³Ðõ±£’¿Æÿ¾G#* ãwÁ¿Ï²3ÿÐÐ×úsÐAã#/isÑɇ3<ÝÀy.çòƺïù~/ñŸ}–~nmOO°ý§è?_Ú߸êïÓ·}¸ñŠhî~Ÿw’µ³öZJN¸~¿¸"¤+èûz3øËÎÙ4»<íþ–¦§ñù?(>5B¨¨›€W*¢‚P¤Å]žoÂËÈ/ü'éñÉtãûJšÍ½W.ÇïAf,hB¡€PŒ¿B,u*HG«›àÑ/€ý¶å#*€¢âôX}vj;ÿPû:Ò¬W$Ÿ“û¾ÐŸÃÈ:môö#/}{¿…ýóê?gËžœ;sðò~bæfÙäìØgéžÇ?aßúˆî¿7'Ztë×¥uìøj¿ŸÐjBëЉËú—êO‹ÁA«¸tŽÎì ?Ÿ70Ü<¾?-;ù{#üÆ¿Ñò;¡G¼~#¨w8ᜲ·É(üÂSÇšeqú'²™¯0ñ£ù?CF§[ý1¿ŽZ¬~¥Dp?Í~ì0ÃïoáÁ.—¸on)án½Ýãô¿ökݪÙ߻箷#,ÉÇÙ«wíù¯ì°n#,ÿ"t]OÃ>¹ïŠeÛ)⸨ýÃÔyϳǗZxîa´yÇ8°/XþR@Ö$ OÊ#³Û×ÑËÐÊ> û’Ôò®QÍÏG*·ÂA‡ÖVžh¸#*SøÐmgîåjû‚B˜'毫¿Ž£gN•çñêûpæ¾E¿Öú=<ýX;8r…ÿ“?"ó7Ño^ŽŠ™¯åaê•>rÅ&åv`ú0ðæ]\îýÓä¬É’ü‡ÆvÓÏ4Qô<ßÏøa#,#ˆôrž•QŽœ<ÓÝölëéÉ×óó$µÃ„†Æ 0=òÆÁOŠzf‹U!ûZ'Ùdܼð¯áE¹ù|¶®gXí9®ê/LpÊ׃ çõ-ßêLZOò8,†È¿“#Y^‰þâ'¥¹ƒèšW£M3¬±•ãä‡/¾â÷g+Ó?#¯€iPÇj‘Ö̧×lpzüê%ÙÇñãDºLùhâ,༉tÌàI,uü·‚ÔtŽ›#*‡Ö›ÿ_vzg«ê·ÜˆÑ|=Ü?PÃäî¬8´šýÏèp€-Ék§ƒ¯ „W´y]1üg$ëejŠáÏʲqŸF|]{ì"Ÿ*Êm#/‡- NÚØÃââ+Š'ìnîZåe5¬mŒKÌPŠÔÇöÏkÍÞ<yv\Uõ®½¦¶yô2ùÌpòd65;™Ñ©²[-ãX—Tto®!Õ´P#*ƒºÛl]&ÞIü}¯³Ü’ºcœ°ÃJ¼6‚–4À½³#,¯J#,M‚ýâv™[A¢Wa¢|‘W#,>ŒkÅãWÊ(ñõ™/¥þ[ÝŽ»æM¢H!%'q!;5¾ =ã¼ì=;@Ó¨:Ræns1`*çíã!H£ÌÖ4WŽl‚`@jâ>oáÂ#*‚«ÃâýÖÛõò_ØþñÍA¸wûðì>7ñ‡#,‹dWƒy,¾¦s@±#,ÈÑêŸtDhê:lõ$7ISQEG˜[Ö“‡ÓN÷BC‘Gv@VýviéÑg—òøÛ³¿³ò„0zý_iÖZ<ŽÑ=õø>t-Äôé&LÏİ>2àÍŽó×±{ñù~Î!ÇÙò²eäö#,ÀŽ)“ô[ˆÅç¸j?»Û&ØÃÒy]çѵv¸Ñås?èÃéÉ4ݦýÞ›ý‰ê©LRI͵ôÇŠUòuŒ¤öÆ/ulu³ÜYÌrs~qzúñÂNïþyÃW¶£MþÁ ;Íä‡(#,©%WªL#Ф’-t#,ã온þÿäÉT§>™OWñ¨ƒÙ%<£æú½cmø4£#*þÎylÁ¨6ÇX(àï&4ÿgÔƒëXQÀ2§©QÈÊ¡#/?ˆf@ç9œs×ðwâó®ë1¹[—JåxO¸cf¡ iDlTŽ Ž`¢´T¢M;b4CC™ÈÆ4ž%UiAÆàQQÔÛ`H^íO"Cf®îSVe™ªŽ‰B!ÁR]”¶…±Ø£¦¨ƒšÃŒ4É)5b‰¡¡º¤µY#,X‚0Ì£m¦© qEvz²iÕá‚aE!Â2`lRDuý:Wz®®»‡%З#[!Û¨´%~Ø‹`äY6i´þŸ²÷[Ñß"+œ8ÎHÁ0#oŸöù‡ˆÖ¬µã²ƒy…1>ÿð–†jKQgõçn{#,±»‘Á¸#,+S#.¥!„Àãù÷qý¿Ï}ùú|_ˆ3¸EäÏg™M+h1’ŽŽª‚&q‰Ë$Ì\Ð"JL#,ÉbRTb"aCV ±6Ç#f’J¤ƒÿLˆ* WI›}~3¯ïÖš'¾G—+–v¨¯GÌšpíý8÷K¨áƒ#^¬©|:ÈŠèx¸k§a¶ÝrÊsÊÕ®Á—6ë<þ÷Ž#*Ž5›<Ý_5†î‰Û·?·€—¤Z«×åÃBþÒ0êsþ=\œ9¾ðÐNQ<ÓÃöÿ~·;>¼?nR?ÓÕ í¼Duä,l¹.ÃG螥”%öJ¯õ<EÔªÁ¯…í²ëpú+¶:Jß÷hèÉÝœŽ¾1Qx¿ÚPò@8h)åpÙŸŠhH$‰ íÁÞ%Úìpõx{ÿoæ¿w/Ç«_»Ä¢Z„yÊñ<\h5U6ú88m:¾ÏrðígôJî<>!Ó’óÇg¹y´ ÂÂwÿÝûŽ.s™îWZæ˜aˆ`~ïìÆ=á·E¦å2þ¾_ÇkOËM¾fÝý÷mæÙ>bmÅ}ÖþéïÓß1l–@L/î‹í ôÏJ°(¤}èüáìÖ‹ŽûNó†ÙìæîMyÍÄÃ*Q"·Ÿ÷ÙªGŒb”í’ú»`“ZPÑm ìMa#/Á³Ý¾\Ûw7ždñÍfR¤ÙHE:P01CbGVnµ…]Ú“PÃUEöR6bq‹Q$E…®¡‘Æ•re+-Ÿ×ª-"4<åU«œÔ1¾Io:+#/•³[(D±R²’`£$éÚN3‹Y…#ïÈJ”¿³#,#/ãB742#,.DH+F"•‹Æ^“K®Ê¼¨-F„nT‹2KbMo1´áj-!ñi«Œ®!ñI‚Õ-®kD´8ož) ¢#,”i¯èÂc:´´q½,)׺èg)‚œjJ"È–Ÿö0 ÝC‹OÅDloJ£AiP+Æ¢rQÕZ ÏÐn´UÞ™QŽeu’‘ŒcdöÌèüÒ¨çƒ<‚½l8šm¶µ©ZÆ2R„õaA‚¼–#*… Èij”6(ƒD¶; .ÞÓ‹ (+]ÆŸ€ÊÊ×þ#,ËÑEØ`XÚUëKE®{yÂØ°tꬿø{“¼Ì|»eôª)éÕbèîÏêü,Ot~_©ÙÙ¤ßë¿ÑM#*‘-2J§‰çÿÏ#,H¶¸|°úoWggÀ{¶tíŠ …\ÜžaŠA¨÷)ÿ(ošóLéÑŽe¿ ýZŸ¿ÝÝÍytŸ-ñؾåùËõKŽ˜ÈÛ!!JóyW®{)ņ[“Ú»m4êìÛÚ~ž¯ŠBDláþMQ$ë÷JÁÚœ»¿Áq²º?–àèuÕ5+ïzȯZ|Ôq.³ñg܈Ûèü´ÁÙÓ¹ÁÛÚ}ÜÊGFþj >x÷ž~Hç<« Vé…§/»Ò\ËÁAëf$’ç*«ƒ9t`ÃíŠSÌ(P@fä³ Âr4zVÒ#zz™éª¡DüǨæ‡êÿ)Èu>€ìTWÒ÷‰à5ÿFߤqÔ¡Žs¹Îì¶Îh#¨îÆ,óôô¹ô¥óm¶ÆˆâÿO*b“õ¸o8ç¤õ1í¨%ççì|7ݨƆãÔ\„køíû›‚2!©QH6 ¨Ú²¯q›$4±§’ðäx¾ÑŠe¢¦*·¹ä“¼‘0ïà:¶ììEÿ64òÑ×/mLúœœâCÚk\>¿^§úh¯5e2Ð?x±Bª`¢¬¯ê•¦Ë›j‘±’Ädˆ±#,D¿ŠØþœºo6Ñ/ŽÅ# ÝŠYdJ©ež¯T¿®?A5Ÿ/`êü¼ «~#÷w|ðó¼oŠ”#bÍb¤±%Îß›ãëÊûµöÌÊìÁmêâh&7pÄ`É24U.Âhf¤3уh¦b\ÃSU#/6EÆ*1±„D'©cÖ³{è«Á£Pdi°¯$`Öpfa”#/6Pu13b2WÉèzæÒñ/nF&˜W»h=ÓxŒÇ‘Àµ§G]:ý˜VŒAØíã”6#,“qV5U#,ø0ÍX(ÜO¹jcÄD³vçÈ[ˆPŽ^3#•DsV‡Æª+™6òtêë àFݬt²(DΗQ,eP)*(˜-†Ó‘2ņ a¶P1í½ƒFÅ£¹v#,uiNÝ‘EÂcm'[C®Ù`Ø2©º%Èe“ÓA,éÔAýŸìQEkN¤¹Om×@a¯Nõ.]оãÏ/^AÖĪƒm‰=²*ÛÍL<ní ¡qŒÌüðbÊÂBÒƒ§“~½?#òäþ÷ì"R€…*#,½7mãÅñÚñ›úÇw©B¶¢ñâ?Î#,É#ÓøhÐâ$¡#/Ze2CÍAO›¶þpÿps«„#Ô¨*ÌïßÑÏ4 ŒøÑƼ¦ìtÍÒOW/™£Ú õŸ€–[4óêôâ:“© ê´ír¹g\¹#*ùǃ4FYd¶(Å‹JªŸª•T@Á§Gßw†=سòàÑÄD\Üatá¥Ò!S§ã1QEQ#Ȳ:‘RŒ‰6TÂÌúìj·L§h¶š$vD´å;ªîŸ/¼:ÂÃ×®i¬KÇ‹‰¦øz#/*ìy®½ÀÒIh•·¥¢#,ð¨ÁÙc£b‹€³#*ÜçuuJªÑT"ÜgÏëú~Û;çQ#/úÚ¥"“p6ç*‰—ë0Ò†CôêßþCù<þÜïÙëø¹ÿ‡Î¨NY;ßר_ž¾ñš|2ïòFŸ£E>õù¡9ŠS_„#/<?5ÑÄš -+A‘¸·B&:;Hž¯§¥Aœ°åŠŠJ«ºõ7N»ˆË>‹¹Ž®´Â@ƒÌimÆßZ¨ÊNЮ£ªâl17$n(ðq°ý&nÇ”huA¶œEtn9â¥èrDcxâVDi59™¢â‹g3702•SdˆÂˆâ„",š0,!L¬À`U;‚/‰%#*PõDŒ¥J31›ˆÝ9È0;-äèÈbæÉSGg*1±ó!¡Få]ßÍ«[jMÄ‹¬’dTtúå6ÁuhU›@p.70Ȉ›1t¹ÉŒV¤*Êø°4µ#,8´†˜úž1Ôf¤ý…my±‘Dâãp+cvÅ`j0t¡–H²ÙdŒaL„¡&q5¬þ«Ë¿¡výÜÅîÞ½?,t€×~ŽXŠ€×5\žðCªøJRsâŠ@äEcY ª XˆÉ¨aFòÏOFh&Rcõû@oÉŸ/w×Ëf”ÊáÐ¥;ÑI1iÍŠÁÍŒï£É¡ØÆ*ë{®9“¿¾lÚm¿i«=DLP͹Ì4³·öÜSÉ"¬PˆÕAm”Åëž1¡Nj—Øî#,qs4Õuë·æfÛ{p„'”ŽRãã¦øfFÜ›’+[])n1V6«XËið&ƒ$M·É;û#*ž:—i™£_%äѼh½ôµÖ§®2¬ejˆcùbÀÌnpdÜ…2Q™6Íæ)‹ùÖ|ÑW¶¬Íí§Ö>Ë¥?^#,ð4cM¬ h¡$Þã¢ã(gÊà:< Náõ(Œ¿Û§2[P™›XÒmŽsmt(qŽf8qĘ´æ9‡÷~òI^8ÔA"û\hV;%d¾·öE*Éà/§KÛÖœÉ,êÓíFIîŒÞµƒÆã8o™–.¯”àų‡#,¿A¥ƒÍA#,¨òpŸ¹ŒX8™¡·/©© QÃph-36“1âÛ¾(¡}ÝsµçvŒuk}×{ gMk¾¼5.¡¥±·9¿[¬ŽöªI,³RIÝ÷9Ë=;3™#Ç-Ÿ`§…²ÇƒßL¿S-¨¨2C¹˜äe„#/¥(·‹|âÁ7VÖ»WEùÉuh̆·[‚!B ŽŒæC‚—‹6èuÜQ¶ÔvtNAY7˜–JÇpÞNq°QÍ峺jß#,K¦.2a?*#,bÃ` ;mkz‡F>+¤V¬v„NŒSuÕ×ÌògeËÌ÷Z[ò{©htkv8Õ¹ÓŽ—fašm– -9мäTØvŒßg$Ï9D¡.™šÑ]®íaZu`ØåͶ2rH'’mjMˆ0Úy›3]ö{ŽV6&<t¬[ô½™¶m¸ƒçaú̺߽ØzwÕ ziÚ\DïìÛòñÁŸ†VP§]U/ðªB’{ÌxØ÷ùí–ÔåÍŸU½äËݑƌD*£LR¦«mºJÿ׸ȓ‰È‰ÆÅuͦOÔʛ߮7œîùUÎ$ý˜¹®;®Ü\lÔ-Þe“›Öt|:ˆµŒ9RM|Tal¦ã ‡Fk& h‚&2Sn—|w-ai,‹Í=ÉE¡N "wÄ!eÌ*>{\˾iá@Ò‘^Ù¶§(• Ôy¾¡0BBd˜wæè¢Ïú=-ºtwI^ùó¬:&†šlû^å†4üÿ°ö.·×ò„±É=y¬+ãÉë¶4@úŽˆ4ÔÅŽ.÷›ËâÇS—iÑÕim;'Ây€Ô= ¦åœ•²ç8ÈW”“í“_ÚŒo(ˆ|¾óJ’Ë¼Îø6ò.Î[h*•Îg¦˜ˆŠAf¬Ù²Jؾۓ¶Å\$Z²(ã9j/xdîØX§¥…âÝ*I7ª˜Ú#/!Õ”e«¢×¢mÒ¼…êí›j¾LÓÛ“nŽlnFpüªúåÒÜ-ØxŸs¨ŽµZ}غ £ÝblÓcMæáZoÉaF3Wã±f½;àjo±Í&é³MŒ-…±T ëŒb[LÑÅÔb0WVše(÷Û[äîë$âè'½û|†øKëÃyÆÎë××"M¢˜4d¼¬p,q!Nzµf嚉œ³¦®Y¼F&%mþ ½¨(ê6â÷fü[àC-|#/½›¨ Þ¤}}~ÿ¥áçúqÖºçI„‡È÷gtê¼*8z!iÄ¢“pò˜J'YB’R±Úç̉—q¨ÏÁW§ù_ô?~–§P‡_{‘é,œ.´ñó‡}aÒüM=ÀBiUSì5›y=\Â4•Ø[ö¥XnFW6¨±^h?€7xG‘o4¼R}^G;r‰0#/äôýØÊ˪ÀˆŒõ Ú_ûú=Çü)zŽüÜvx¾ªáì\Û3å>;Ý¡x†|n×s Ó¿Òÿ1i%å$ËÓ3€#Ûû|$6§ñås›Ÿ¢gfõ뙊aØøD»–@ÏI”4ͦ‘g™˜Å¶´›Ç#,µøþðÓ¯R+,;òþKâ+Ž~Þûl@!EÚ‹1#/ƒðí–@ð<”ÃÏ€ÏúêÝ\Û±ŽQ°0L÷¼<AF€°Q¨#*„:ä cáb€x×h0¬¬¶Oë¶v‘õ2Á•°9n(3ƒ=ps¯´ exæçèn«‰ª‰a¦ÁûF“û#/^ÄIÓOA[ÖøŒÁpê`”5‰µ#/i~¢ŠÇ {ØüÚìtàz\þ‘vÁŒ¡Öñï$| ùå§³´äÍA#,D¡àFìØÄݘ‚ò`\e¾R`?‡¹ÉN¡Î]ßë¸i8Ho0;CÏ=¿Ñ:6,¯¨YבD`ÚóšÙ‡Ý²QÃyg²)_ˆ~-'4æ$(AFó«À»½Ü!·6&iX¹Mµ×½kÄž?¦Æ3Aòa‡vÊqàkì#áv×6GÄ_.ýúNç«ëS¯`‹ÂÄÇ%>Káß“ŒÔ|<;™nJsÇÊèM±ÆvÂZ‹"šbMVÊw05ª-V:¯=\;µç¬”„*^‘[ Ó-‘/ð‚¡>Žì¯|ܱ(˜Á@°@"oû+¼¹õ¨#/+r-;t<6+4羫béó†™õd*w_‰GÀVÞÈ뿦Ó:#¬ð©cSO”e$l½P¶o÷`¨ù?|>ñmÜÑÛêœÓCó_'ÚH¼ÔÑ솸ɻÊH^ØÊ$tø„Øt‰ ç0/)’îímç0´ì¹:¦¢NG²>}„ï&½Aé’’zê½PY±GvqamÙ1]‡BLÆrLVzž™Àßs©bãb=.½á1#,tß©¦´MhA»XŒ®¬Xñ¸]g˜ñ®˜Ûiþ–Fkl"†œM<»Ô”£ï¨žœ¿ºoFÅÓ9gö«ï¢#/™õv”ˬDBwòB˜Ä¯nŒÙ¼ºüÄZÔºXðÞ ØköcOzú¹øClô*Rzö…Äœjixz9ÂÆÌP\.Ñl©:ŠäìstC/ÉÞøÚ>͘4&]I!ŽðG#/QÓ ò‰Á=+• Ÿâ¹#,ÍqrݧXŽå“OÓm-&$vÛ#/#/M(ÂcÑAF1DÐuazë}p<3R˜tZ€ýúšÐyG9ùe¾;eºôØè±±nY,Pʹ®#,U±Ÿ÷#/g-†Ÿµ¥ÃãX^˜ŒÈ[Bì¼…¦y©Cx=}ÓŠÁd‚1 ‹y½alt°Ÿ)…°Û–{Ñk¹ã͆[ƒ¶éËk …ÈÁ…ÎG†s¾Y¾,ftS‘èm‘¶…ÍÒ[T%¶ôë“×ÍñàbµçkdžäÃýÞgôñMÅž¯ÉXpvêŸªÌ …G_•-_Å#,ð¾'O:òØÐ³ÝàRÜrúLgR$š.jXóµ©*–éÞ*o‰X&•®d„)ÿ4™„ãêÜGg'/ÔõvðŽ$vÊEÃÀ°´]ÔYK^< yÙîÍGàWí8ßvRtèîéƒoÙÕóh!]¼áAR¿d^(õy!ɹŸ·9àÀJ¢ ølô‚hzÜÂí…¨ê’Ò€!6ýU#/4ª*—ÄpÔçOKÙL%«´ VÍ\)uC»u‡'aí=ê ˆºdi¯ã]"óéþ„>ŸÏ®ŒõŒ1µd,t«/7ó\¤NǨ²…§¬ˆžA³66õíñh”}ƒåÄuÚäåëµT”¤·Ô÷@y#/>;æ5ìÒÕbÒ–¬ ó,¡ãm/|WX×]°,§V©O”~1P;¤ñ^'VKè³óP;ñÃÉ!Vº¾i¨Õ¼2M÷^^ö:Û|“:ÂgËòlù[@Ù¬æjwr…jrGEÓ/•ÇAôµº!ý\”N†K#qb̸ÙGG‘šÍ\fúBºtåe6(àJézétÍ¥æö(áZG¯®ÖIôïïÛ°€Ì€ jDiÍnMdf¡[Ã#Ö¸EŽ5·A¤ ñmÈŽ‚(ꪲ¥¸Ù*¢ðЛ <f›Î½–%'»C¶”?”CNsèõ5õí±m³†ë¢Õ˽C¼Ì;wìdp—Mh¸³'ºiÕôFǦ´n¨ZãmÂR¡ªœ½Ù°¬å§Ci|#, ¨ÆY—=5xx#ÍõoÑúܼY{;ˆÁ‰ ã6)4jO'9×%ž“6#c2m·}ù’Ý3âöŽ."[km³èu¸}½»Zê¾/&û„Q«Çƒ™è¸›Ñ§q}M̘m¶Iö0ŠRûÖO•ÞúNÝS¬:ñ[cu¥1¿faê‹ÇŒ"² [O2,ÕèoÒï`üyÓæôšE9‡”'æøÇŸO(Ï~ÔDwr%¶¾B®;”fò]Ʋªà‘eëg‡ó¦©Ò_=àÖ}úç¶àHÞŽ#Œ9#*»TµöÍQ<<§éŠØ>Ò5ûæv66Ìg_Ã1x±³Œßð#,ƒFÏv‘á(Ž#/äo‡©É¥«p¹(VŘórïøð9erþØãˆw¶j¨Á³}Ñæ«²‘͈§ó3|N>›HÛØ¡Ì#:–E¦çvÓ6ͧn'jVËà±èˆ%ÝØ‹´”Ùƒ›Áó©rñwut¯r(zµžÅðûŒ0ßBþïÎ[œqoF¼Zhå"¼Çáq8ÕVŒ¬jU°¦¡ jïЉl¡ü¼ý#,§lo´ÈšY<;ö‘áÈÛÎZC-lŸÄÏŒSxªñ¿n¸ê¸Ù²>ÛJ`ƒÀšt©aÝÌ–x6·ÆÐâ«Ë#,#/[ÖÇ]¿^ü<#a´tr÷(‚y×-»Š Ò„M@oÏÀÈ8B¸†ÓÕíØ^§‹Ö5¯’o·£éW31’ÚW»³±EŒìí³Läæ4e³8rz;:™ÁЬ×ÌXúlðf§YÐ#/‡¶‡†e¡>ܱÄ0xƒåz½ˆÄ<Ÿ|OÓ;öõ‚ðÛЄ‰Gw•-OlÑ`³ÓÒ#,¬‰jIw¢y,ûÌ9Ö—V×9ÿ!h)?-TyžúI {ÈR#/#/èAãËùÍ¢ýk:N#*uœ…Žxìý£f/y +#,pʳ§Í:^\«s–ÒŠ#,õV±õë4¤G0X¦òÒɰô´%•ƸB˾ÂÂitZ×YƼŒ’Žû©¹°gÛË=7Ø‚—5…Ù0+UæoÖž-[l䣌BÂñ<G~‹³rؘX<û!¨¬Å«'\Ú¹nhªâ¢c`(±û^Žˆjbêã_#Ö—Dö²Ê¢¿éï±#]¯ë£š°åÓ BRË*äQÆøÕ×®ÓÁøÍœ.¤T௶º&V¿~PªØ#l-±¿Ûß'ÅfûxœE./UßNÑMªW’qI\e`!ñ³—Œï¶^úèöºŽkyaÉmF¼sžf]y`Ùªù’q‚(rk?~£ç¦y½º_5–èË™Ü&<{l¾c1„±R/5>Ž}‰„—•{–÷ÇïÇíÑõ¯—aÚ©°uàúß_Ào+ƒƒÏ›WÎÄ(ÆöMt¤idÅ—A\”Okéàè¸Pe…Q»’ÆÔþ¾‡—Zãú3šÄ]zH•¿‹tª”x[SÊ(E.xýpü[Œú³êÂ×FNv÷©ˆvÅò²MîÑ#*:a…Ãz¨²üì“åat¬Ž¾ª|Â"C_5“ª/ñÊçá£K«Û³;9ˆÂ!ÌÕÕÑØŠ¥´sY²ûí³wÏŽËA:-J0±š/óíΤx£š£×σ.Ìx¬Ñ›x¿»ÄøÖß_ÛïŒk0Ã+†š‹lï×Ã!1##%}˜Àè,|äº\ø‚³UÔ\ØâÌã¦ÑûFç>çÜ\C“Ê£ÌÕa{ÞºôQ´d4´‰äsÝ#/@¸t¹åêøAúõ6Ìc=’¤W”±ßº.ŽbsÓRb)¼‡3/#*ÇLXYc<÷ê²yØê Rû™ þ+LXXe9”6;´:ÀÔ9„diÜE[˜OƒËÝÑøn™}2yÞé'zˆ·,Ƹ™0üe³Á³`°÷»Çì뉜۹ÝçsÚþ•=—[_6EMKðõÁØù27Ý: Óé8w³¢âpÇð²?Uש-'žO½y¼m¡·ý¶WiÞ#/–~G¼2)¥Ë+,˜ÓzöÌ]A ð(F7"ã€c›ÅþµÚMå§t»á#*tý±#,]¢M«’ÐÊìaM+â¶Î'zÃuöߙԙßn*KWDþwÄá}Q”¹º@:H·5WÜÖÇ0¬ ñÁDßÊÂØ÷Y„6tÚüaäV©äQ„{øÙá=#κØ;5Y™®ûr/j´…:ÇŒzm&<Ðþ9Œñ‰½ñ÷He{Î?>°Ç í÷•L¼‘N™ãvPµ§˜Ÿñ¼õÆÐÆ»¸ë·€ô]ÊaHR0¾ß›KÜófWãMÒ{ªØ¬´xÍÅÒÑK_…_¶/YSQe`à{©(êJD8ÉÔ~.zóáx…#›p|œ–‹^BÑtôÂÇãÒë{Nvì#eiˆ3ÅÍ"Ñ/¹–Ž‹––?a‹ê¡RAÜÊœÍ|ÕÈïÎR{ñ:]W>YôÊ€ÝâÕ9I9°ša¯\EE&’Xã°GeqçÑ;yáòßDÔä–òYD’8¿eK#ÉÐ%g5¹©o7ÏžRÚüòbœÄ-3s“ã–‚>^·?ÛÎø£´o²)±4ûs²ú¾1m·fA3¼ß€«èéÎ6)k4ðà',…ƒ#*µ¥cd²i*⬑C¡kXZÍæQ(Ü…"$xÁG#/]×K§MŽ×Éd¥k'0î]qBŒ/šÐòZ¶Êª6Eß²m-Üs¤œÂ@Ä4Îzj‰À‰L-¶êXÁÕáÙ§@HŽÍp¬šÊáÕ®·.ë+×aõß÷‚GãªÖq*^MkUt{]d¸Ê{š-z®‚¨t®6b±,ü#ÓM˺iY\jQ•óÅIJ‘#,P‰mFcËKtÖCFæ€ë1šƒRê°ŠB„r—æí‘Ÿ"àçò;†<–ÀJж˜¬#hXFêgÁð}ËÀÝÆâ#,.‹ß»Ÿd/3–Œ"÷+½…C9H2ƒ¸4&î““±²£u”Ù=QWç 9ϬM«:æ‚™Ö×óôOQiN®´¹ÒáƒÁ½ÁšñN–¬2¨•f'HÆ2‹´æã}“¶R´&NÔ?WŃšœÉ—¯Ò¤7z¹ƒÉ@ˆ=*M~xúYguŒ÷Æø¯^‡®G;á±Q‰Ë¿Ú—nO¸r–_˜ÁOí{gÏ´à<Nß ˜ÇƒÆpZuàuŽ~ÅÄî9à^¡nü¾Ë*6XˆHZUÅ뱎߆X¿pskÅfk¿4Gä³g1#/°æ5ò=c¾Ž#,§S0õ•©¡DG-9\)-aƒU‚Ëáu°™#/ªª!%PÁÐÞûð”Œ<UÎmX=e~PI¦ÖQaç¥å®e´î¥¦ ¬î¶d‚ |6Úá;„jîÊA¬…)ãy7ü׎Yª§ÐoÂcÖ›óÄoKi™Ú§ek]um*{CS™ýX†A8ß¹#,<Ý?'%ü´øY«œÐ/ª÷Mí›C¬‘Á®¹j)êôK"mv²rЇ_ŒC4ãïVf½ÚÛSö\ÃçÅÊp§j˜×Ow™¢WÝǵÞdÄÛ½&%rx`õƒE|øœ2ÒÂ[>*¦cÇI™Ap:üúF¢ïœ„Kþ(2S=I´ç#*,º-n®ÜÖÞ÷J6OˆÎBsQecwcuÕM‘–“®•nµ[TJ`MrÌ¿4',X“Í@éˆ"ᵑ ¥ðû¶³ðÛ#,Ÿj,4|>…\xT¿X´½„Ò•[úì¢ÃÔ·…6sççè¬#à°tŸŽ'D`ý7ï‹ã9dÀA»1¸ÆNuÝŽ…,XÀk±Xª|dt¾øªSÏc:1S;ú ׿.W˜¡#øIuÏFîçžç&ò/¶‚ÝËç ßÏ+EÌŽ‹áŽ¿d¥^fºCf3ÌÅ£:ë´ÛÅÄ™Û:–¤¢6m‹›èÐ9M"Ìe¥ï/ƒo9‰bç¾rÂZš•S .èîãÂÇí‚ÅI”§G%ÐWòŠÃ‡éìjN#(ÿ¢"m!ˆÄîi²kÚ%#*¸ˆl.ðÂõÐÓs³Á_=ÜЈ°™¶NÅqÞ±·Dz!qæ"bhþ{cÇv÷¨çKÀˆì÷ö{mtú8ørêÝ#/a5ÞëPMåþ$k>‚—ÂŒ+˱“¯[Å®ÔKih‚‚òžªfyß}o×#,T (gG¯µNVçfêT1§O{:¥ÉÉw){”©HtU¦®cÄJ.âоšF¨[^e¶mÄØ‹{šš&Ñx]pí/¿Ü£À{Ÿ£DÆàRRÁ¿|<*/ªªx/ )ÒTÑ`»výø@æáöè®ÓáëøIé.UÆQ³cÀ©®aØU^ŸÛïοa¬ÆÛ®UŸßè%Ø`éu/~¾’ü¯¬Z9~£êpÅk¬%ŽMË-ÚôqÒ¬/˜í×DK»žöÃyÆKE]cÔ®AƼüîI97Ì`Î\¯W3àï¤ô°²˜ã+„žv-‘ž›Í[sIÅÓ%4¿¬#/'IÙ3OUΙ£‡GKî´Z!'bMØÙ¥”o!M6(Rþ7È¿;°(gü¯´ãËœêšúl^žQ§ŒÏ* §§GZ1>¯rð³)Œ¬£3-0<}îŽ×ßÞ1Ú%É*ó›Þf¼J¿7e®èEòaŦÉI_HÜ]Zä¬ÁSC•H³æV“Ú¶#|oâ÷¼äÍèÃ㌅}þ|¹-°@Ϩdk¬a‹Ýºô€•S´ÿm}]#Ž<ã#,Øü£=G£ÚèÚ¦<u˜ÏhÛ^ñRælù_ÛÒ½3ƒ;ï8œZ•Ïu}ËÛ@l”/à¬ÆËsÂwDøe‹ª‰jÁWTƒ}Íg磟#òE̸ÎTóAϘ#/úÍÁHç/ã¾}?¯ñÂZÙÛ|9îFÇ×8…GïÛ:çºc*ª¤)çÚ#·øwÌÊa5*ÅûÛ Ïm~ǙՈó[$™B„ecÐ=n³0ûú¼²ðù†Ž“áp¢VÖ+9,>:›º\¯OšËŽj(2 ŠýyŸ*€È–€?®-=hÛRûäˆÅúȳ^€ì0§§±ÛÈ1#*…*¡%îàÔã%ÖåÉ×øº;„UŽŽ]n¸ÑÐòÚÖ—wÕ…—uƒÇ±t趈B‚¨L#/h_…\d×ažédòÕp˜#4à›u|ï©#, \B(`•Ðuèݨé åŽýl#ÂcXÑ|º¹°s’ÒƒxPHÒ÷¢|ÃÈC9#,Óda)æ7’QÇ(z²Ä_4iC V”ã½]³>‡yú!#J»cŒÔ*Y_Áü[Û(Ä#Q6謃žÎkOé‡cgøLKJß®k—~û+ð~Ǹ£ïpbC˜N¬Ø´4—Â]p—Dó”mRœçNŒLw·ì—uàM¬¹Æ&yŒÑ¥6åÌŒFÐ6ŠßÒœôJßnNmpÙúó–ßÏÄqˆŽÝ¦#*‹¯hÿGÜåõÐhžNô®3ÇÙŸ5cúã"Žtdµ“‹ô½ä6úÉ¢HqZq§7Vº³E÷ÅÆ"ø¾1ީɕhŒûà|Säùà‘Þá4Ì?Å—æôÓð³§óÍuÝwz‘J1è›·7P.êºMgÄÝ»\=:Å:cì½üå½~x"ú÷õn¶ÝgƳ] «GSA3Ùåæyöòê¾ÝTîÎG®8Ø’Û«ãyLéÜÖ5ÄZpW(æÔ·¨Y_[)Ì=N;~GŽh…nFŸºðŽ-'WXp_M¬?qزÓ7`O—ãg åßekì$³ÏF1XÆ&$‚OilQ\Lcs¶wvS¤ÉÇ\‘ (²i\ŒŸ!}¯†:ïŸ.Ñ"Bdq„âý-”bwézÇ2çŠf¢éÍî]:hitQÑ[Kê•#„¥Càât[ζL"%&ínTÿŽtùæcÕ¾ìEZ¿^°Óû¢o0T{´¯(.}±ïí|ïŸ_7!VI{D¤©qÎ&¿\ÏätÚ—÷ÝÎ'Ö|T1¼;pŒ@;'g»B8¿Áøã~1ƒÔ‡Pœ7ÝÜGá>¿Lo= À!óÒ|u¿5'ÒT£:¹èœÇ]$Šoåý‚^.a@:äëðøN<Žó·ÏKãD<¹ï³Ë%—k±Ò”'êÿìÕÄ1²Mµ ìÄxðj["^îhF#ÅQ¯Ž¨jƒ[ӡ脱ä–V(C±±¢#*ale(vÀ»^ØÙ´&įF4 ¬:tÎz&rÎÄ^îÓÖDä=Þ(cÆžM8ÉnyÁïLXМW§ˆõÌ‚<))KN=ojŽ—ˆ¸¥ë¨¼”Ø”ü(™¿žÒAØöäû ;!(žÈ¿Nºãª´µÜ aíÒ¡FxQˆšwbž ^VÖÌRÓ"!ªf#,.Tç^Ìg6íî›t‰ñÆò{ŠhÜ1îæbróR«àü{gÅ}Uw¡ˆk ЌՃ#*H¿Ñ^!à5;…ÈšÙå=‡`¤:Þ]"ût—F¬úxŒIèý=§Ó‡ÀÀ‘ª€²Êó¶Ù@Þâ¿.ðÙVå¯àžáßÙÓp#/ÛßgÃ]È;y¶ßm÷&žÅA4!;‹³á™ÈRöE$3õºÒ¿—Êùq^ᯇ‚‡‚ ¤QdíŽÉ½ãna*:ž§›¤RïR©æTì ˜›kÓÂ/vü2Û>`ÖºÞÃòx¥¦æPÓ:k€W‡!HFÃÝÃç¼'ÅÖ¼‹Vxþׂ>«‡me¸uèl‡>,ÄuÜ¡´©ù5‹’1•_±LzÇô¤#/@î•}&àD#/ÕE¥Ò2;…ϹL¬`1£gšbÙa(˜xÄ~¥áOèýM¦0ï3f•~öc± ä’¸#*ZD\€uRnN5ó¿°â!%$±0…´7étM*ÒLôçèy)ò@®ý·b(ÌÅÃ.Í¡,ÐÓ1JÍ©WÚ*NclÄJµÚCJ<¬Õg˜`ú)°„‚ÏÛéaÅ|ã^f8Fëý|Aà—ÃÏ}_w‚wÄõqêügÆRÒ½ü¼J#*õª}>µ#*iýÉúSõý y{"„‚ZwŽzï¯0ü¥ Q…•p¿tp¬KÎåM?¯f¼ÂDÄò‡ˆ_*‰ Ÿ¿ëÎĨ‹êô¼4K¦KüŽ {8ƒUËûŠ@©ETB*%o’Yh("ĤZ“l›ÖÑ]un|ôûw*œÕÚ§œaÜl$¶*0üøPoÀ8Ôkú}9ÄŒÞá=Wß–74óì°DÕið¹wHpUH²FE (1XÀ€ˆ‘Jn#,uâƒ|¤”J…©Ê9@àR™vëé¶ñ†s0àžlܘø»#,›ÑÊJܘ*½¤K½IÌÈ "êé”ýf7°U{ïhú*N%"D¾Ë^ðýÁþ›Hˆa‹HUV`·ÇÏòŸÔ*¹T)P¦˜j¨@nTÁýó‡í¨âûw,T\ö"°Ðæº#*>ÊÑ›&»Ê…Ÿò‚ôã_GuÖ£#/kb¶0Qî )s—Ëêƒß2Y°ŠBNfb>n.Z^ÏiÜÐE!R!Qedž¾š‰²å* ï³çþDg/(Ü{/;'èú@յбOUÈLsÌm1ÕR&Ä—wBSbíioE®xyFU#*Yê-ö]Ó?ÕKº1ÿ$…ü滦›O=›d”¥4" ZzË/ÎC霘aÄ„OÚýjhW¥maµ:H9l›æY‹=ê5GR'üƒ‡ºcdØS꜄nKNµ¢½@ *«0[ÅhÒ†¿©~ý^ïÈ•s<7E‰a'[C“Ÿ™ÊËö;,â=›¢ã#,¡Bÿ7lgsZ(¨Ôd×…ï3çå°H<´ÈZá ?gûàî2[}±ÂµÙ¤#*ì0ÝG‡-y!#/Ñ¿»|û`yš<†sNöhn”]Ȱ´#,þ•:½ŒPËõ¿Tüœ“)LwD5ª#/GT#,ÿ?í¶ÈD#*âi@sеxA=Þ5¼GŠ¿‰ä¢(¢’ÆÈH>Î*e;â0Bµ»Ë9Ä)å#*lÓA©>6cÞ¡’V|ZŒ‡–T†Ýréku%Ðb'‰àB€4×r䩽#,VÔ–t]<b/®!”doëç¯fŽv²?ÕKhvÅ8Ñãý\èo³11›hʺ{@ð«óqä÷vŒ¡!ññ{A#¸wF鸯±Bþ·ü¯Þh>û‚ÛÈÃdCPì„Ùxä‘Çô±šÑŸ(/Œ<ùS‚zî{¼bߤ‘‹éÙ¢L;øÑÜŽ<ÏáÛ¹¢ÀÊEšÝ÷ ‰½B™@+7äÊ·-4!¸Å²^ÓÆ”ÔiœK“à«|>Þ9wÖKÞvSöÖêÉl¨+¿—R«óζ.nº†žºÏëu;Ú8•HCY£6ø‹~‰ì‹ü÷×f¢æO#,+”½áÎÆ[‹†ž~1æuñÂjåtHeZ7¢äP.ckS'…ȶˆÜ÷÷瀔rëþþ¹è¢ºußmyºd¡÷STOaRî™àUM‹õ·=oÍphŠ7(ö¢ž¦÷¢b'?RÛXÁ{ºÕU3@2Â’¹íâú¬Ióƒ.D•kª¶Nã„í¿Ý2†³lAý£M ò€´¦ûïŒNò¸·S©3s vkuuŒHé@dcOF@šGHH¦A¨Qßçž|ïmëI×øê^cÄéü¢*´¥B«ÈÀ:Vëî‹õtuCZïÙ²ˆÍš3¡‚@ë…Ž!Q”ˆMèX³TVPxSŸ»¼q³ ù¾n׸Ñp#*_\z/wì€<g£ußSºäàÂî.KÞ¯~<à‚@Â×o‹ç¿ÇôØhÎ(v½ßÎUxzï®(‚„> „B˜e¡®¶¨2(KPÁ2¯*#/WÖe;zôâ–ÁˆE¦sÇÊùÅÀýó\ C"†¦”ŠMÚÃÐ?ð~ñÑïŠ=Ëa„“/Ä©Â=ÌùÙ5KëA5IRjuªY8 ªJ:³s 8Îöb[éÛÄ_~Útâ•ÕÐOÂÜ`Ã×ÐÑïsÌzb%¡j*°N⛸Uvz³Æu)[/$"ª„@,”³‹7VõünpЉªˆÙ-Ç?]ÄÆðCò•;'ŽSøë“´˜Êû0,€ÉáéE/)©Ëd/{7\‚åhM»#\â¦BÕ{XñvHµ#*˜pæmAá.¯#/;Џ\qÔêPè^ðtÅögiЈW!t—6ÞXï9}ï&z</'žYºÖ'Uƒù~_¼òî3Êe‰?”9züyJ`i‚'0ÔEÜÔ%útºd]ù‘N±³9‹~¾Ú¾‘H•ÎcïvÚ#,û‹½~%ºK¡™¡0B6jÊX3Tàê[ñ*±Ëçx陼܋7)¢#ùFRH¢ˆ¢Zbü!y~©ƒÏ“êþánÜ–ú“Ùæ–»¡‹rö?LoW RÓªH9váÚ3^îó;›"¿×‡6;#_~{·ßªËfÜnL Ûãý¬×žG>WHxpmË"ñ¹èò÷I©Ó€PC#/&J\ºñŒ¦!™.ÆÉžX)j(°#/ɹS0"ÜÖ´€á—BÚ„.Ñä~®W1)* v÷F(N‰&QâU¬w8AÁúîrð†èɆ#/'†QÜS`"%yÂØþ,·½È,@éÜÃ#*äç7ÍÀ±Û¥‚UÕ¥ÀW‘h{7Éîƒh±XY¡TÅP(!æˆW¾³ì®z9z©×cH²¯+Úý„a¥ž{ë´pÎÞks^GlÞ=#ª^\ï4íé?ºó£ågd5ž•øø¾*=¡éÏ>zï7÷ŸZ‚ɳ)U†ž·©ÏyY‰Ýy”7,#,C£ž5@ùr°ße£ˆ7°EH„6h„Ë^迎†jRÁ…40E"7Þ ”9Øà#'ÐZˆJ‹ÃŸ*¾ì‚ì$–ºÛž#Ì/‚ú¹šÊ=#,ºuG“ÖyáXþ÷xúA‰Íi§‹)“OD”–ˆ—ÑáËÅ<›Ãû£©‚ãÙÚ;0æ¸ò¾0ç~æÆîΈú¦ªbpùîýxé#,”„èÊønæè´Å3#”] ¬ÏL²Û8ök® œšÏR\6pÁ#*¶€PŒ‚‚˜N68 ‘óŠEÚ—PqAÝXK-;6¯•ùõtî³Âˆå™ÎýÜÄ·'߯O¦_œ;ä’Òs=¹xàæ_PìáŠùëlb)ÒìÞÞÐ&G®+ó+#,¼·Ó×´ÓÒ²Hí4ù)H'!áË\‚‰ò,"ŠlÛÆiA5ÅC΋ÂzÃ#/AÓÀEävªº+×É»¨[:I¬ ÷9sÎ[ž #/R#ÌäLh# „S ¸ R.kaªÒî;3VûòéÞ’K[K72òc¾iQnÈÀM#/g›OÚ)Bô~»s°B'·ÇßP)¬³b“‡’dU1¹y=gîÅöÄeZHñNƒÕ $^\zóþ[GåÙ>«žêh´Iµ´ÏÝþµ´±w¨øKÞmrªm6Ÿ#/C”aàê<Ï5ŠHN㬅(àÊ5uíÍÅUPáæN1¥€ÜyÍÇQF7"8ªâH¹‘wFÔHį'$AÎԩƒқP¢†ÛÍŒ•Â^ÖÈ”Ï/Y\¨/º¹1Fó?šc>1i½ðzMÚcI>mŒ*aéçÃE¾,¿äTÜ„Ôé-ƒcù½—GG׿o?þ)óß‘¿®;6©RaCRL‘ƒ‡©ÓU·«eb„Ý÷/·÷½µ©õd$8„WŸ:6E~l†…§vÖ·ë9´£•},ÅàˆvÒŸØÂ#/—Õ#*ŸNlÉ„³Zçôþo;ù&þ£^]é9àÉÒ„ÆÕ‘z ìÍÚp§)ÙÂ;þ½ž¬ƒÄã¥jt½ˆjR›ã´xã)K¿Wr¦:ŠûPm9]‡C‰”TÙ¥’'ÆÀœ'^í¦¼GNr˜j·^#,rgqžÑ >x_Eø#/Ê8wkcÁI°`¶\&QžXŽÍqšFWV 5+°€Éš¢jXk]oÉÈÙ~jVĦ5æa?¤…s#ëxhB7©³¾èÆšHU3oF…²W¹ÖUîdõ¡ÿ0¨UB©çëº7ùOí”.tl‚3vZÿ[ÿ)ÿv°/÷;ŸzU¸yg˜¶Fb¨Â2)Ø8 ‹hPi°aJ6äCú¿Ÿû}S¸:ê¥GÆ¡ŸõwGn&w·¢©?‘ £¨1F0…}‡æ|Ú_ß~úÓTu÷PUTöì Ÿí‹'µ~„éóñ<ÙNÏÿÀ/ý°{䇧÷‘„«ÒßÑWÜW‹WÎ]—ô&W&¶†`Ô_õ¾ÄÑý“ï¶¼Göò1gˆ´¦ú#ÀO\„AcàB<€÷¯®Û›ä"@]ììß¼&úZç7C–ܱÀ)I â£MJ¥„&“?C#/òÁÇÔ„1’ü(ÁæÊ`¢1®¼†¬]7-Ó0ü9t8cÏ–§Nuúò±ò¯Â‰‡ïü¼›1ïi†‰Pëig*§ÙÓÇG=Æö^ÞË'; öÑÎb¤ÄažUï³’ÈN–V£FÙº^ÏE6ÌöïeÇw&êV2T”'ðr—F=d¼r<[áÑ?3ù;wàãÕe¾" TñD#,Ëý~!†õ÷Ç‘¯Ç©—¥uŸW†Ã¬gB³çÈÒ{˜jhsi–”$–Ý Zp¦¯¨C7ÙƒõQþ“ìôààûÜ>µ%úí‹´Âo §Hß]~_Ýd ȸ·J¢¥†Âê‰êA/ëüpZNî•wÓa»2†‰##/¿zK5 |ðùŒû¡Q˜éû0àþOgWn>ÉÀ7t…B6#*=,€OòˆY(ù?QJ×sO6U}¥óÿÚ0<;}‘âðBb_Äí.y”cÐ#,óhÐÀ+P@r#/½À…ˆsˆY‡¥ˆ©ª(vDro±CšP«"•È´¸YHênѬ f !ce,2Å^‰@…ÂÓaBf—!$àÃ]Ë#©Fí”,ŒQt(~VÀ6¡4\,/ÑÀ`[#*b"Û&´£MâðK•ŒÄÑbŒ%”LaH³H”`ƒAÐõå@åo9A,S”jCÒIw³Èʶýº¼G¨¥˜q`ƒÑÞžgTše:ëÓûâŠ=~0ñêËúºUÿ#,%ß(¦5Un3ÀkýЛ¦†º[ý›ªÅË¥.:%̆‚D’@âÌO„@OWÂÑí#,gMmþ—÷µ+1Pm)܆í5•Ó¾µFéÚIv:zÑùk9¯=£ÄM&JïPR~n¥íÉͳd•¦·#ú8g ›ÜÐ~KÞΕÏG¢¾ÚVÖMËò0‚ì„›Dj‘q];vºî®åÓ6ëwy(ÅçTÔC†õ„DÝömw&¬‚·)ªvoŠ:TëêOY¥ÀýêzúõïqR¸ëŒ«ú¤á{ÑNøåt…yávl•Õ,⣀¹«QØÆØÍ4}/RŠup÷EŽOu¨ÈÔ•—.Œº¨pdïfŒÕ¬°õÕ‘Ç¥SäÓ,Aº'Ò <7Wè{L6#,‡‹AŽÊŠ–Ý÷Ú±c¥×7]·ºzº¥#â@'„šñ~ÏsÒBÖšiOõ<!Á¿Z=™/p‡f*Éûƒaò²e›B÷÷&ÃbWO˜„„2Þˆzò矰¹èX¯fK4*•"(H¦i²ÊÓ2S>·Ÿzûž£04UU#LPZbUCÓ·_f³0™d7Ï\ôèw&îÏ1æ…¦³ˆJ9šX,œ 07ѽ…ºmíÑÆúCåª(Ñ"1°iˆážhg†Q¨˜)ï,ŠìøP-iöOÛÜóÖ‚‘“Ö#I Ûq3B#/B+Ðl7Q`Lúk¦&c\a·Êê´xäbËSj›ãCoox¦‡Jd†¡âdäÈšR#4 3G£VVDÁ3ÄÌ0‚²i‹£6‚ep&¶©R¶rÓ]Ž:Ê0#h ¾[ ëóc†¨|Óg.öx™à2‡5ì{³#,µ®¤y`gÅÉprHž‡”$<Âò»‘ìˆg ¸3z{',g}l&áÛù7j\¶¼;õ÷8¢yžÝ#*Md \§4ðO/*,‰Å¹ŠÉC#*”$ÔI!¢KM²mljÞ:ÍY-«É[ÅWe¼k^-ªåY6«•]6®[^¬Æ»®ü;½z×zcT$öîtÜÖ#uë·‹cm}2l”š0W¶tRl¬ ¹®&DßUôÊ®áôÂ#*øzÀŒƒ±£çW¤@ÒÍžW`Ã’_†+ãÁfýqNR)j5ïia¹ÜgÔpæîè^ bE‹P×ÈOŽùþ5Ä‚t¯¶åw”¾=|ë&úJÏ•MòŸ?+‚ÜÛ}KI ²mØÙ*ÅÌ6C#@y d›2+T=9²Ê´®¾™#,u¹âm/ôè«â5‘KîM ʺñrlÒŽT:«ƒU¶(ØFi$“UõÉ¢!,»¨n”)Éo÷V°vì¯ÆÅIå ˜‡ÏͦZèÕàI[©Ï%£XŒÖ⨈òÖêmh¨MÖ·¶yüûà,mµï.”iwjݲ×àóè¦ÿðxV¢ñöÑ8ç[ø'díêO#*TAi#/ª×‡f"*ÂɵORˆÎ»&F(¦“]Ê,ÂM6\lg—Ît[Ô÷‹ñÝÅ‘CÔ£(vt±Cp0 !¢˜ßÔGLñ"³ÝjÞG>´ÚÈtÍ0 PRû0&Ï&,Æ¢Pù×%¥.’ØlcùÓêÛŽ{¹jï:9·z‚a…M÷-5Æ$9#,v½47ÜPkƒÒ‘\ΛÞ(])ÍX©Û®W–h3Ç•ûS@éD*DZaH°R¡(:ñõÐѶ§‰JÅBmj‚†ÞŽyÜ;yVfþý³×X,†Ñˆm`ïÞ†¾u'¤êÆÝPFLWÜÖM÷*íuÃìco©ÂBFKÎCáæ¤QHPU—èQXcRAªšê\3×——ãÎnÍWwJl– º1³ÄWj5/£á~ñÉÈíP-ENÙ•øÑÁ>Uœf/3épÐÚSá’mdТe]㓺äèñØ—¹°õ¹Žù‚Tn϶§*Jˆ{‡q `ÎŽžo©š¤”ÀiDÆtÒ· È2);ž£' ƒ>öpAÇ*45œÎ6Fª€©Dò…òÌߪžL[p6ƒëFØ;nÀhœ/‡V0ȶ[‡CäÒY¶Û¿J-vÊjµåf4÷5I$Âp.÷SØÆ˜ÂH` š€ý_ŽfÑžärîI ¾£C&íãó¥‡>’ Ó¡¦sú=|MŽd‘Æ„j¤T&eMûñ¥U;7Ç#,ög~Ú³ÓåÀÞ¶Ô;·éNÙ–q×ÄQ_!ùE(ü;UÓátd;#,.”u«ója¶ûãseÓ¤2àϳ+¢þþ‡"HÃn¶†üD¢ƒ:vtéÖú%µe¶I©§{ž#*…$:"À—NlýçÏOWJ%ðe“¦é#r9#Œ‘±èg¢UЛTÒÊ|û\RW‹ëó³çW•È‹yºlXƒÂ¡/Z¨ùq9g–5‰ÙÂTz7åäZGù¦ö†Â|¾|\Û)åep…Ðtstê“£8¥•]“Nëömݦ³Q×UˆÐ@¨Ji@KE”ÐÙPƒmI"¤_y(žjäÆ#,Þç] ÷Á2î*Ñ Ë»\aóÍ\½úµwß¾Š4׿¾‡z‹×FùP0‚@Å’{бE/[Â#,äs“^M¢õ‡ì©7csà—{K좎#/PP`ª‹ÈÀt’bZÑ)$ f—<-uå%ÄÓ¶×Xn~p_éWÒÅ« ÊîŽJ½ñà_'-˜òAóËò¤ !sÙ®±´Å›3ï|ÞûË3ýùÄõú}‹Þ¹¨iåhÛØø„ÌúHÄù&p¡(foÃ#*=OŠcU:²tCµ¾ÊÞ³ÕöBôL|¬“#¡°;áø6‘æß7úÜ7ÊGý“ÜžµÌ3£¢Ù,~“‚ËÄæeÓ¿ß7“Óf+øç•#/[¸?°C‡’A[nSM…ùP6HŒCA¥Ð38JœÉú•Bµ)Ùh~Ý”"CÙ§%Y3©(³%QF-hñj¤È„A8^½þVJo“geA¶PQI#ÊR™ÃϨ¿~`ø$,|UU8ùÍ$ÝÚð·`ÅöétLóŒíäl²‹ú0ÿFñÁѾ3ð€”vã"mÑÙ÷Ѳà‰j-ÅÓf!š˜ÀvølBoŠN‚•AÈàÙAÁû¹#/ªÆFn82€š:@èVÖŠëŽx:pû/F½ûM„=]#,»É¼‡@Î×|Öˆ¾jÛ9˜·%BBóÌ2p'ÕÞÀÝ#/¼ç·€[LY6tå‹õu”‡Leô6š×äýYÆèm#/9!«Hä“Á€¥²s|Ò&Àû#8]·®m¡Øˆ:6<L1©ÅN:M‹›ˆ 6*«‹ÐЍ‚ŒI麨ÒkMŒÖøX¬_¡µedDkgŒÝ=¿5“Œù•ÔT‡\Ž%ÌB*ƒÞÑ8Ý̈f0½?®ÔýÖ–Ášzz0Óm®²ëfH_zw¶¬<zÀñGƤ'&Af¼(zYiáSÁd‰ÝÙƒƒáUùúî2qëP±ÉØÙw¢L)Èâ1>Ï é®;ŒqòßWœ€{jŽœÊ#*>\Urå–ι*ï&|bhXÉœN£F>c½¾Î#,¯H;náàä@2ͯ–‘¤~ Žz"Ìðfƒ‡{’zãÝ8²HŽdÜIFÍtpöìçÏ~ìhÄ}Ê#,_NS€Ï²ËvߦΠ³_ßx.ÆX~̃4JÐ ?Š#öæˆXÓY|ø–W²«ç%——ìýí3*9ÖË’}¼6~=J ×úóÑA8=¶^øê‰º&¢‚öüý^ÅïË-¼ÖÎôeÎÙÛ{#/!#Ïxß÷3Þ–>oÔÑG–Ð~èO½QâÁ£óÑßÛåGVÇ5®¡‹#ç©Kf¶9އ8’þë‘RÿkO¯n0ÏV2@Rƒ…tØ÷å]ÕðLŽ¢>Q’ÕI–ïYçž´šÁС‹Fò;þŸÂ«ý)蘺¼ý?«Í3ˆ@#*þÏòC‚nÀ¤H¤2®SrŒŠy~äÜÍk…+01MD[ª|Žb¿Ô88¹/!úŽqáüiP5ñ¤¸^IPû*ÍB§ÖWéê£ïéÌ=Ûµ“pÚÙnüqØÇë?¼Ì׫³Ÿ‡¿†sFÂ8o“ @#*˨†@#*—ôçü½?ïýœÿŸÍü$?‰|Ø/ü?ÕŒ,ƒëC7Ëqbûš‹Y3Ÿ¨«§ùFœéª…²Õ\*ô[fËß'¼÷NÞ“²€¬€¿ö($ES2ï±Þg4…ò½²¯,WîÔ ™ú]3è¾6m‰ßõûpÒ¶£<4G)¥j1©˜0®âHåiZxu‚A(‡Îª#/ª•R\@Áèú=8Ð÷IEÎ÷ctµïðÿvóÁ$i©’—•ÊÏÚjè“§}»:+˜ÊªÝÚ$]Ñ*ñ"ÑVEŠL]Oó¶1n"Ó(|¿ÅwÞ8ð½¿?ݥϺ!°#¥PþÜ®Ÿ¶ÿå "Vÿ9{‹¦¤¾Fš0ߊŒLþx¶:ë=rý=¾wxˆÝï&”Œ0uDÄï¾à϶®‚tP¦|ÃòéÄö¨’UC¸åÇ¢ü´í禧d~úW“ýÁ®èÞ™™ò¨§WMw-™[N¡§[¶ø"#*‚xE/"ûqrLq´¢J‰h#wÒqÏf*eÊl¹ŸSwþ»ÖéZh€šï(Û®ö?éwbmÓ_÷/°úûÞDG•‹±öÌ÷]šz&‘÷3åeív/šBážéAEž}Þï‡/Ôº#ò*”·ý˜`y «÷—6kæÝ¨©I3UØ×mùb<~»@ÏûtÎ\Ü먬Y\Í©µ¦Ü¾.Žn“.eB)E’üH‡?©çaí‰ß(šˆ¹x#,ھݳ?÷BZ}w?/ói>ÆSõq êÃèÎnŒDH±A?\3뇡2ª»‹]zŠÑ’ØûÙA™vý¬,˜ýbrpuÞ½üâÿ¨p»ÕËo“ù‰`3Ís„MZ'´óóyv¢#**#/µHŸBÓš¯¨#,]‡·×Îz›·€ìñt3ôú´iˆv*.Z€bk#,ü¹Qlõx¢®\‰{—ÅZ÷SžÁœ¢CòªãýEñ°]WÕÉf{ífR¿½™œ[s™¶2)ë@ÞÇð#*t„ìòÖ@¤¤@+o`_à<´jyÿO©#*ùƒÑ1ð'ËæP¡8•$â±X¹+òr¹ó|߯Íw¬2C?ÎÇmÃ×>æ©@÷Å#*(\ѹD:V½ãÎLLÏD™O¨©Ë£ì·ôWÂQ{€£Çò¬êО¤sßærfF÷cããò:<#*ðÅ~Ò„Ž‘ðñæz;úpùœÑ^Þ8ÓÕ[cæ'’Gq|SÉ.;‹¿‰m“;¡”E²Ðœ?/z‚y?£A~šù°Óçà‰oG0²Ñèp[¤—òó<uJÄ…©æ~DXN¢6µû>8bw«pÛ$¼ïmèoG•*fŠw§GϽÚuz±D#׌6‹i¹buåmG)@“(¢Ç©QÅ^жèR©ý»¶H{ÆV'Ÿ™@ÇV»é¸tu•Äe4þʽ8_ó<±ªûñ0¤ZO—ïøé.°#/ëOsô³ËÄšXYÑTs$ïÓö‡¢ý_{ñ€Þ)Ç—§N(5&äù&à(@ž•Äim//r¸½µrYšÎÞ‡¥û ÷-Ècôm‡ôn’¨šþ/á¤Bö³8!K~á×à #/ØBC3â³ê¹€%”=[©óVX=ê§RôÂrS-ŒU˜˜µ ]èLL,Ñ8ÀWeŒ)‹OÓ0À0›<ßïñùýM½§#¨HH„;X¥µ‘Ë~ÝõŽã…^pv§J\Ü<sDGMWHt'_/uΕ›v«nÊÊÊ~èÉÔ#,3Ð#*ƒ8IËùû5 ÷TÚž±è÷xÄD9=´šj–ÀšîøÑ4òä#*ØŸ¡Xg˜0@®½«·#,‡¦ 'vr¤ã™Y^¥žùð®Í¦·×™AçCnÝÕ[ë—åÊ•¯”6†¿‹hÏôîGŽ9³há0q ZÇ¿E„!&‰âùm•!CÂOb)n¾<B>1„VÆošjúyê_^Ù]—z !P 1@OVxÀWéÞþ{ãú·tPzÒôá¶ad@vQdgiOòWH–[wE¹åní.tvK-d#*Ù€¥—b9?*Q‘1Ô„H5¶ö-wß·3–t.w/ÐR>µ»{}¿açÁ‘Þ` z{Gº£àRGѵ\óñÕÃâ}\%$“Wq„¬ûX]IO¥Þ»Æ±py¬õKÛÒ뵆¼wO]rá³#*ìQ™QE%¯¿Ñû÷ƹ)ÌÚÕrFê™Ç+D±³Ù¿ç±ñÈB–2!rW|Ûv´Né-lQ”)«›ªDŽßæ¶Ì–tƒz‹:Sż(ø¾û¿Ùñ9[ˆs0;ʼnßóUUå§S±óV3qãû\×5iL¤¼öƒcÚÞ¾GÎ#,¾ê!%²ê‡õå÷—E¤Du½¯8º¤ýþNŠÞö÷¬åú¾7˜Ì«í-Ð`*w‘30P¤RAI*HÈ+į~Ö§±Àk“QBœMr›å}MÜÚb+ÃümÅ»T"ðõHx{—IJƒ0R\|Š#®[ZÿWÃFûëáõû,¤QÄF9oxh>€lp&#,ÂÉtÛÈ'RÚ¬Ç઄‘Ê'©ºô,µ¥vRÊø>MÉ%̉Nz]#/ˆÑF-\IÿíÙ1˜ÿKŸfÔ ìºá§‘ñõ¾!ɽ:`½þcœ}X[óÀhç¶'æäõå–Ê›|Þ›M^þXºÁÙÑäû ż‘ýöNÇ¥šßÆ6¯ïŽÎÞU°êñqïFnžnÐÚ?J¬~“PAK3,HeƒZXÜt1râ:–Wa|qí³–ŸøzĦXt´¾JZrù_–.)3‰«™ýûÔqdvåÈ®ÐæÂqzôvD:çÖEÛ|ÛØÒ#/°ŒÚÉ[r¸cÕ¯X,kåq¤mŒ˜I4:‚(!dC«×7K÷MŽT°µ%Ìc¹bÊ,f½jÎ9¢•ß•Ù#,^›O\¸ Æ1NªGøˆ!T+æ›Ë¨îûgFcÆ'so(1Î0N0qån~ŽLNïˆzük1Åä§#/wòŠ:ô×ë:ísª Ǽ#Iò`Èø†Êö~j¸h“1.nÔ/uð¦+Iúb‚€H„V+{Üœbì17˜”7¶ÙìŒkƒ$’I™Äµ]{”ƒ‚¬4ÅÎJ_¥œ©Í§ˆÀP!pa.}^¾5·º>o3y³ìL¹áò{gßAG¥ÞÓˆtÊà]opÖª¢ÑlY¤#/Ý#,¹I£ç£‘Ê4Oœ¿))$w²¶PFyQ^ÈB²5—ýZŠmTZ”ÊD:eøTJaˆSŸ¼éDï¶cã¿´;lì&9¸Ëœ[¯ñM¢hÿƒhi”S›DŠ_‰¹oÚG}Íj“¿¦ó¹{g^4–Ìæzü±=m/Š!Ç_¾º'<Q38|’ß·Ùgãc¤¿„,SNí—óãƒg~®%s6!éëàííL_]ö¨Yê.IMÕ"NüÇTyñÆ·ãl÷ÇZu‡c<.SÔô’x|6)ËüÅ6Ññí3’ïNéÝçˆt%s†Ÿ#lââÁ„åx?–ÞëÙÛe÷SËlü¦8L4¡&Lèž=fõпê çNaa×øT”’œx§?»h‡œeãß-«µKº"90ûñ1Ø Ž»ÁNTdÿ³UèùÎ_µÆZG¦¸Qï¯rç)c¯c×o§Ž¶KàöäÔ¸Üö\°…ÏXLuZéñ8²QLÞÙŠX]ÑÇîßZ¾¹¢\ÙUÛ´"=bjk¦MiÉÉâ ^EJH@®d7a}«Ú¯Ä€+%]ѱ¹+]ø»¥zÜòxÞE#,ÚÅJhÕ‹ñÄÎ#,ôûj‘Ã$íãbëîÇ‚³ÏÝ·wÌÇ—“Ác¬`Óå³O °Ü¹'ˆ{8àw|{‡,àú§S·9”cįJnФWUa#*·óƒ£Ú|œœŠ÷)m˜æŒ>úÒ)§E•âô‡M,æ#,°ãu{E.Ù¾õ£Šr¼Áëis“b<í®Ü²î&~·Öãïç/»ãt=ÄR§ë ~†¹*£"Òø›w0™Äsøy?š›ºÇÇç`ê±I£u04ȼ¡}²õð}!‰Ï¾¤xÏ_V`ôÖ«Ç·õéƒýÓ£\úZå}ms¢£|0g”_„Cü=2A¶ö9ÎoåðÞ·c"gõøÄ>ñ“Å’–·ù%=ãP»˜fDHÀ,Ë”8s@ç…îx9“Yæëöºôò"RØì}ÒOú¢Ñ¹ƒÜö7²Jsˆõ͵MFÌŽÉE›ý,Ÿ Ä „¶'?…WÅöû^F.!³9©GåÏ1¸æŒ'ËÇæà땎'ãñÀ¾þÜì)²‰º~knçFdݨTC)¨~ojhè3‹;X¦í†¯›º[ߥXšö¾S¯ˆ†-<þÏÖ_2á§g~¤?GM;l¥ÜVîƒ/0VêúÌrí¶;8¬m%Èãñ?Õ=3¡pr1ÃÀ†ˆ°ª…å#/Ž4Þ¢‹Òª{”(aÒCMvQ‡tí‰ujnC_?Õ¿/ØuæÌ?Ù4J¡â–Ëúþ—hòw±˜Be.(xr]æz}œxÅvÉ®<EËÙOôHƒåá˦õ¬ÚmBÁ=3¡¿7s—gÊdý&õ¸Í‰ýr@{{vâ'ù_¢rìG½Iƒ”Õ.ÃŽí,œœb¤üPªzf¡š ¡^ô›½¼(ººúã]§™šØKŽÉ0àìE¹ˆlÐû8‚‡†ZƒØÊîB¡‚âeΞ,’ƒˆé·ÝÞž2L|Ïo‰2“ÞÅígºl¢+êÀõk¥“?R:aŽêÛØZe…%1O¿'å}Ü(~…Hvo½…§_¶g¯ÅK†>!Œ;Í´˜ž¶ažl<¦Œ…¤õ¡x¢ŸÔäEbB"}÷°jA «w…»Ðs¡œâ»TtŒªX6ås‚ÂÀàãÍ;òÇQÂîR>ÿJ¬EÌ×§\f®‰D$’¾µ$òR‹™F6#*\Æš¤–VÐŒ`%ˆ`Aý´ $$Þ«(C/•T<#,®‚ EäÔ¶ž°È6úñiÛ õyeGÙËäÊÁÈûcòÕjAž„ÞZ‚âó‰¬<~šû ãÇÊ7yØsâ(N&:9„Dó-^å2BÞ*™Éiüw3Ú‰ä1xësôÂÑs–3È‚‚áp½ú££=!B#*GçøRyFkW˜—nÑ»¼¶†(€”1Ñg[™·ç’‡"#ˆ÷tÀ`Ûøzÿ‰ÃÈÖyÞ@‰g7pj þMQ!áËpÿ1g?õqN‹'ñ%D±öqóõUÇÌÝRŠÇÌ«ý⟢)¬”Àþë•ýmm6uþ£üC͈ð_ÀñíP8:ÕÞ £pQ… ˜…ã–AwØ>Pë?Ú6ÛH[þ&, yÈ܉°Úg9üçñÕðù–u¿ƒ 1æ•y>qé·OóƒCðeŽý#*8„qo0þ|©Ì:L—fíî›>ßñ»’Õææû ƒ7¤HoØFrǨoìW>ß·ô|¹ëÐ;#/HzC)!‚ã§HòÅð:ŸW>pZg(”ýÊzÜÓ£C¨*H€Ö(Ix ì÷ çü:ÃF@*Ô‚‰•®aÉAÖ]j(Û• ¹z0úb0I%ûHV0`ˆDÙßü:¾Ü~ßÈ%£ñBЈ‡Çbôrx#,¼PŠ0Gº§Ä,ЬP¾.%š6¹J¼÷bu$¢çüy\Ïþ+uäù?¹JP$§™†2ÃgÉg}ëÔß·U¤Ìúg¥úŠ_¬y³\Š~¨Hi¨ñÜþ¡€ç*1"Ú/ŸVŽ×¹ëäìçÊ·œx€>˜ë‚=Á#*‘Ù”½uêÐ\20`ûïÚákf£"Å–%ës5Ó#*~!8Õsz‘?ÈÓA|»™Ù¥Å9(öG#,J€í^Pà¨ü¨ç¨)”éZl¤7ŽÔçP¥H!4#,´][o3:”ŵr®œì¨h ø’—Z`)-”r\€€Àö\¶%AC³³ìÂë˜\¤<ðrã#ÐFŽ‹ÐBÄÐòBŽË²4!ðÒ¢öTÄ0e^'Ƹã!…}ªO˜ùîÁ¹F–d*#*Qâ“@IÑ1ˆ"±ƒyxÌîTÛ]ðbGXf&i´›\ÑŸ<VîZ .ê£ùÛ#*톉¾3ÄšüôbÁé6ÖÇç¥Öîh6þÀNWU®û¼¢ƒ/øàyã_|fÐü@çàê€\à£t]r[28«H[‹õòÍE X¹ÿ‰Óˆ”wxQöä™[ºw6y ‚+´`ŠÉ@XY«i/›’XwÇŸ‡kPK–ÁÃ9X§w€äGN}ß³œ–Ág&øž0œw婹šfÙeq5Ê“ÀÙß»0¦»3œãÑÊÞ§|¤ˆï‹åÓȨü<Ó…¯:µ9ë+šXá#,'ßtŠq‰SR«Þ ›¡åF·Ëæ¶×[¢º3¨fÎäæƒõ┣‚bT€ªœä]#,#,K\£0ä¬îÄ[éƒI…9låÉÉqPo¶àÕ(À;‚Ü€ç±öãÓä6#*û5c~>AtSxŒQ9üºà§»7tY1í[mâ;y™iÅÙ"ƒn_Døér‚íTb|"ÙµšDL$Dç#*êRo«7!šß=8èŒ{i¢Ëÿ»ÐÚæ ǵ~UL˜$JýQeUìå`¯gtþÎú;âZ9Uq¤íJWÄUï´ÏRÊl!û\Pÿ‚>i·—>ïê½Ý¹h‚«ªc³”6‘šÍ1jëÆ°Ãõßî…þ½‰Ô4hx¼¤¸Å´oµ¡úS;—EG [{èôÑ‹Õò‹oð"ÞÆårÇhJþßÛ4#="P„Â15E|1dRl/e¼õŒ–rÛ`øjÙOçÔÕÉݦÖÅ•øuÅTãGî„æ¸¼‹³¡GΔd¾"é öüÕŸeþ§gbë>Ä•„Çu&çõÉûçAü±›9ïÌ[]b®Q ‡”ÁÌ2QPÊÛtRïiÒD®2Äa)1J©$FRÓÀÄ©%#/*’ò¯Š<¤Æâ¢ê9Íѱe)§Lá#úÊÕK´&9h?žçZéž´ÆWÓ¦ ö°íŽ|ËX•³‡¯¸zrmYæ„Ô…Ï´Çœ Hæo¥ÉÂËÉÃ#”Ûä±ëRÍ8抪£ßíÄxZZ-Ï»é_;Km߄ꮾÍq/ge±ÀÜ6ˆãÈ&šRÔFú›ÚâçgÚ®_U, §v¬¸÷OÙš"aEó†Òn²ýp~Ú%Ö¿Ü:AŸtP_®™ôµ6A©¨ ¬Kk;KÙËs.¹Äš`ÐhŒ†©sSFÌ(ë"‹fg*ïnBð6Qø>Y…ZX C:z(];hÍz-Ö‹C¤µtâ#OØß={û°@™a7ƒ‚èߢÒà÷·PŠü±xöPÏ:H?wJ“sÀ[žoyÑ=uœ£;–ÇÒªª*µ$$Ī)œöCé¤!ÏondªÅtMëôŽh¾ß¼ùx ÜÅ›Ærf‚9ož½¥WY4Ù¾µŽJ×TiÉqƒ\ÅalÊÈ.D‹©äŽÙŒ÷X„ûkÎ!ܦ]‹rÌïV‰ló)2š1´ uÆÆRŽj–u—‹®ãU+šo™]kÀpùÖÉ£B·ˆ‡ÑÌ?…(î‹M¯çŠmÃv0° Hpð#,žÍ·úØ-²§áÙæ.k¿€ê?5‹¸ò>€ôVÆU‡Ì¬D:#,¿}Y.@åú¿5´Øp?>ÿÍ,]ð]Ñìöõõ4KÅóƒŸ#/~îv´¹ų̂Ë}jê´?ÝœÜêÌæbó+«±˜™ªTµLÁT&”4|{*pÏÖN©³<¾U£Á#,Øpª†£7z9*g¬CvæYÿ\¡·Z9Ú`ð"$é?E¾ÙÏ_‚;žÈ.éÇcûˆ@L\=dȼݳÈßŇWÕø‘CC^”Xa|`Šv>]#,4Óþ+€}çÞa‹¦tǹ#,«WLÛ%åu5#,çÕÒ¡è©}Œ˜£rA6•¨)™â«ÚZ§é³s~?@t¶<5ÂÔ#,ŠÐGžá]T…¡¦Ü¾ºÞ={êpyÃTXî´Väù}::qº”Ä9@µÑs›0ÐÃÚç2a£÷Qþ«‹rp\4hóî[™,ÑßÞ¿ßúºÚz–,#0Jp¹à”噓ÏbW×^ôòùö_³¬¢[°*×ñ€M±™~Ý…!X#*ýçG·ÃÆ£ÄEh&#*¥0Öü?_Ä„8k7ª>>\#,¿»uL*,UO5—¤#*¯ŒÄ„q…þ‰æëònß(¦bç6¢rª£†ng#/UøkÀ\å°l#U•XRø^G|†Ç;¹ÎÚj¼‹ÈU .&¡.sKnù¹5´2 QhéÒ2J¿IítN‚@žÚžqML#> ¯ÂÖn¥àLß#*›¦3|!‡ º1Ü´òíw‡’¹ÌM!UUd•·é×'cÅ“Èè|ûØÙ޼ׇqÐÚyàmÌ’òI*„„{.îk·cÆáÞÓuG‹®ý® ‘AS0¹v÷µIAÈ[Ó¶«:Ìá,_…E NI+^ì”.¬"4—¾ÀzÜòOMªØ¿›{Ÿ’LG<÷äü3Äbj-A%¶NÓ ¥ðœ©ß}Ú\ÍÝaî8ÀK$`êÜ2¿À0G½FÉî(°‚ͱ@th–hŽ‚†c JØÙyHÏ\´»e«—³¹ûŒ3÷¶™_ží%ˆÃ<DffQ+%}3QK×1xfrŽ]öR’P/"Ù°la!Šä¾†œíGv¨#ª8eñoŸb®sÎv¦î´4G‘ñÞç—!kÞ‡IBƒr†Ým#,ÅC„Ji1píä#*ò-®¾¸]„okß!ås\|™N¹ vgnÓ´fð6ar½Æ[3ïK¿›åø³¡Àº6X´Á`‡[b0|N”“÷“Úþ+®ÌwÚ}-œMѬsuöy3§¹ORصÙt}¦[™ ³¦OCîü‹¸NÆDôú9ÅnÂþb?ߨß+÷’kÐÅ[¹ô©;×[šë×ì¢4zfjs¡.64±•k{ØõÝH«> ‰Ù=$p)ËÌþ„ȯT”òç¼ðßÑë…h©¼†…E²Î‡+iˆ²:Ï@r:Ëéä)’¸x˰an£y³;N~G©ùuõ߃WTb'\—¯@–åk:YqtÇ#£±`¸jú;§¤YlëY¹yÔ”ïŒ(g󬺡f÷YŒÁNé¬8ÝkNèX®CÚõà&Ïèk9\Ò!×¢3Ý"«ót΂{{‡Zçb^C Œ.*ÕQ§n2¦/´a-Ur]h±oŸ?Wu”GÑnŰ“œý%U°GD‹B-CQ#Ô#,:©¾ý¸'CAÔ#xkÄ“˜H¦nß6¬œœ‚£#*O#›†÷¢6ÅS™¹ØööÁƒÑ*6à/!*a;Ũ@Vå"VË¡Ú=±k#,·-½ 1#,FDtu>Äm‹^ë%a¬QO^;t½¬QÅs³#,X>ÄQo-×ç]Û/"¤Õ ίáœf·,3\Ci½H¶ô!Õ Üe¾S{Â1*ÉœW$Iæ[_ö”dìíâ+ÃOˆgJ7÷Ç¥º¥éœ‚ÀBÜ7@k¤¬r#,™*'9@îe´X岸hú7幋€9-¤ ÷èmhÅ»]JwRU”q¶ÎvŒyõ¥oÄ9ƒÏ³´ë#‡›4º v·Ç²”/ÞX·— §¬O†CÓ›/¦G>fG?~¼Oõ¨Ú¸š×¥W¡Û¿CTý»¼\–›ÄͲÒ#A#*‡EF ¥(È6à.`]F6Žåœë€pKÀNîr%ÙånE¼–²åg“VÄÎô[÷^TY_c¨šÇ"‹ö냹/ÔŒ#]zõ½úօЧDQ2ÖP]!¾’¶T–ç¥áºÀù<¨¼žïYg‚s„)±p‡€†=è1$rCˆxRQã¬C9ñúý~Þ½Œs¸¿i†èíÜÑzè?!#£Ÿš=pÁ®ä8Yp¶@Ø‘oDD÷ÎêF9tè³Mü,¿_¹árä÷sÑ7¨ÐôÊóçÌÞhˆÎ7ùÓ ï¿x”ž(£”#*y#,0pŽŽ²à¬«“™*PmþÿÕ·›ð÷ûG¿Ì>/¯@¸è:érýAÝÔúj£ëÒ $ú¬ô¿·©WÊ¢‰(û쵞Åü¢ô‘#/ʳ_+Þ®À‘¢Á˜ãRÅN¾Î¿^Òvò>[âcò°V^þ°ƒñÑËKE°¾ÃÀq#*“úþjÚž.sß´rs0ð‡Ï>ÎT^ÂÌ#,Õ£N'Ôe:ä®Ï÷¯W}½ypýcãYþ¾±âužXb2ÊÄ·än„-#,í[],ðg ±ö#,~ÆX¢“µŽOÚ1ìgc§?ŸéXÛ÷e¿ûúzïoº#*³e©ÖU„äP§`Bpú#/õ¯»ú ïþxÝ0žàoÔj ýÈæ„÷ A€ašùˆYÃbs?äÚ%¨ßùZª…Oî,“øIJYEC·ùMjù¢<?© ‘£h¼B;@.J,ƒ€Ö™#*±PŠõ–„00Ð2gû˜ÿAm§–›ÞË-ó¤)»Û Xmþ3}’KýÕnæÁsôo‚hz:AŸGb,/¿«¼à*jLÐÚvÌ#*À‡”Ž\įg3jNïG›Ï-Áaã‰B©ŸøLcT%x²}ð#/2Rq9r°[°—ˆ¼„Ãþèfc9f@©»¬#,^#,Y±íxuƒ‹õ¹û°öõÓ}¿Üú\ô!ô_gÚkfÈhf_ØŽè- '÷ÀÿdnÜ »“ç'h›*–ÈäÂ÷.ÝaššÌÀsÒacø^Øk)#,p$d¬éý¹'œaê^cH!µøl*&_ï¯fÓ·ºÖºœ›ÆþêðþªìªýRÛ:^™X¦¨[þ˜yþÙx=ð8Z·¾Yɹ¦\’B8šjUz½_ òþü„G2\@•‘ #*5bÂÂTJò;5Ãïÿÿ7·éú#/þÜAËÚÁ©k ·EÂÁ‹ÒHÑÛèêó|庿‹ìEǪýV8à´¾È<èè IVK%UkRÅß‚®Þ}åµ0RùÒÔQ°-¯á«´“´«úÀ¤·÷!zC`Âx„Škôþ¯Ü\½!¿] T0´#/ä.Á)rœ±»Žl¤néÐ-#/þvâT#,N–ÍIaÐì„C‘\÷&#,;ÂÔV(»†m!àeÕ%“?æpXBÚáS»””rí+î!QÓË«ÍMVë6ç.Iëùwh5Ô,äOaQì:@Âï:{›umZ?ù•5fÔmQ¿zž„uãqè5ßG²ÁhÂÃ$ jl#b1“ƒ#/R%Ø'Rs×á#*åsÐÈFÏ¥(À—Ò«lÙNaÎåŒvÐßM—OÉ·#¶AhNï°‚MröŒ% Uµ†ôú ú¾Äíz®€ŠÈO¶¼¯^‘²É>ï°/rxÿˆí˜¨*¬&ÝÖðÔ»ÿ0i˜d•xð~j. mÈׯþV2#,þ#* ù<É Ù%¸ºßŸúxöç·ù+˜;#,²È»#ÛI³ƒú¸]0ƒü”:ë.²j†A‚•…<Ó×úözúñÂáN«óibÙd^×3è"„VIû§ËDZ:ŽúJV=~ßÓ*½¶÷@ö⚊ûÀÖÿvQǪ|'Ðþ'±"ꜙQ8ÖnлêꆉÄkXe×AL‡užïçõgàùºÍoìÞ¿¨ûÌï.ý»CU³ê>Ãi!ÂhåÐIÛ£F£‘¢A£O‹h,#,ä´ƒ$÷#,'·ÄáÐê9ˆD4õ~âªà‘â-#—æ%;Ê‚J¦j ÝW:Mî`žA6a°LÏú®Ù#,æÚ—,œ_íyØœê™ß¤ü«ÇÊë+5›¿íYI0à&.Ò¿–Šbƒ#¤Ö§Ov9K.:D ±nŒsŒS;$–#/BªªwI$’Þ"0ôÿ³ßvja¼õUÛ°~'#*¦Ä|ÅÏ]lá³4ú#,^ƒ_¢‚l=ÜáÖ1Hˆyλ#*xèšš§#¡ÄžÀn“¤éôÕ˜v¥›dæQfåãχòµÏyéO‘ÎæGõµ÷P¯éüÇúa&fùˆ ?ôõ}zÞ—Üs:ÈTŒÕÞ7öÀ’6§ö:äýoÌL¢†˜ÜÎpxß'#/q’R©Zf_ °aP¬¿…ÊŠÀ-üé·Çm@ýa1”‚$y× Ãd(kwü_ÓýÏòXnmãGâŒNÚüOK‹†ÇfÊXQ2myŽÍ•0y*ÆÔO„?›p#,¡™ÚB@1¯üÆå$¿Ù—©µi•¥d`ŒLNËšË.sšXÚg–y|Å‚ÚÞ’ÁÂ4#/D ƃGêÞ³h¤Lînò—dš#,u¬!çál¾ÿ¿ý¹¡·íuýÝZÈ$(i‘^Ž¥7Óòäñ"Àñó9¡rwÕ¬1ÆvP„ Ù;àu†H#*§Žö“%#*Ôj!cû¡f'¬Ì8ȧÒûì¨;ý(µNzt¹Ê.®iÅOÝšÂSbêP„›tÓRq„Û¸\š²6âT£u0ǘ33b¡™fî²3· “·¤{Ž»ýÁ¹´cÑ÷“Û0¨#,Æ¢‰5Öç÷ì’NðÍÔk‡.Ô^arÈÆžó£±t©#*ަÈduQaÍ€jÓa©ëd”h]*„5†ÂI¹¨°`mЇäoWì´ìðÉ~ÏÝGò à`32ç®õ þ—Ë£%¥¿»çðUüÞk§¯]RoFJLÌ‹û•(1±ƒ`ý8RÍßó~ýÌFçvKK½Fá2™¢WYY£Y§2'¨6C¬k9 Z]`Þ:Ë2¹JD1Y7k¯$’I3Uk˜©šÖµ%¥¶žf®jË^³™Y„uã.¡Ž½aGƒo{ÂkzDhhk%Ü7‡±ëXìÅëušibÊ‚Rh¬gù+Ÿ_¯ÖB˜È„„„@*<à/Ûøæ¥‘äG<Ÿµ€MŠƒö‚û&¬RÁ¿!ÓËÊÜãªq à1wÆŸ?Rô{/S>¥£ƒ9§D$‡ì]ÂgTORÆÛýpÁ«¤F3Ï.ó%%ùõû÷VñC³»>´}_béãÄ3UàZi}ö„¶Có éÛSãJª¹&àÔEd&}¯AõôןÄû?Ù¹µÌ ÷Ë}…+è´.”ÊDÉ“ŽîZ‹dN…I]êìÖD@<]A Û/p[ÂI$¡´} Ñdéÿ–ÜkÉ¡dÏ#,/KUYÀ¸|#/¶Äh)"ƒÔ¡F!¤cÑ^nëM·¤×§ |ºu›™~%>GŒbrØzb’)ûuã»[®/‰¡X>àeè{²Ss•#,#,O@SûBÍ‹68 ê}è]:7P%ÎÝü7³’D‘b¦ÎûoÛ®œfíJW,Q¦Pƒd#/Õ~:iuø˜Eíö íîð—€ñ#*H¾)¬V)ÄU#/Paëöˆ@^·Ë¶!‡Ïæ !OŸñöýf+0Ô#,…:R‘è¹ø ¯Ý·#þ¶æÀýŸ¶ä Ü¡‡ãJá…¾G#ÙŽn»¾â©¢–¤*Ù·3Zš!¥ÀõML·P뺳#*Ñ/vkK*Šƒ”šYÒ•#ôìéÌ:¹ö•ݨ¨U¶ãöıA<C)" ý'q;^öIë,BÅ%Ä`{ÀŪš2Å!뉊IÌIÈÜ#Ç„¿ˆ_%Ì5§K‹mÁÞ}W#*¾HjÔ>ÒÈGí .V~¹aMœ>Û-Ý#/‚#* Kü|}ÿ`\›Ü}Îó¡|·qòU»/ÀR“Þö(€ûëëµIõâðkÔ’Þ—°l÷Ð*Ñ=ÑQLn7"yË[ñ%J“ÔCî»r`»ø éƒéûßäîw9ï“ÞŽó¤©mŸ`ØËŸ†ß:#,Ù2(D$V#*yÎ ‡ÖÐgØèrÜøœïƒŸuB,cN@wöþóô;P@òÚZΑv¤HÝE~p=ŽÝ¾)øœ:Ä=â¤T ‰£¼#,¯—h¢LLÒcùÊÁ‚ z·óé®ïyæ.æŒcÐwšrÚµ;AÙ@îõ¾š-iÿI˰=äÜ¡ö÷Q¦•E¤ÍŒ&£bŒ#!ÞuƒHYÖ¯ïu{ÖdR)³ÇUÎäâø}ú›ø ^‚>KÑy¤]o(uœ•=äþjµ¾Ï¬B¯ú‰÷ýf^ãWÔ?ÇGäåüa¼ýF²ßxû_l›¾Ž3%‰[£CäŸ+¾&Zˆ=ÿtÏöCÕ‚¯ªÖ G ÂšÒ {ºv!!êÄd’Iî@¸#*ú@ö¾µ#,›¿ƒZ…\£1C`m`ÕçòWò¤RO³¬DëŽ[Ú]½$-=åšîýmžGÂP„;¥cÃszaSJ3¤ÐK¸éôÖóá2µÍ,lÒ¦(Á;ì'z#*&ÂÞ?o¦èìŒ+•}Ǫ¤¬Psù†›Ì°,Fu¶³êUCãÐcMIôDb-’‰ÖNáa_a̼àSs‹‰¨5– µ|Ì qñ;IݲXçŸäð2fKõ&ñÉ: ²Ï|< †‰D™Xïº˜Çæ™Tú’Ý;ê&#/¿¼†PgGÛ·'–pdeþÚTN[;Ô*2`‚Ò«î÷üž¥QÈ$Š¢T…œuzæùóvÄ4hɘµÖ-ÈÛ0ÑèE¹½„Ér;Þ²ºCSêáêM½œÈ¦aûS<a‘$Ed¿À(‚Û%4ËùöOrxž£¤»Æ‰#,¶0`‡êí;ÌDùÄj¹P]Š6U+¹wï:w ú žnŸC™éï¡<Mç›ÖŠàìßÂt²#/(=¦Ó^ãWw ¥8½Ù0ðüÉmÎ#,„"…<Ë™U(½Íg·Ãàí}ßR|“ôÇOw`SƒìªLʨD.•ú-ý¡ýÊ€~M$‰¡É?ªmQÿmRR±¿õ8Ør+¼4 £)$PXuÚðÅɌڕ¥(d*‡{˜£ËÏÖüZú?¼ŸÌ~ú_(™‘9 h”ä^°öž¤Jãd«[áÙUVÔ‘Ê*æ#//ÿBgîw!¼·VxÍî"vl÷Úâ§´#/«dâCfãoÏèo~3h‡HHw‘œŠ)eÊ×fÜÏßÚþ6¾õüª2û³T3‹ºàuT§Qñ&cçùé'A^¯lSòÈí»ÄÓ¦¿uß»gNŸ,åyž'€F>:Ï/Wçïö1?@a÷P¥(CÔ(T-w!¬À‰î«`3%˰°?Œèi¢>ÓϯOçš báßÁŸ3°h´”{YåpÊK2{Õ‘ìšÞj4õ¹s2Aa¹ª·¬Q¤ŒýÉu±yP4UŒU‚U©“8—‰˜G ¾ÕD}åÒÉ"q?µÌØ:Ú¬#*§` ;Ã÷Õ;¦–ž@ƒcc%&D½•$ôD^Ã*B"rbQTÔ¼CУ$:@H:&À!©©kõž8vÐõú#,>Q FÆGFhþ÷ìÔÎ¥ETÖpEŠœ¨#/€#/AØÂ’E:oµ#,›¼?,Jwn5)©À(üøšÕ…xˆÇʂĉ"ýïá=³ñ?{u'ÖuòV÷~iUúê© ‘^ª.Þ{½”‰~›I;(Ñ[…àeryc#*šB|zäØl…6%34¯—y¶ù4k•^šæéµÙ#,• ˆ+-KnëË̺¬òv´KH¬ SwöS¥=>¿_ßœ¿Öóƒ.û½3ÛésìÞ]‚‡zùîº|™È_¸ kÕˆ"#ƒíó=Ãc˜Ç ÐÜcN³cøÀµ˜‡ëÐ, èä…ˆ-ꔑŒT‘#* 3 ˜!¨“«¤tÀÖ<riÄÀNœ®ÀÒ-´SÅKÉå(ºïæíáÚz)uÂKžm:ιÓÔ/!ÂýõB¥èãHÍzœ:ó+·pþ©î¢’sqBpïÌuPó€°âàQØDèû6”m;â¸w6ÉÑÌ]®†£¯×;o®ß…¶¸!ÈSŠPÍ’ãCvÕ#/¨aïóî2íwd£Ô{?5›vÂåßd²Ðy²þÞzCÁÁétÝr(›º¥99>à?‡¸ù°à-*WœõöTöýgÏ õGö¨s_¤:ŸFÖŽæôzêT?Ä$‡ô"lûÅ¡V–žiš¬Ðôä/#/]ÐÂe#,êYêY%Y$‘÷þÉ ƒìÆÈÝÝ ;E· a¥¬S#,eKCÆ6È@ß`’ÿ“Úó»iªJbÏ}R*—Tñý…÷Ÿ}¿BÈ#ÙGVIÅÏ!C'$/Ÿcülób‚$ò!<d™#J)ß#,ò(Åú€éì²ùŽ :º¾_hõ•%¦âŠà/¿`·æ†ô,¤ÇW}Zà@’é- ʶ(õ¢3¤âŸ˜oãÞ¢Š¸?¥3¼åÛŸÃz¾®¯ë„9q¡|ÈFÖ>íàĬƒ‘“¨tˆ$VF1AIgƒ;®$‹½=7FÍ#,Æ8;‹êKôšÊ}'ãû~ÙýŠíûÁµ}†¡ÐÕ¦Pü3²ÉW€hGõÇÚjÆ¿ÌV4Õ)‰úÈSý³ï1sbwá5È‹(¢ úŠUZ*`æ1œ(0#,‡nD²zHöDß Gªåxé “bLmˆL!÷0¤ÉCÕ8¬2âÊpㄈ .b©@Á ‹ü)ù’*ÈRúœ¾`ôP{þ]½‡^–Ëž°a#/Nh…"”°Y.-“CŠÄÁw¾çvføE `zN}#/:“R)¨/Ø;.'ê…ÓžþÓgyAS|!žõ{ïy©©l×ñû¬—#*€©DÏDQæë9)Ò>}º‡©Né Þô@ì`ösT øÜ “!À8MçP÷ÙRx`ç`rÀb*6â,™{ŽA<CS $[˜"Uš#,^¤ÝóRŸœöy~óáN>ˆËÝÏ-ËçEYÀžìô Ó¤ª„¡@‰³³2âÌ~ŽUù"qa7uÒ ÞÅ’”…dÐG¨ÌÚLíý¹8æÉüD‡ß’©è¶U”’ö¾_†÷¡$U#*M?+aܤ¸™“¶Ø8M^Ž1—5é¢_e:³5d©M1Ç"üú@”Hÿ²¸?çIÆYÄm2c×gpº½@õ‚*ªU'l›Š+”ä½%–Jf¥¬(A©|»„o*8¹hÅFÁßÜ>ÿ‘,~¶©Ÿx>YØ<<¼{pv›Ìdö|Gsx5Ö휇!¦Ð[®MÑÐôðâ#4›Rêy#/¾EyuéË£‹°¦+&qGbd^®›H¥x[‚„õSþNã,pß78l#*Äx‡zþ}šõcg,MHömÌ3¡é•#,t?a6ƒ¨ïNƒ‹q¤bB:1äA«ÀFÑ,1@)X'3…Ê+‰ò„ó‡“ÉQòùúŽ «Ø#,ª´hlD›2Ú<m*¶žî®žD;veÑ„Xm#(#*è?!®úêƒ^“Å#*=ޤ(ç¥xé]»Õ3ÝGòÑÚ1#,þ#ãc"žICÇÜJN—nóBV$I 6ÒâwÝ»¨Þgº(êû“ëüçðíœëúÀ#/“P}‡ÄËÍ÷möÿ°Ö.»C'?ð?{ èÓ˜[?lOÇõÖ"šÉ1ñ‡{\æp‡•[¼»”§9oñsù/ÙGãùBëN¶†ÐÌâù¿.vkõ¹ûÒSŸ°Å3šãg'Ÿû˜ürnìë+Ž,ßXÎ#*sáöaú«¶wúÎÜ~ÚÚ²×Ï`ݤvþÆIÏ#/sáN*j€JHˆÝ’¥òÔÂa»BƒhîÀêb*ßS#*ºÁdKøC®’NÏ´'Øyý=ŸªUW< lA;áAÍàR£H{0ÚöKƒ@!Æè\öx*k̸ýñ÷ò3*÷'±˜ÑùÔ‚Ç¢##Ÿ¢ ,€ÀŸÅÚ(ø‡pÀ6$éyx&J@2ƒ¤L h«Ú$#*l½IÁÛÏWV‚ÑÝßúw›Hd?¨öXnŸ-{{˜AY¬úçØèý*{ɬ6CÇÜLÒ/úò2'èGÖW›j¡Zƒ½û lbU6á#/{‘‚8Ãgcq¿¢ôÍ^Ðà`#*ØÕHnhn¬UTX&†”Öìû½_½öÿwÆ&GñÕµz¼Y#*#/½À‚‘½ô»®Þvê5ãvëm?~ý/Fð?µÄâ(Ä}ïž#/ÈR9®q!5ÀÿÜS!ÎȹçŽ#,W$Ð[È£Mù/ß_xg6)Ù¶PS(c¬> V›ÄâbV>_Âñ ˆa$³}øƒ€C"X &hÆß»®}î¹[œÙzgžo)$ƒô€?œ5Ô?#/ÓÛîôûÙ\®ÛX}¡õiðü¶„O`Ðõ Ä>Ôt#/ôK„#*ËäžRǼÑÓ‰Ä@ÀùÆL×åßîº<1Å8ƒ˜»±òK9ðú¨èïÚT$$ÜÀ¤®Ÿì8ŽÄ:÷#,6Û«uý¡¡ 謅¶ýWä°îâ=ÀvÕ«-Cí"(¨ˆ¨¢«/F¡EUTCï¨Ð3ýêüö1-¨`»üfk‡êÅ+Ûšœt‹ÁkѬFÚz"R8°l-ЦÛ,º¯È»À˜ª‚1ˆ2$¸à*-ŒÓâsê?ÔW÷åcÅ\q;•ééóT%4ÂÔôþ¬4H*üÂãó<s&Ä¥ü' ïžÓe¨$;a¿rÉR½´ ¹Önw¬ln9¾ÓNS’_ã–O'ÊUfÞmçæ8(ýióȃmfP?×#*û‹Ãf[» JõUu_D#óGh"duwNÅÍÇ섌>×½P¹âec»¿QÊ^r«ÿ³‰ì#/¬ÀBCLʆt«ð÷Os«ù5÷#’#¯ôU–k2¥¯t=é¯õ½F$ÙÛfð.B³Œš_m“ꊋ#/eFŸÁ>Ý]¼ªœÆ»{Ší2W´Pk4£Ä¢Ñ„ˆ’H#*Ñ€\˜#;X`™çÄ#/ Laö¤£ù/Ïü°ñ67#*l‰b/?§ûæHäg·ó?WÕ˧Ÿ¤×v°0™3U¼µ[]ÂuhïD¤’Ø*1',ŸCÄù>ðê‰ Ë¹í¾è¹+0ßùm‚\ý»:ž¤æ|>ðr§4ìý¨}Ê?˳¬¹}ÃüÀKš/õ9P·r¦Iüª‡Åú˯ðþêùîh©Ýˆ+),¢i1H@MXášbLtiË)%·"¢ÉE§è*ð BM-ÀÉ¡‰±¦*"Ó!uC”›ÐÁ\Ë,‰If,´±L¨¢daE$`2¨#,„Šô‰µ?Ëõ³øŠ°†þ33Ì8"BºÙ’Wˆ)j1ð/ñÄ@Ö´°+@Óö¬Eý¿ïn“…mÆDdòstNûítLß#,°LÆs8ÜåbvÙ6q,š%¡v 4ˆC$b9KZCjnb5ˆÿ€ÌCŒGöV{`i}”HÛ1¤Ú|P#,Xã¼*ªðMþöýo]™°ÓÈD2ÂBÃbô[õ§ëÔHÞµ;O×±˜d¸³™ ©þéÿ…‡m}jÄÈW›¨#ÏùÒwŠýÍK™œÏ¥¿á6æ>>ÙýŒj fué׳¦L¤‡ð?©PhRZ,P´–ÁRc#×±xAùˆÀó5=N)ÏûI¨¹Â#*-BÓÄ¿Ïì7ô ôí®w¦Þ󈟥K³²æ»LpÖÕ¶Mˆ-}ým†p«µ™Í@¢dEïP÷3Ùˆb+Ü/pÂ6civ”àJ¯{ƒh#Kìv\rÆZ"-$,-E‚‡’C‘ýø‰B‚;ƒ#½ÞÐkZ÷•jŸ3ágî ¤FñÊiŒÆ $”‡o¬~ŠI–l„%¥«`§ìàáÁÀ#*Ae^a#*¯Ï&Å™ÁAåèi‡¨¯©C!,·“ðñj§ÈŪ—>‰üv+»¯a_ãŒZåƒX=1DxÛ#*XÑôoå""6ØÂ’:3‹Ð¾&…à Þ?ËøRó|傳åA«e®ú¾4ÞŒÄßü¯“¢é9öñð3i¯½À$ŒtŠQžžÖIlQÔ-=Ànå#/øÜ“˜šâaIAò7Æ,ã´3Û?Ó¦NëàmŠìêºúežYÓ^.#/aD¢k{©ˆ¦c†s©ß4X'â(#éÒqºm}âkCeû0å:Ö‘àóáK›²Y’x½ötÕ,»=Z¸w¬h?ÊPñ+™àEعìÿi舩ãcdCÝËWóIì3‹³ˆï@¯èk¹;ì} ÆUÖ‹@ŸÑ;ùv¼ÐJú‰Âˆ#*ðÁîf’£|¾ixÍýNõl%@!0!òåªÿòÿñå³Ôößèï†xìü”¡£=¤?99ÀCõú[o£r2—ñâª;C†Â5UF`„‡¹fw_7áƒâò‹à#,èðýJ½¾íE8döŸÑ¯ç¼€3D\&V¢`SœÙ°bÎßÍÖuâ÷k‰@¢mµÊ¡U—´6ôHGåÀne!ë×ú¿Ô”ÈÚ¡^G•ÚÄÞô?Û«òÊÁA;ìc€Ò&&÷Ù µCÈO9—ࡲp¶ ò–oT#/@HÏ`T¯ªŒyÛLtÂcãpv#/Š;:d÷ÁGýVŽqÕô?3KDmÊÍø÷\:_¤Š>`õ@À£*§Í˜ê6]b àÎ÷¢1Ìû€äuÍäò}j‡üë;à$ËÑØYgô\±ª(O±â{ß?¿„‚ÑÑÊõ½DÝú#/r¾ïؾÎQlÍ•Á¬:—bä!Çoh¼QÛÓ¦ÞÇjø¹hËÕ;/wó{¼Ø"øNZ²XêþË×7Vçým;å-5}ùLjºZXu@#íQ ØdUë…Ûv™ÀVÉ~§Ž±îe´Zˆv*b`Bn¬ÙŽSÒÅÊ3QÚmr‹MGȽKŹSDÅ&$Û¥÷*ãCŽ™ÄÏRNº¿Æv¾†ú¾Y/)ãI¿°›²Ý„a ˜tÙÛ8~¦"ð«à£vpȶO. Rå½óMÐì:¦Âøðú^üãcŽ.z@šÙ±Øºm`†âÿE°+”¥ñzÚo8”¾04¶ÁU.Šƒ‚ŒíT$bù–M¡²¶6Å%¦KŸ—Šxâ#,{`‚G!Å:?#,cóȺ¾3à å/¨îtËôÎS,Óf^Z(Û¾S™Oe;·ÅÔyÓJJ”bh©š47 ¡’0IʵžIË^Z轕²k‰( UaVDp'•BÕP[í[hXÏ'¿öªÐ¶‘ÏÏÞS÷ ò^Ý´×Ó>¾Þ©w?õXr#*˜…x‡í³Íïi韬Ùz:ŒEƒMÍžþâCB<Û½z‹Yø¼šbçå_Šž;—ýú¨¿.÷YáwúkÄÜm_³j²áÔøKmGä¥m³—‡u_–øRR/û»f2þ4>çϤÞn19×PëhTg´Ñ–Wœ‹LW*ú¡vÒéÚ³RU#,…I#*.#,ßaSnï+Ó(Ì›òHÂÈìaÙû ³˜En™»®¨¾½qó˜ÞVø5Ú¨ÁÀ R˜„ìc— c¢ð¾Éð£g8/•ÒC)¾õË€ñ¸<;£È £)×½˜t*‡æÁ¿vðÇÝððÒÀ})ö}éÙámñTwçè—|Eâ\Ýw^#,8Íw£¢ëƒ»Ä4&æÛЧzìb#*NšUü‘æ}T†»&‹ô–ÒÜ¡rÈ;!~íAs@q©üz>#*?ýâ2™ ÊÍÖŒô¾)NIøêQêLö¡Á#/BÙÍw°Œ¿}äèÂ_-@° ¿"³ì+ªA‘8 qp;] ‰VìÜS˹òãÊ=÷_×´´kMÅkþ\ð¾;ððìÅÒ?HÔ/98j‰Ÿ3Îï!¶#*°&÷¿‡ožo}† ¾MëÚb¦M4ÐXɲ+Þ…ª~i'uôÀôF6c¸÷KÛáíìïÂ[¤ÑNg¦p—pöᤆî€Óæ&ôÙèG:ÞïíÊÌJ4þÿâ‡=¼n#žb÷2î-+‘Õú@Á†´XÂ’U"ë fbj«§å8Cdn¬™^&4‡ÞŠâJ„åpâ=,+!»ž#´Ð‘b©µ¹Y.«$yyÄb…ëÑÑ0È›õ¬FZ’è€ê{®`Ó°»œ¨Ñ®L…«ör£õÏn2£‘b‹0î<ˆ„ŒŠ}?Ëçÿ\{ßñü|tz¿¯ûëWÄ#È€g[8ÿ§z‡ø¬[Þ?!ôåYB) à#,Žw²n%„|Š(¼Óù£?gqÕmF£Yý¶Y#*j#ù‹ÆOËò®ç@$PÉ”‘<åŠ?f¼»»_óø þÿëþGÄn!ü‡‚j#,-èIoÏýf[ÑUUaÿ9èb7Sý€û4¬à“o¶€rÜð2 HpäLÃgIüÀuìÚ=òovMž¹Ã`~У6ã|‰G5#M!%"F(Dcþ4þ»/ Ý®jt7*}¦YØ’Kàí‰)u¹´ƒ#*ðÌ7Û«µ»pUâ0xCÒB|’Á:è!7-àn‘ŽÂ‚A¤kès;éDzÐ}¬pàè,v$kp÷o€á#,aáƒàð¼Éì7€ÜÎç¯Ip'HN{#,!‰è¨oTÈ”ÔÌó3!©•³?¸Øï8ýM€½"%JÆJ¥j©TjŠl;3`:¨5#,äg&€N#*=ðuòdj¨ònaÄ*Â|žgì>ßáJû«·ø§#*³bRˆhß9ñ燗3Êd(èê5ÙE¾ã¦„ó-'B„ à\Ë»èq¾vᆸГßÓ7äÃ’Ï.g=ÄõT«”TeƦj›MÞÝžPk"ÔL!ÍA†°ÄB1ˆp¥ƒ4´X8!±†ü#*Ê;Fކkš7aHgƒ1(̰®*ó¸¼Atx8 ±b‹Q!Ï”± ;x$<y£!’Ý{–$€„©0µ©D &·f"Éö¤Þ7"x‚ŸzýeΟr7³‡§ÍÍɲÂBÚ»¹ÚÉØº/]î—"~øFÎ]±7ÕîîõÔYž‹;7¨T8§¡Å (¨~¡=L&ž§!l'*¨†jlŲAƒ®ÆãBÍ«Lm“V‰T‚¨d)C´—`Q‹Ã¨I¹eïO–UÛ[¹n$Jÿ)·&D—•þGôÿ«íoi-™£F±¬oáÞ÷X^kÙÈi»£uÕýλ§•–ýŸÅq‡Ô*IòÚŒø"1®í»<ä¼ïïïŒ#*∂ôÞPjlyéÃ×4#*Ái¤™Àœ¿¯©¿ÒX|z^¦ª±Xˆ<¦Œÿ#Ç‘cÄ8ÞH-ÍzÂË¡sPýÄ688:šÆÚ ‚+VBGŠpŒ=«Ý[W'#*½´d<ÇÆlÿ¨»ü^$Ñìg†–#,å ©c|¨e{B†ç 'AÄaÄÓ-¡ÉÇR0ÞpŒIÂÐ,; Àr'ÚþÂ) µW©ìëˆÃðF†˜ÀÙ"Tþ’›r"hÈ<HÆf,@ϱå#/#Aïê²1»òðñÀÍÈš—‚A -Æ96·vÛ°\ü¤(ß íå*`ïWâb W`œð±€dÛ3ô^%·kfûdÈkK&÷ïãúoK#/«_–:·‘pèã!ÌßYa63>EÀÞMHé7ÀÄÖdòKò'KÁÊD¨®ÿ$]c°ÎÇ_F«›:2«ßV®1ûáƒYÒsž%ç¬XóÅä’:zß“¶O|²O=2Ý¿ yvJ8r‹T˜¤Ñìnµ¼›»ïºqÅ(tèç¦i髹…8gk0›wŒé˜I±Ää®»5mÝ#ìôu†NxG@]¶—ÖwÐcôVñ×6»_3…õ“Š;Š80¢8«Œ6ñzw~Þ‚ª÷räi¿qê3G·/5§³Ýž§¯PÄNƒ´7œižA0CYàÝ^.fæ@¬šæÃ'P ðþš¦ŠÛÝêö\ÔNÍî´ä\%™ÜYšXÐ:|° ’ºôÉ#,}<wgßÝÏÓÇ_"BíB÷)Gc;hhÃUÔèã»#/.GG²:ÖÃ{@#ÜåÓ¹[9¾Ø§{Ç™ŽŠ#,eA*&”Ìì§Z±aõ!ÁÖÞ‘ŽÃg a’›‚0¢¼Ög@˜i^a–Ô-ƒwníŒ>z›$ÈÉ-x¢@,8ÐCH\œ{YÀc‘<}½‘ïH¢ã£è,ós…&»ÂøÑ µ–)Ǹò´©Ê=|PuhžgAf.šHN±Ì¢uQ/e\ÍAëö¯GˆX“A5š8%€€=†À7B8x£Â99Ö-~Ú¼¾3Œç*‘p…*hÒS·U‚ˆ08úÃ%ï–¶ÃJT‘ƒ“w:Mz[®Ñ2¹r¯/σ’ööÛ’÷aˆö÷÷uÐ;Ù£ñNz1Cžá·“ð4º@ø`À¨ðvä\‹tlLˆæ;l ¬è[–ê…0í(*º]cÃ#2´6¢¦É¨:¿‚ª#±ä#/Oa¶)DÚoß™6–,rS¥²YÚ&ð¤vŒ»„SrÄ›ú¾;·“Q9I,3‹Ç…©´2Pe›{1MÚrâ,`z{L™æXì#E¥<½|«”Ù‚Î]ýЇ©fó³L6cÔÖ.rJ‚É#*`ŠJdVoå®ÅïXHcxUš¦–Þ©»K¦–TqI„…ˆÉ¨wNþ„`ú™9+[Õø5rÔm“ABòùºî‚;a0jCkޱ ¨$ˆqÔèÔMzIÅœŽrާöQMìëƒâ#,‡Ä‚ù4ÎËߢͷÜ|µÍ\îDÊÆJh5¤æÂTIÔ£¡é4£³”9a-:¹À€Lpçïš™‚Qí#/fbTÎdË™™™clƲ¬Ë3$•c¶gšç½[rüñÅ$PÙ«…äÖÖ©ÈdÁú¥Leq¼*èf&_>ºvÖnMœ#,À퀽Ä6O8<òËrLðié÷ˆ•»Û®ôxÒŒhlÔ„]{@mx¨>Ù>9z§geº8ÄT³:ð¸:O"Œf°&Áœ•ÅØÊ4ë«jI…"fB´ˆ miÇÎN¶W¨6Èé›°Ãü–p4ÉÓ”eÞD)vz‚öß®dÕÙÂX>P:|û%ÜbÁ@J¢„—T²Å¢¢"^%œ´˜]ûo1h+wn™|¶é{PÖ£ ‘´¸…›5;$·%ôæ“c[6û¾v˺Î!Ô9kOæZ¡TCQÔ˳¯§¬5“NIã1¦ŠPQ¸—¸Ýn“ý Ž“~ôTU£~…y‰ËR#*pª¦,Û#£öû(ÿyàÐzè#*òؤœo#,cS#,΂ÝüЍb2 Ó‡`jž)d#,HDrßÐ\!2h±O쨖‚¯‚H4må,dAváiO©ºÓS˜·|‹orbÌ<rúQÐݵG(tÕ˜wà:`s‰ÀMé,˜d!üV(Õ¶ËzÔ5ÖwØ:”„€Ž_‘“´¹ÔbΪ:5©5·KÜ#,ÚâÄ$%Áȉ¯]ªVØòË—"ËuÕÎØØjå§ð"è^O´¦0Z;69ê‰Þ¸â¼#,®†lÚѺ̪µBZ&žP“!Ø*Æ¶ÍÆÚ0m#,fiìÑŠP…œÿ³ùaž#*çÚÜD.…áÓM‡b\Ô uà™ IÍ“ïrØ1–/+ï(“©ÕT™B=Yì–c¤ÍAãÀânWˆ÷¢H‹BŒ2xœDœbGÁ.ÉsÉ0wO€ÍtJ(oäÝÆþQ¸HÈâqkkªL;$†6öEíF¸#,Y‚3EÒ"¿§¡C~DÒ‘ƒ¥’BgÂYÖ1F0¦Æ³ˆ¼<#*LYV õ7Õ3Þ¢ÝÈz`E*Od5lÃv±£Ñæ¸7]ÜM¹»É»Ñ„ ƒÐìc¡Ø5ÇH(Ô#,°a!S©,nRP÷ÙÛELu©¶ŒdS3 #*c$†' ÐTÕnS³àÂw2šT#*ÂkQÔ¸$Ic"9aMVÉŒÄdÅÙœæøfÐÑÙE׫݉iˆfš‚›…·;ýÈÁXC¬ÎˆÔ¼ÛŽÐ5Ñ ûWJwxÒ’½À´!ñ|‚Ügäp‰S²@‡û²`vˆ ‘,‚ŠEˆŒäÌ¢jÞ%ÐóœÇC!ÑŠÍî 3@<!±6â±:o̦ø}ïqë†[˜¬ƒmêvVö0ç¯È$Ödk)ll^¢#@“©÷x]¹Öñ#/x=R=H#KpaÏ9ؾò[q\ ¤Sç¹'¥ûîkƒ²ògÓQa²§ªž\ûyn¼7R¾\=û/(´x°HA$aç—€w‡ÇÒèlÍÍ0‚¡Ò7ÜÞ7ÒÄDš¢%:øÏÜÛ3ÊWí|:æñyË3d$yêh21à÷#,·bþQ@o $Ý,«$’À%¸n¨ G¬±¦¶0 °~îÓƒ¼€rgýý†vºÈÌ/N(¦‡×rý§¬ 4|™„ÝD´§oû(Êæ¬®é5â‡\\Ç;úiª,‰„pjnO×?•¹ëÏák¾Ð}ü;l—ZÄÏ0ý^†d`Pô®ûÓœ{䮿M5XßÔèPPKBnI;C³í|×5îßìü?í_äÒ‘ÓléÝö]†ÿ†YÎÇ€Þûü;󨡬 ô‹`¢ÄFÉEòû»¤´qþ8ßÒ3y™™gçGÙB°ƒÄÐ\`»¦éRä`vèy¨õíO8 #/QÈóãýÏ`ˆ{¢†¡OtAb¤,Ph§Þ|~/wDõópV:⟧ߋ/‡þ¸~o÷³þ_§TµùâÕ‘—el6i[ý_aÖ…Q‚Á'ÌTETBO#Ûê>Â#/ø#*è.¤J-™²J4í«ü¶Û:û;½xõP2}xuÙüì\Ž„öP³kþû—áÕüšRbÙVdªiGA!ŸÕ¡Œ`@9#,<6lŒKÉmÀilmA&+ßP}*ˆû>p€,‘B8¥Wd¡EQT°”]{0c¿·‘Ì’º \î„„”^±~iŠJ<¬©ûÌùä‹v©E2$HZÔ€¶@ÀÛH ZƒèOûÜì¾4tÙS.«ÄÑòÁYMtC[UDßÔx¡L)¤Q#/a3B·ùr¯ÌU-#,.S›sH81T”JB Õ ÈtWé‘é! „;çóD‰,:©X}S×.SA¤(±‚…ÁSZ;Tˆ(qPäf@>H‰ì¤9ŒA$‚ª@:‡Š°>|/À5’}h,Ó¿lm¦½wª+x’QkB1JvºÜfwV.ŠL>‡#,/o~õ½o40TH¢ÄH^Ó’T¬š¤Í’7(ÀÿƒtE²û;Îò•“•9|l~Ès6DFÛ#,¼$$êæn&Ú¡æN«R܉éŒ%ûXÑUÙæ£h„/H¤=F‡XK"?e>¸I›*|HTp€›ÉA ¸àjÞšï{Ä€„bùÁ¯ñ²Ê}»W€KhÀvçÖ#n|¹l{Z+ç €¯˜Ç©ã(Ä #*46ôÌž`ŒU}JÆÕËERÒY´©(£é!ÜG#/Ù#*þXŠ,Šˆ%EID#*„‘ElG"âP Ý YV*p2âüCž~I'ªÜí¾ÉSXDáõ=šÙK÷ÄQnA´£>àVVÚÐ<R±:Ô#,a¬TÒ0r"d&&"HG¨Æ§Ò4Í¿¦ÉW¦/è·.¤’-êîÞ=*¹^¦åêoìM£ˆ´ÆRFX+üö¥YƒÈÈ7 £Q€Æ „ˆo,”rJÀ´R„‚º”ÏéÏŒ 0jfÛM¦þŽúflƒ@› ×i~ ÙØªÀ ì‹’#,?¦RØ2Źž'ˆŠ¨+Àö>AÌžÌ/Çå?£'oÞW&ÚV’ç}TH÷²2ÈQÇÓñÎG±Ó§±_;Ñäg·õU±bÆ„cŠ0Y„o™ã˜b9_xغJŽ;Ÿ§¢ŸO]yxó^‚ûï‰àð[òCä•$…ó¹Y›cÿåÚZøO–ù«oúiì87Š™°MQ#*i*2€ Y]y#eµê°ÈÀ‰È‰Ÿ¿½6}7Ù$CGõ¯N»»ê‰Ò=ŸjÝê ëùÊ ÙTòjíiy鯰·¯f#,Ý“ÑBæKÚî.Ø"Êp!Ly×H’fC&ºn´p2AVb†4¶†›¨G{¡‚šRÉq¸L.¥ˆ‚D2ì°vŽþ-ÁëÃÇ+U‡å1rÝ‚œ«²hþÿ¦n㿇¼¥Ên#,"BiÇ£Îm·R{ÃÆ'¼,6ìãrG˜ï«UX.qÅï’â‹À.u“¯}¤„³Ëµµ‡èÝ>DXD‘DT>!ëÐ÷ÉßáL‘`¿×D˜aüžž`„óåÕTÓ&Ìíÿ‰'D’³t},ÃÏ#,GŸšç¦K%Y!·ñƒQš6ÎË÷nø›c–P[3ÐçwLU:> ÒÌ?™$Ÿ§çÞ EÕ5MWgÐ:÷§QâÑE£¬ØžšMT½|ç™ÈQê€H‚4#,j¯ºB#¸Ùš…#H‘ôóG™#”’¾%'Dl\ªV©i…E™\juód'mcÅS؉Çî’¢6ÄØ3ï¿gà³’¦ºbYϸÕsâ#Ãdžœ+@ðÓãî;c%U:º¯ËGNeç»Îi;v5¡û*÷¡B@K𠪀yv-)Q_ˇ»ˆFšÆÚ¶ÉZ²A³V4“eTdÚ+--«J¤´ÚÅiš¬Œ@„c#*K#*ZEª1€ ÒqI8ÏœåoªTœáÃh‰ä‡ ŠDóĨ"Œ‚½6· l#*À Žaïl‰J‡ÍþÔ×ÄÜöxÙ»hƒ\ØhŸÃ.d(`<46:â¨æ¢#,Bí80bÉ‹ e<AàU–E.mˆ …`æÁIN™&™×+ò„¼«ž»Ñ`‰DC7 l“C%hâ¡+-–š?®ævÈÈ¥m6¡‘0°@WЬnÃ#*LH¹-*òè{ÖêÁU:â¨#$Š2#*Š©³j¥*– $€»Q^^|Ô3ÚÃ|¹JŨ¢!líiÄÝqL™–7@€Éˆ”ŒÊ„#,ˆ’ M¾7‡·¤SÙä=™DÙ*F#*¡UJoU6oãL@T HÏ€…xãZDá #*‘‰$YG~jæ±mŠÕ͹ͮi•#/h¦h¶f#,EI(ÓH °Y÷æ~Sɬvl©xtÌÔ¡¹xÂ@#*!‘rNõ6 s¾¾/Ÿpý÷¾ïQøü1nTj°†p´no–ÐÍÅÂ&ïš+™õÈ<#/óâv©Ýv¥PÔ÷ÄÖà2¤8Z|d=§åîü¿—íþ/¿Çüݰ٫YdPò‰#å8eD «æb#*YÝê³Á/#/„bª*¤0ÀÝém¼ß›áÚÙeüÑl¨WL×#*Ù*,a=UTšŸS•áÇ3Ìððî³I7@ÔèÒ…à&ÉÿT]yÒåô“á¼}Ùk̨#/Ÿ[?®´:«C®™Ñ_¤#,³–m|[l½ZÈe1Fø¤:ˆ[û)9ôNÝçó¯*?U»`B&Œ@„ÃM(…E÷úÎC#/AéãŽíÙ‚xÉÒÛ¨…:Aû% J©ÀÛàÿFOiھ͡±Q›Áÿ<Ü.W x)™#,ýæÚGlØ(,ƒp±Àj!E10šÒíŒ&þ—¡:YÓõÑÚWfìÉ,.ÈôÌÐ!Ò3šƒWAÏnvÙwì΃(h¹AìÂ5«ÅÔõL»Û½ü°9!Ðéõºµ88¾ºÅ¶–QW(•;%ç\×®¸ë|>YL’ª„šÒlŸ¥²‚dJ-ŸššÄCòuV¡ç¢:Í!¦~¿KK§Òq Ó™ÕpÖmÔ û6ù‹ÑŒ¹ÿUÍ£zÔ_ð «³¯¨ yr6ê]˜-Ëí¶ôƒ‹³§T)DÝ«™i\2™õAÄ¥Ä9¼xQ†_Âñd¶pcú¦!öó·ŠÐÉÜ&ήðÛ˜²¨q«œ9k%–0ªq¯ö3{ÙÇ<oZ\ˆ(Ñ`È#/¶žHêÊâ㙈Åh]ïv“°CÌ@ ÁU=m&«R¡ë0y¨ñPM†ãÓàü8nØ0Æ”´8iÄåYŠíþæ¢Ò$!gùÏèïĨA«)¢¨¨4£QX>Ô³ïèyßÌI±ömÝÚîR‹ÖéQBôzSDp"¦jQXž¬Ð'WRyºûúöw&jiŒÅëy¿|ƒŽ°$*pGäÑLXÜ’“ÕÒÀ€FR#²AÐÏÐñâUWMeèáUÔXXXiœèèrø|Wû&œ(˯@¹F1¬ýzÎÆòäjzÜ#,(éZNÅM#™5ì}‡G[ï×^Ëà¸bæ 0á±Î·8Ä@m‹xh¿å½Cí‹Ã2†!ÄX‡’Øð¸.¬±_A`eíÇ+î€#%KMà‚å.L4ü7ÇG"cB’}E®‘hP¡Ú_¥×æ,4°tLM‘“Bœ«®r YÅcWhmbðI@#/ÔFùx$ã“äqÑ0ÜÁâµÑäôuå[qÓµv\ôòæ#¶¹åpçqF;jÌt,ß0ëf¡·U˜U)°.iœíÃí®:G!;í<ÖU6ø3CÑÑr£Ãaºt¾¢ëÛž>ʉl7<Ï2AËE’r –ô¨FNL^ç[:òk;PhÕÃg#,óØ+ÙÜìØÁ»ôű©·|ûE©ÚŒLÐ(+«vP鱆<{¯ÊßÚà•^«š Gƈ£p9#/äæfÓ3‹èN·QälÊÄ0(õ4|¾XœØué¼ûqÀb쇈6âõ`»XAÏ+†ÞêÚn×ÝÑs>ÜÄßÞÓœÝãEwoz‰åê}0ý§Èúy%Oçtêp#*„¾”F}"(ReÕõÞ/´?BYžP;K².…‘áR±ÒW~;Ô»'˜=…ùxÍZ¸ ZÖLê>¸té“#%ƒØº<#fH<HE^ŒwqžpÁ‹lýpCó‚§-•ólÿ™ffÓn„ߨ”ZÏÔ#Höág3×-ªƒP‚€‘Ýˈæ5ãt=¡ªætì>šÌª#*Û¯CY½³ÆâöŽéÃN6±Þ÷í0˜7Är¹¬…Ð6m ¯©“µ¹5ÊèqÙÆ½<#,®ò›\í¡Ñ&ÌyøÜ”&7sžÊ[÷9èy”*²ƒ&ç%:ò"ÕT©b‚DÀqÞqè}›õä0ÅÜ73¢¡!ëµuH°ˆŒvi¢²YTÝPžêÆ'¿ß¹Q芔zøorg" †&=ÆA@šž9Ð#,Ÿuõ¬BìS"cŒ`«Ã‡¼–€G)”qÛ·û8+fºÁçêÇ©·ÁÅœȢY#/8<»Uä•Ѥ! ”GuÜ0]ÍÖ7Rv‰=ŸöÉ$‹âÎìR,÷¢¥„:¤:ÔѼÔÔ¹ù÷ùÄ¿~¦¡´Ç4ä®k©}9büš\‹yÅsã¯FU`ÂâÀ›#,‡@þOVÍ¢·«§ZóÛP ¾!ÓNŸfMumP9èMiÈ;dí¥j Ð:Òs”D/$Ž»%‹U-4+UÕ\Æ–F†l•®—6@wWRénä\–5 ƒ"øÚëÖ©!PdaÚ#/á`¨ÈX«$ˆ!¡J"(!¥ÜïÝbØÐ´–ÅA*;>=¶V4Q#*HA"°À:7Q×Áµ$hjkÌ3j”¤Ö´TáÃptçÇó¯VÂÃçÎÐÖgÑ‹Óæ#/_Ÿ”ùó÷“Z6§f={“î<”JTAðõZ©€m%Êé`dÚévKê!êa '¾ÇD3ÛB#/ "$…àêP:aUï·d^3ó•GÆŸkÖ™»•ÖŒ’?‰s7ÂA…öQ2"ftÀLO'P¸ÓYF?ФƒÃÂR»@s[)ŒpT5›B°+)#/gvàbXk#/ e3,5ÑóW©)³n7^ÑVšÛ±<t€Íû#,a2@ût¬°* ¤6•#Q-Ƴ{@ªÇK´öi¦®[O-¢w¡æ„ú`éòü;ô-ïq"·§†xnëFµÍpœ‚ˆ€¢"T¥°…T)vÖí‚¢ˆYb%,@ #R"–K>fí'5mŠf©à,Ãé@6xÌC𧻂&y#/6â‹ ))¡$B#/C\Cè&QBN¿&ô#,Q]Ÿ§G_„æ¼pÉ!1ßÄ:ó®Õ…´ ³æÓûþ†ÄE56Æç]7€dÁå†àtŒö>ËѰҧ‘_ƒ™¯%¹2ÒÓ-5ŒmµÌÚªªPcÔLÂLÉ“#*ÕÔ¦„ã›<¿èÖG5âÐÏ)ÖîNÉØËióổµ[Q˜Ò¡æÃK@¦€PH;˜Ó|Ú킞#,I™].½Õ!„–²r6I¡¬@DPE=í¨Z3䄪£EýÜܽ‰âü¢OU¹›!¶¨õ>ÞÇ£.eW˜#,ý&ù*M§÷¹²ƒàÏííáöã¡ÁÑ7±b,(mÛEŒuÆ™òפg/ÎXíñU’5äÍ•N›ôàN}EQ(æQ8dã· ‡¿ŒÔæ“ä4&š;!d2¨êF¼»s€ <ÕÌŒ'¯™À|lêœÃ<}—½¯ ´݅$¨R3¬mFõØëyêúM¶ðŠáÌåܹÂ8)ʦÜ$fœÆá¤RX‚àœ´ßš¨Ç÷ó«aÛI0cüºç°Å¬e'_“ƒ)&ÛÜ[®l#/̉k—dZÜ4›¨lñÆ…$$ Í#,†¼jU#,$CëÒ2¤a2u!ó ŽPàˆ<‡³P5¡B^jÓ¡.rð¨#/,2<²Dâÿ'7»+Ø|8ÃãDAfx!¨ ]gr¼‡2Ê=@+ E×ÒVb ë‚¶òÕ×Õºï1Ù•œ6×_µè#/#©€V¡äàliƒ"a¡BÒ¹èEÜK».BqÂn]ÙPÜ0ª„¾¤ƒÆÒòi±"›Ð`” 6Æ1°"wœµ¥s…X#,,[©MD2–çVß+«¶Þz¢‹(ÜaK©K;î·dy'9s_f/ËåÔ‰÷{jóÕ’6‹lJS>,’î1YÒq°§tµR}à¶;Ã^Þ,õ[èh"‡³l)(‘›oJ…A-¥9>“H®–0›€ý–üðdG‹'‚cw>SêÅ>óÕ 4&IƒV|wu@#ÜÜýD—Ð’ÉZhAòæ¦W7qÙ™¸ù9&ð${`î±®Ì-"K\d6s>7rÉ.0åYB¹Sá#/ÝEÆ‘ÒêÒÛ<8"Ÿw¿M>ßd'Ì“I=Þ‰¹Ë¼ýÉ0Ó¤\öוýÝ„`Š4åÔØ•!ËrÇôu³Ò'Y;x‡#/0ZMŠ("•TŠ0dÛìð?ˆÈ¬‹"1€š—¤‰¡R#[§»c¾þÝÉ›¿Qöb_´Î.Þs}íý\Lmç»ætì¾gžªŠI>J‰žo#eBdˆ3àŠN³}^דÑfÊc˜>½MÿÜ~Ö¥SB˜N¶Pˆªim¾¶ôx×_¼¯ÎØÕLþ6D¢R6Ú,dEº”Ɔaßæ³8-šèL¤VbÄQE0’”£!B2]ƒÂÕÒffN~–x”+%$Š$ÿ:%è¾3ì¶00\ bšäˆÅ‰<ƒ¥Ï¤äd@„Ë¥«RVuk@ô¦ëô4÷+a¤¬»›Ð&jƒ¼Y~Î Áõ¤¨ŒU¤gBB6Æ‹ðúhÃ#*ˆžV˜ÿD{ˆi‰o&¢‡d<4T#–V‡†RŽñ#/MP“ÄÌÀ R½<¥UMÅCch,#Ô£dëÎN3k(lÔ•ÇZ¦€ò1ï”Æ¯éˆQ‡#F#ì…8m&ë•öGka¶²Ž=xÉ#X°3ç‚Ë“Æ<Ù´Sr$ª£¡QìsFƒ…Œ_&ýŸÉ<ØÖ„FÏ|Hšì›ÅåÖ´|þv%ŒÎ ê˜kSZÏ8›h ±“]-0-f“KbŠhÓ‘Ü05‰‘ŠJÖ?f“Ó4`KXR*B4Ô±ÐüÞ4l}5ÅQœ0°>×é êÖØxfk#/QÁ5éÔ´Ôj‡±y2·BFN´'HmcæÈÔ„ôçyÚõ4©¬±²ÀÆ7#,¹Èg:üÓE=‘F,憬ÂSGK*Ó¡gQ‰#€ÛìѹÃÞPFÊuªF¥þgˆæ«z«Bw;9)Ùlœ—X½áä•^®Uwn…1áÔÄÓª—§×Š#/.0°Ñ¯ùùŽkðn7Ôºö¸¥J‰.<¹9t‚¢âN×Ñ«Û&5¾×£Œ.ðÎÈçq!*w~ŒÄXÚ£cü°tá‚;ïÏPËY»YÈ¥¢› ½ÕõM«åkz·Kî¹.jke$ !‡R¹ÃWÊÒ˜7Ñ—%tnŽKQ^#/(4”¾ ÃFÎ…øüBh±F…¶ŽÐ¼èÅMõ§ &‰–SBRkFæƒ)&¢S#,ØhÁ‚\#,#–#,.]ËÞ,Äû0‡wIàãm.[¼Rs:èÎå™+IÁ‘’)Pv0ËC"É,Í%T´7CGƒD&Œˆ*ÃCvØttˆGOÚoósË|C;Ÿ(¾qºº•&g•(uÓX‚’Ë‘{ê,ÔcR1»˜½Þ®#/‰ÓB—´|‘¶z‘¸Ã¯~|6¶3§d^µÏèB©Á<#/ÀˆsEÉ$¥ÖN8r(‰TÁ($6Ca79 @Õz6—þŒ`]Žvlç#,zSÂÊR“H,)¾8óå’ƒ‘Ü[€`±ÎÒ8%B¢4D:b޲!"ï26øxî6…Ù”KÆñ9³ÓYè&Ókhca7™–Îowc•!ÕÀoõ_‚Çch™ÖÖ–jÖnkæã]›ÖvQv%#§=°k|9ñiËÃ0PQDÑ6ò¶@”Hû›kåTm˜A+⪬ÁDÛôÙ±>¢#/B-Ìkó–Ü\°[>}ñ—9¸ck‡Œ½IÍh×7füß}©aÍ-ë„Ø–û‚!†™m‘€ëñlÎww(1T£G7¶LTañ%˜B8_ˆS¼;ÍÙnÈþê&/¦D¿y¿N“,ìvt#, 6€)ÅŽÓg»Ë¨zÂ{w8œ0Âây¢,EFÌìzD´ ¨¹[%ð°IŒû½Ô±X[ØÜ@ ŽmÍm¬Ü•¦ ¹1£¦I#˜„jšÐ„P¡SÏ¥FŸBüuJšD€c<sM†Îœ(#,b Û1T‚4ÙÄ2 BôK6>5¥Ã4L#/¹Å#,ûøk#*8J/pŒà¡¿^€!ƒð°ÛðouDƒkÐ~ÿÁªf¯!wJ¾ß«_6gæ÷Dü”Œè€š3jÙžÚ×ßj¥ï›Œk‡d?Š76MÚ—ÂheñkµXÑ€,Ãuøª‡9#sÙQ¼_Àäe¢™™zv™t‘~)s@ÊSƒ¤ÉfeÅebÛÎnüÝÏÝg‹#* H¢-ÎÙ×` ¾™ç§©ùÀ„!(Tկ̹âÛ¢j5j6×E·+m±µkF«úëm¼kolkUg]iu»[龟#,xyÜOE¨ˆ†^-bˆÛ»*1#/‡šàì¾Ð[YvPø ?aóï<ƒsÂÂ÷¿dûñºm«~XÌD#ˆ%)2S1š¥,Ì•”¦˜¤Ú¤ËIúÝIL6´„ Љ¥L›4DÀ¢Úh×ÓÛ˜d©1d”JR¶hS&&i™)Ti‰¥Kèî #bÈÐ ¦4’’Ë#,PLš*©QE"˜EcÉZQ²ØÙ L’ Ó)°e*3Y ¦VLÙ‘½ïwÕ_ZsÕÊžD9^YSzó)eB 29˜Ù¦a7åciŠê]¢^Mßfcú÷_gôë+Hqågž¬›f*\ˆÇÀä¶&°²ÀKJŽÝÖMN³†MàºÏ¿pS(hÆô–à3µ.ÁGVg>£XvoFïCEF£?-–LOSŽ!ð…ËŠH8#*>M‚™—m3³F}‰e»Z™ïŸàN™Áž¶’§§ësdRÄáÇ7“úDäcÓæö¤œ¨°ZÝK^î;$Òm°ÆR·#U²8†¹#/u.\€ƒ‘¥ƒ®,„$dFÚ#,#R²kˆÙ•™F(ªŠ"$Og{:×|Áà&&fh¿eRã&DW)¾SOÁ¦²4í-ÔM&/–™_<Ò³ä;Z>ÓZG¬©‹S%™”IÈá¿§-M?Uu;rö;W¡éù‰íi•#]9ì( #/FXL Evì<ÝIóÚ¿ZCªxçmG")’êAÉ#/—ØÆ‹Á>!µC—Áx_âýPÑ7&š'LpKrÅ%Œˆ»r>-õ¢÷rºÁŒøI*U‡Y¤Hb Ø#*›#<äÒ3äÇêñýx=™‡ÔþßµÖúýÖ>k§¬ÙÖ!Œ¼~ª«Ï‚"b8(ܶâ°hÜž$°™húz댜yÞϯ^®%;ýoüÁ¦ƒ³M›1i¥¥ð‹MašƒÆaG–e´Ûµ8ØÌ{ÙÙ¬j߬÷Å<OºvÉ‹îmNʽIe©ídÚ›»®Xã;o°‡V9CV’@¶ö’,7ÕÆé‡m ‹ “ic³4X¸=·œëo·æüàÚ÷l9Á‹PK¢ÊÒwO/¨íã²ùÌiË~ÄOÊ'zt‡ÖΔÅCØ·6iàOy¥o¯4º´#,²max5É5„Ûa? ¡,;b“—O¹ìóªrÞR,½¸ì{ <óá&‘Z)í õ`¯nu="ès|nÚ<Í0!@Œ‹õ#,3Оd]“XšÎNÜUE*7•ûîŒå8#/Þ.ô&%óØÔ½á–ÚH›Qð|Äü°*~÷®j²û:5êž»ü»<y#*r6RE·|IÔU¾N¡=µÛÚo®»W¨°Z>!8}Ÿ]q½ÿQÑi:R$àô¨Ö{|³Ðéva±µ°}”g²_1°]w¢^Uh‡KQÉæª€Ä”ñDö€"©rPoÛ¥9ï;ÐÕøž3rÕçMkgœ¨à<¼½Øù0܉:„§ðÒ¡lÂS¤x†!¸ãuì.£u#,áÏ—LU5Tn)ýü±ÚKBð$EMnÜP–tÓZfDÔi𓬓”:2z߇Ä}´›s%×i^ý:"ºŸ¸H@" œ 8•ÁRµi¥#mÿ¥/Ñßc¿®ÆC×éúÏ5Q‡ÛU¿ÁîJºŒÜ+)@<ŸcDtj1GjF8ÞV\ÌÙ1¶dÕD¡•ÂŒk:7¹¬Àm?^31o+ŸllÃnj7Nf>f˜óP×ì„©wwH´úyU.B4"b^ÓÂo,¶c'–R<8s1Ú²io5¬DâdZ.Œ7™3#9Öý™&ð¦ÕÕ“Pçkoœv»²pòweÌ"Ò–ñ?ƒ5£ rq†]50Îlcªtî)º\,@øuCTI¬3>š÷ºD䂉™¨ÔÓ‹IíTbæe –•Df]¨²”& M) ¹$\]Åqˆ”h\^'jk["§acqó§Gìt!åî^ÔšˆÂÑ’ï5½çkÚÍrvìb€èù0BŒâAm‰'bŽ´‘çS ?ƒGjÉž¹¹®œ'—#vØFŽ®ì$!qvaIËÌ&*_3Z8†%_WhmŸ\Ø8©!píµøó€AÇHz7hFág^®±§7Q$i‘Ýé‚uŒ.†ìÀPQú³£Wt«Xd-%ðø440iÕ⩤vFæÆöщ“¶61d>ˆu¡õ#,9*>xï¼Ý¬.eó¿Yáñ¸!9Îvånª¹Œm¨€x¥Õ3Ú~™ŠLi34'ÃMFÅ,îåã„Ë¥®Nx̵â¥ÿ7nb`c@¢~Žù‚“"¢¥àÄ;P›e“e)Ô£38j¥Š ÉQ„&ÂMþ+ϺƒÓþQ¿dbõÆ x‹@ìIÑEç*4˦öaè‰Z»ÆøÖ+y3cs7ÕõSÆûÙØzJHÚœD«±‘vÎÑñ¨]Ýw¿pûôà<ssížç[Ä‹§C}n&9=Û‚ˆOßé'Iñ¡)0±Ã™ãU9ßÈ>q¶pI";ôÚõ[ß5ÉÙ¶´oJf…ľ÷U-|'—Šß/sKtyƽޡ*³’tûÛss9ØlíŒÞÕ(O˜‰åTîžöj‰+#/J….¢“‚\<…ƙՑÖóa#/Áæ7#,w2f£å6“H„#©ÕH3 ðÖÑ·Ù¦l4Aô$ÎÍ3¬Ì09¤1Mª† DÐÈ%q’d‚=ùhˆÎZ]0Áqˆ(2§ì,H¬ º5 јXûé¨"#/—0õII:mÕËø¬ªr`iYݾq![jâ*És-ŽbbT>Îåí#,©‰4€HB,ÊÁsY#c`¨Q¿&NëCÄòaDEº‘òí¦—«¹ª`˜Z¨R¦\Á`NÁÔ¶˜Ø`8CA“wÙI®èy¢JMÄÁ[=`ëD„U2dÜñ+}UlòXéÉ4Iª+Fž7…³¸ŒrûFËtÅ.#,ºÁkKGMéÉcrS^¸Ñ½ÙÓ,™©ÀÄ$lj¦7v„4hIt:h@„4Þ”§ëáš#,æíD•¢-‘f™uÙDÚݯÉÁ-ë!ã*}mßÝ3žÐïf›;Vï8"ógX=é&2ô™á‡&YZ몸Ò+=>UˆVÑy"žv᧬9Y|¸mºbL U±AÐÔz\];æY¡š‰rï)²¦EW<&zár99‹T-JO5Ì,Ì΀ᅫg+m‡lm±xåÄ+æV0êè¶"¸ $3‡ÕÝÞþø¢ñ…t(‚1qM&]9ûÙ.2Ýó™tjFÛpó Ü#5&©_èãFäÙò¾'cdÌ}Ã|GÃXܳK#,c×)Î-tû7+ºÍ7׃{ÈÍãngWZÌ8°¸Mäë&Èûa0êÞ¤ÄÕ2†LÉLïOKTøÃÂB ‡j×OS¢¤…k¤‰O.a0æ7¦²‹‡µ2RTócºÖn1¾vvGC7Û3Nl̬Õo#/Þ˜Ìeô´¬ÜÕ#ϯ5X)xùçŠÍãJaCœËõ&‹s¥DÍEÕU<„Ò¨x“QâËñÃÖÀ¨®"6H<Ö凌ÁP_wã‘o„kŒy+m¹ Új8Êàmù<k$#,&¨3 9¶jÉ«ˆÉYÄ#ÆàܺÔÏašÐcÁÌLšÜ£G57V䇧‡á&¨6«zešÌÌÔèi$ÞknmÖfMÛ53—N½Fcelvj˜1<“’‰ÓD¹§MuÖrÈÛ2rÄW^ßU4öÐØ°×¾ÊY7la;5ÛFr³«U>ú¥á°ÙmdëÞ gÃ’5l÷(³² “äRš¹ÃR˜©D¦ÈmÁíñ®Ú9ZãE2ò@ÓŽN7#/ÆÂ1Ã8²˜pr9àâÕÄ#,ªÁû‰Ç8Q£˜!9…Itw‹Rö06"K@J#/hØ”R«’–4ùi#/d†E tÀlV(yaW›I’âIÂolfjWÞÔ±ªÑIÑT3|óÅ$ºhÉ*БåpV1ЇM‹-UM0ö憆IjË£ODÓj8*ÖÓÙŒ*ížüB£o]s)ÊHìø#/ƒÀ–—¾¨ÕJ’-ž-GTlM»Lõò¹–Ó[¬P¥FÒR•)%kcezÎ,³ m¾Î˜BmÎf7-aa–629'È!¢ÆÙ3-àðàlë#*G†4aäÅRí»èÒ45´=‘t¦ç¡Asɲ‘QŒbõ0„æ(àÑÇàPCvwꎛWg1ÕDžíÊH¢$P8ïuCÁ’ën…i+åØŽ#:1oqGÓ™–d±3š†ÉXñÎ!i4`[d#,zU;0ʡɅ<i«Hî Ñ›³€#h¹CBh˜ƒÆŠ\‰Q†”¢ÔxU)DÏehÌàIB…ˆæ‚ÝÃz4‘´0!l&î®™©²Jd0±Pxë{³’KH¶8iStÕâÍdI«'6mƧÂI«-‹–M2ÀÑÍÂ?²m&©&÷ÌtG;ùt£[;Ö#¿N$Ò›v¥)G4)yY£’‘¹—&mÐ$#8¡¾E×|`]ê¢YZ—*HnbÁ4ÔgG§!é™rðõÀWH ö0ƒÒÙ‰¶P”½8yÆÙÏ#,Ý.œ<nÕ“´:œ¡á÷]çn…¶‡Ö#hå6Ü-#LÜmWœlÌkJ7sÎËt9¹Á96R³dg4C#8µJ.ô£cèrtÅÕk“™1^%ë§Á”ɵFq[I³‘Æ5“#,—áq×k“L1c€D‚ª/)¡#,³µ °"Ü1±ˆÞÕÎk/)‰Ã¡Þ¶xœwÆ4Êý™0ÄÎ\b‚fwvq5¢ÁT<§µw¾cÖ‡&ù8MÜ®7æ2áÊ¡Õà7:´Á’ÌÈMN¢iŽ^F!7xÀ[Ù6B˜&ÃLŒÁV€Á ,¸`£Œb±#[x¼£‹b óhMw;ÃŒj>º³©Ð§tª6vˆð2e‘Œmµ$`1³„»÷¼~Zæ¹luã¬kÖmד‰þ•HÆwu»PÐ1ìu ¬`³ÞB8±œ|>[À #**vBú†ŽLðÚƒò1TmÀ‡Cu.)lÀrš÷¥YK 0q3$1¹2I¨¦{œÉ `Ê-Ó|¬'°ÕÀ*”DAÎQ`jÄHÌÊÊÑc7nܘ€ßvä†0˜Ê4:b8Bc‚8Aª£¢#~§$(AÝ4f@M¦óc¥ßVqAE&HÁs2ÒFîæ“.S8Éq›Ã\¡#,ÆDLºÅ1Ñ‹ FÃ9²4SlÁdÏ”¨*S»Ž$¶4@5eöJ‡ee°;8nÒ`m«‚èkCfBdê`ÉÉ…ÓRR:#*k¶R9kcŒ%Á†,Õäw€·jI0–ÔV¶pv6L©ii$t4ð¡RU`s†ÕàØÖ“¤¸àM*‚#*d!ÆK-¦fÖ¯â›Iº«;ê»_âI„TMDÔgxîÖPŽQCÉ)D`"5þ³/ÕÀ=¼Ü!Æ-¨ß*ü¿—l»\#,cws;¹$ òª7Ÿ1þ Ì`“šŠ±AÄÞÌtn‘OáGœm„Ò•]B‰p*,Uc"!œd#*È#*Ê»“#/<à´÷e¼Áø×¼ÒÀi°Qc‘ÚÄŸ:9§m[«L>YÍ”}â[#Ÿ/<àý3²ÛI:Bv^æ^[LæàÖe)šÑÆ2ný…´‚È´¥Xs5§×Kn)V«¾ÑÏ-áG9´àÙ³X`ø:Õo× Hø¼ÌÃÉ&âm›ÔÆû@äŵÂQ[Ès´74á„d`ež6œBûÎAÃ6NYe¬ðÆB°ì.Ý>):z`Ñâr*;Ÿãl.ŠKBˆ“´èŽ'aŠDB$‚PGp<öñ¸m“nKDU3n“§7‰åÎëŽï<®]–·ØÅ™m¬šõW.®›^*Õtª\ÐP(l¬‹!œ<`›,7TAø¯žhP;„ÎË«“ãÁ"f&A¹éÔÆÆ>µ¥QØNÇ´ÍÁ hÃfÝog³W€)šâÑ×1ÓïÉzÕ~A#*6ûöƒHz`Tí¨PUWwmÙn»³.nºn¨5sdõÂÈBÇÞÕ0‘Hí5]ôè/±æK*¥ì:ûHî”Çj¨ð#*w¨p‰ú0 !ÍgÌâ‡>•ö^p9î‡2V¤LŒàŠ{Om~µwi ú¬j?¤È»øŸæ3 ír~¦Â‡³Ïöûý§¨áÇp]¤/»ÝÃna®Z¯@Ú´E²Ò¤©W“r©/;u»ÓÏ(ͤˆÞ'Ð72à\ß(cÜ6Í”‰§4˜ìF#/i‰@ŽGÁW#,‚F«QeFŒ'1D%Á‚Ö¶ÄDaåû‡Ÿ‡8°ë#/DJ†±¥{ÈÄ3#*þ$à~ÿ¼,¢ÞD„,{«’ö Äù>?«µøÕjm )5±llZ-hµ“ˆ”6ŒÓ2Ѩ*5±c^5ñ«\ÕÕñ@ xTOzïõðÕZ€{@ï" –ëSnÛõw&A’ð.޳¶›#,]¢…EFšX?‹wB"k\" ÄnŠ˜I$ªºj5Êçekã¦íî¶Ü²öZÙÓYnIâë2;’T9'yAŒ^øb»ŸÙNC£ô?L"[sŽK»¬6®ŠSѺàð{h´™ÍõÚÀv G²hÐm°½X¨Ñ쵈˅†òOb‚ug¨i/B`ÙÜòç•Y…µÖG‘¸A¬˜+¸Hó¤}L=§#/°ÒÇb¥ªšƒ1HÉP¼*DT[ƃcb˜*ÒWdÆÌ¥,€ØAŒ…°¤–ɪc%4ªAI”G=Æe"fÆ83ŠîPEbæ÷Â$x,»)áU$‘VµRYFÚLWí¥½ûæ4oQóÇ’vîɘznøÕ`µxãZ_VhÜ$Í11T1¶4>;të‹‘Hdƒ’#‡R—#ÖˆVºR6‘Ôf2†™Ö¡CÛµu@ɽaÊCdœ5*NŒ–$þ„Üa¢ã6tqPƵ5Ô1˜qÈ"Â#*°&r‚ì‰dÈdŒÕ•çF-—ãæäÉ<aÚ1žžâ¦#/1I"ˆ–À«(—AAt¦àÜl}ªK®¡J~$BÖTK6hBðøYvÄ#*ÍU ž”2kþI˜2†>®ðž±^¤™_:1zgU#,j–a²ïòÆX¬e?-*²˜ƒ[èêäaæöpVÑL‹»#/3‡®¹3ð)M9 LRâá:ΧGÚr.C¯8ØŽùðĦ°)wQhÔFŠ¡Ý©7¨6#,a§-»"øZZVÖj(-„Wù7 't9`vhU#/‰¶i!KábÇgØÌ>&ƒS2B¬Hb‰P¬IClor˜ÃÄÖH8 ¤áÈÌæCÃà\D:}÷Á„[øA”Ѥáš`ý]lŒå$Ç#·c¥ìç1¹ÃäÆe²g3Œ,$B>•‰®´ÒðA»Ò²œ-¹x[IH¦SR.†B6¡ÑÍeÁeÚ¸Mæ›%¨è׊.1#J ÏGx¸‡kÈDÔëy¤YÆYÚ·¦4!ìÄ1›#/#/ÄÃõa0Š0Ù Yc¦Œ£vêìa˜h$0Žˆ¥–‘â7B…0ªHC"€…У*#,Ì#*»qY5oX…ˆAVT¹uÈv foàä³6掱MmLÔH¹Küa#*#/ #¸#,›‚ÀcÐuá¨|/z¿æW)§Š,OeðVéDÁ¯Ì0õU€³sÈŸ³:𣥰†k†;úmkC§ótP,LBˆ”z¨¯W†5k±v*Ò^ŽIÁñSA…J%UTj¥1#¼µã_Ò[AmFÆÔZÉ´jÖ-¶T–ÛWíZ–š"ô=êf‡ÑC3ͪòT¬yë°XÓÆ/O®i+]Ãî'}‰ÅÓ£JïDVÎñöóU祔¡¾ýⲿ¼¤Ö#/Ü[AÙ[Äu9V’W"†É½õÓ†³¼J6S=£K#/æaÈ}'Râ–[jS®V›i80Ù&èfVø»–½”£UÒ–1›6m.tìÃI€¶‹¶Uxšpȸx©Š‚6ð’Âæo$Ã8Áá‘å2=Idæn!ÕøšïQŠÊÆÛÞ¯’7•Šiȉ3Ìð͙ۜTÉ•«-&ºÄc¼ç›h4MÊ4m®b˜ßSœn© óǬÓGŒ¬MW>:Íœ;ŽÆ¸DAÇqIÜàOy!ÈO ζñV›”äcP^åP…ª¤Æ&êÙ¦#*ë[t–ÖÅD6Îkj‡©§ÞæTîí©BÉ-2u‡B·Ã¡Ú2ÌìúŒÊÍbp§k’LßVw½xf;œNÕo‹L’jV 2ºT¡6ŽE¤"K´6¬’l±äw$ùT=ÐûS##,“bË#,C˜`¿c?›9L“¢g…n±Q„dMJm/°BùV’Ô]XÖ5µÙTª[›vS-©¤¤hÔ>{}·–•e-0±‘V£#Ga6#,oª&‡d˜X%‚aÀ`@’‹¡Aa‹ÒH,²$BH’@‹"¶5œÆá@J!0`É&J6FÙ-éUÕT¿¹2Øø(=H@‰ŒbµcRAmMwh»-Ò£bîêô“žR²·dŒ‘¸AvAÑÙUmN]zÏ:ínóM5ãn†®Ö[˜ÜÝ“zeÝëºÅwk™›NÓÍ×y•y‘¹¹![©[“Ï+26LBE$HÀ#fSýÚd¤HáÂ4ShÙ¨@ÂÔŸ8‚Ü‚HÀ€“6Ì¥(›+bÖl™JYy]k¥¬RÓ&´°Í›mO»¯§oŸ¯FZ-P`±©‰E&ÕEj„¨¶ÀHŠÂ-ìôyÊÑÉ:u(üãs^ F¸—öëb¨ÖÎA2=AT–ƒÀâÙ`E$ nÄ¢%ŠpTjw#,#*p‚ùâ;Ò!é;ÏeƒÕž'œ„aq×§ï0 aÛòã!u4#,#,}Æß¯4OŠ&(w#/ÁvÙÜHHQ#/áTÙ„Òfg/!Ň~zfa@ÎV±nЉFßÒžƒ’‹‚&Ze³$:ÞxÔíÁÔ=z“aŠTâŸkøYP:˜·½*UPI*#,”ˆUýè€+M‚*Ì #/Œ¬H#Iuêw„íØš˜éÜ‚á¤ÚkICú¹9ñÒ—öð¹S•O͆úZ·Ù&é†ï†øýNc#Å›aR•lZÔÊf>0;Ñ Q5z:É $@¹´†îý_¹åm{ùìM¯¸¬pÎÇ0ŽÄ:@0#/Á‘+f‰%ƒÜ… Ìx“Þôsªð¥QAã"ä@EX¹qÆðxRµü~2¥œÜ¡0¦3p0…¤ÚÂH„ˆÙËb%(v-LŸ¹–Cd%}±ƒ]Ù÷(KƉÜâ4@Ý×$årC9œ‰r¸(…ŒHjÅWü>¬@¼'5Bxú¾äÔ–¼x4´ñ¥CV‡Š]j“Î^pù$@"#*Å#*" }›Õõ®³Ü}Ý&Æðч›bVO³0BÏ×€S#,pC¯Ëù˜WðÍÚ§}~½2ôì•£ZCýNꊲI¼ë¦š3i=º×DHJMãs[L‹0š’k$ŶyMrY¬¶2–Òl1´šIã”Ó4;t²™4ÚŠb–V„R"_•®°¤j²™†Ëf‘¦%›Eµ5¶hžœQ´T¥Ë¦Ô%õms]q¬Õí×cELBPLÍU˜•^§R&¶"-,ceWð6Û¶¾NÈ›½wl“dQkDÖM[m‘$Ò©«[›-LÖöWI©m½zï#/h›M¦Ê)…MX¨ª[-&ôëZ¥j1ŠtVlÛή¼îL¦Ö™#,\×m5I¼Û5xÚëJ%V5^\˜‹SVÓkÆÃ^?[ÉT\xå“ì×ì[MyøôtýDéD.ZõÙ?OéøO·ÝÓÇV'Ìé&Æ4èG츥É&C§Ù4ŨŒ†~>½ÞÄÄ/î ö6ša«bæ€{a”]“¬´#,.î´bŠ#„Õhï΀@›³m¾6Úƒ¦jZm*f›a#*A#*… ìã¾f y $ˆ(ŠÙ¥lÓm{ªÕÒÖÅJb1!f’ E*²¨KD¢4m·lªîíŠ-%‹cm‚ pŠb*·$R(_0êQM)Ú`G^â€GE ©°HE#*$XAÛ-›1,Åc#&%µõ«¢„£R“T¦Õ´Û6e´›l4¦ŠT¦ßJÜ¡†ËQY¶%£’”i¥$(°Úm”¥‘6’21°ÌÆXØ*##/Q)šŠRbM&D´&´¢š,¥”ØÕ)l)¤Ê”¦DÙ±‹E2Y4•$¦)*Å’-J&ÔmfÓJ¡%&,™I„Ó$Ó%K-SlcTEY+E,LÚ“$‹5Z–k&MS%¥6Ùf¶¤µ|kZî6Õ&Ò³VšÉe²K|&ÐÚ*Ø‹ T#*#/€0Š"T*”Bë#C"Ê0ÁF@M|ÚÜÕ)lÔjÚDÖ©"ÀST¢&D(Ó_i<ƒ6ámxVJd:è¬ìÉI>%ß9çTuäºÎ]1“:Šøé€fÿ+81AMÝ.¾ÛŒ¿Ö¨›Yô|lè?Ô9#*Òݹï#,-N8eÓ¥ƒäÛ_Ì-ödjƆ£§xüI‘¡±Ÿ¿°ßן1™n#*CÙïòÆÊ#²=PÅžÐÈ9,ŒWåá»±®uÝ‹f€Íµ”1é.ŽÍÑT߃’”nÒPîäR•Úb]WÑ-|—BÏõj0÷fû1Áìë”:ýæÂŒ„P’ãM¡„†ò@¼À§3™¬$4ÆäãÙ›l`Á¢K>`©&z€zRWê(-ç#*©nt%ÁïT|š®n£¢k#,N\‚•¨AR¿Owl°¢wç°M±3‡ÜhTɵÁ±ü«mÓÍNßa?œ#/$S\P{4Ì"„$]ú|ë¸f_y{è„ßsšU#,†Ó±±Oh;#JaÁr0™È6&"ÇØeÀD3P¶¼ù¶Á¥c¡Ã,€°JKâÃJ®§O‹=Ý©Í49¨ÏÕð£úô×v¦s3Þ&™TZ‡ÑRä`ðªtJZ~éÂðä+g~½NC|À‹$Œì«X§ jzpßy"á†Ùòu6Ú >4H6õÓG"Å3Ì>|FÆÞí”q„s³PÕµ"ˆË€µ©ƒDê~ÆAfaÇF>‡JÙ]Ä@ÂöŒ$@ï¨n™]\RN,T˜]À#*±¶ÆÕF#,·ÎUÝt”Šài\´˜Bd:nɉö(TP"¤Š%dN»E—H1(œhšï}„mÕÒZÂýÖ#/,ë÷ãÈëBȬ$Y:îp–ˆô…VŠ*MîÆŽ€Ø‡#£6U¦«¾;1´mΟA¯ÐÉÑ#,¡Š~<ömǵPdbA<ú ¿Åî{YëÌóŸ±å][{éLcØ:ÃRô‘P••¦`}~¾w¾è3¶›ñžÛ¢ÙÿOð²X#/³V¦¾óÍ0bŽhÜÅüw¯;'ó{;9ÔWªXÙLjñ®¥â+tŸÌÓ«-†3V—u)‚Z]TÈÞ±Q4#,5¦ˆd™l#/Û´C2Iš¨µÃ˜#,¡±¡rÔ±ªÄ(‰b,jF”ËñëF#3†¥°Ü‘MœUV6pãPbmÊíRœÙÅA@Ä@¤––ãXâ–*2ÝÆ…UH¤T®Û¤“KV‡šEÑteS8¨¥!®)ž•&ˆ#»#*"ýîÕ'”¹¤çÌf&ý5¦š0ðB)Á5Ú5H'rm‚÷U„JÓ¸¤hÕ%c˜àùèú˜#»„ZÕÛ¦IR»=[Œô18žˆu79…bÏ1ÔÑ;PmäåGÓc]\O)ç9â;QŸpÖ!V/Ð,²+h µculA;rß >µmë)Ýmu^‹ÉðvýSæB(ëEhع¿³vçáÑóúH}Z‡Án„1¤Çîš_ —ò†¤5!±‚•®“5…y+n->.µV-œ›ä„3y‚¯†ÈÔñ–’æWÀæÝ(Ö@|ÑËRiHRhg¡3n˜ W¾¤³dT%eL¨Œ¿_ |rŒÂÛÞ¯±a¹ei#*‚9.ê/ ‚8I×äúÉÁz|ò üžºÎ 'åR:4W`Ðä>»´Å¾¿¶¤pÀyÅ#/Â9ÇQ;÷o>ha¤i#8æ€z°l#\aÍ:Š_øµ#,º?Ky&'u÷Ô÷g$:<k8¨7kF˜\2É 4Ð#,ƒMJJO6Ž¢+!¡¸M@(Xä#/4É”Ññ™Àngcƒêç§ÊuIp'Ä].¸˜ý•(dшU†R&y'€õ‹]÷Œy†EA¦ìqJ™ Ï_l0sZ¤d£º_:.Œ)$#á—\BãP9Lg%ãÎl¸ž·#/{Û;ë÷ÁT;ON!‡fT*©z2‚8¼Z˜•:(Óž7tvÂæ>É„@`’#¯'%™F;Šb›J&‡Š»I0`ÙÃ#*³D%¬²Ýü̽ÜùÀó§j¤}‡,ãxê.UDy£ÁcÍ;y¥L“¤!”"ø¢µ" IÙ§¡Êä~Þ"ÄÌ~ï(NqvÚšŒ-úVj#Q…74Lo¦‰¢:8#*B#gË.$I£°w^?‹äCÉt1áÀXlìb™9]ÚÜÕ« æ1.…÷ç˜ÈµØf=^hFÃnUfɰ ‚š·(Ø%ÔCDÔO‹‘À::©]›ä‹WÒŠUäIë/Q`G§yÃ;ºÍålÎåBãNó©&}Î'¥;N¡Ô@QHÀ±J$)T#,(²@l¢ˆUñ;}§Q¬_<©SCì;˜—-؇¬`ª8#*3ÞÌã£pYAÂþyŒ£ÔïÜÈ$ˆDॡÁ#*ØôJDBÄRF„†*¯ ˆ”]û@"ÄV,ÉA‚K+¼h"bl]e¥³—;µÜË×v3œ{×s1¬„z³Hj¶‡¬Q§u#ùôèp,è¹1€‚ðc²û=ï/ùbU'#/§mIºcg#/*]£³5¹w§;®î¼ó°¥x×9¸Ì1×w.)Éf—<ó‰áçgí–&XFÓpI6 ”’#,‘œ5¬†"Eƽ$o™#,HØÆ¤‹FÑд5ˆ$¶Øö÷s3þD%B¼ƒ©vúö^äµ'@HEHvëU×wî°GÞ8G>˜ñÓ¯—«ë€mœ/«@œàfØtÛ¦¾%Ô*ðÂÜ/å‹TÅ5ZÃc²ÁQ ×ÁÒ´.mØHHëw s÷¶gbe:}!èå`Æ:'O.>]¢U@‘½ò]çW«,OPv%x½¢›DDíàÓ¦RåÚ~8;qœt¥üì½Ù0džîÚEËQéSghÌ¢áúQH–ÀÞÅ“pˆÈªKª`«##/©Ú·³'?·Î‘ ±@`SÙU(ÌLÊ#,Àêã’DEÚD’l-´—µîåå˼]^;9·ÖÞR&S$0ç•ç«SWI+ÊDÕI$7#*8 …‰€#,€ÁÙEÞÝÕã®uÛˆ™.Y²1Â&á¦0°hPÔEb´±E26kè…Ü$C˜£¾+Þ]Mݺ`bãf)añû6ñˆˆ0.“¸CÃû<g^Öwª\i®0;NÆE;Zí¢1¤Ïw5~™z^0kñ.³™1’zšÒ“m0P¿V±Õ£VMª²3ùÒ‚ ëGK¦M`l Â+{¶ibeovÛUâÀfÙ¦“MY]t\ßB¼—ŠbK"ÆÑª-¯ÎÚ¹ŒTF¬k_*Qµ^—¥êV׊欘¿ÍýfŠ)Šª^ÑÑù/b`Z£Ë†®ÍHa<V*9¡fYüYº‘§Ç4ÖÓZI´*ÀŒ‰„[ÐÆtÁ¶µ2‚¤#/šÏ,ÈIc;zZB$a}VðÄUa˜ØÁY#/LDÅ„n‰‚j+¿?Nf¾0ÒqÔk„áÒ-‚ÃØs6:N8®È}ŠMàCþ$RrÖJPÞq†®TÑdÆ¢;ê¿Ð©1óøÂþGpY½~~)*Õ"®©Ä0S.LX1<ȆݮOE6šóCõí¨Tj!QH#/ª„IdTi6Š£hím³j×ξ¯Ë¢°nv,dnìºqQp‘üa˜!y#[ì\Ã# 2ý0ÛzÚØÑÉ®h'ÑÓÌI|Z@€€DR‰™(Qýø_׌ú¹¾ÀÞð'ÑzÔYãI@A„Y#*hì fên/w¨3OfîH™ÁÓ?6>ïøa‹¹ÒÙ°0…¡…'G»ämÆ2#*´˜–Tçª%Çe³WC¯ÏmúÛ“`ñ<#ƪ‘–x§#*ïE’mM¤@êèìØ¨ðÛ*{õ\b" #/’. *_”H>4-+öz¿ƒÔŸ'ƒ:ˆÅö#/)À3Ý–M¿Ð~Nva&£ÞCѾEÿžEdF«gQQþϟ燰 ¦“v[«l±^;˹hV9îèåŒQ=‹Ýۺ̳SWO¶-Ù¿òüC—^Ö»«°<a#,„F~`ø"Û8ÁÏŒ)ª)±Äò¤üP>ž€ô„_æ;×¾„O9S…‰B©i"2#*Ä#*æ×6ÛWJª‹[%sZæÐ‚$4€¶,À»¨ "bLI±.#*"Œ×,>wØDîÆ³2ãþD0m¿dÝŽ°f¥t`¬P[i,X)Á[#ÌchÙÌ"dv Ð|,x=j~ÃhòØÒ}cÍ ÄÚždõ¥!Åàh/8+ ý@ïæîr’H#*È#Kªh•A!ÖüK"üªw#îdµH¡l)Ðiy”æÀÏoÇwÈùi¼R¨ÄÅgìÝß;4׺°õà(.ëO¥ÆóVƒ3qBc› t#,!È -œm@Ѓ}—x”hÐÔâÞBüÔö#,†œ²íËÓßG¥?"v‘P0vI ¡‚ ¬6ì>;X0¯Æ‹#/©M°‚æªWõÑ–Öe&šï=˜Õ¯w¶iÝ´awW6½¿¡ëÇ®uÚÊPcL… ^J¤ÃÙk#*Ibn„Åül´!he–…AH(ëFÿë©ÿÃrÝ•#/@))Œ€)½Ôœ²#*6³ ‹Ø"޹gFr$´ÆÛM¡ñz`cºÄ´Ä±3FÐÙ2i²aÍ-I„H„]Øa¨i¥â“ ØÐ[Ue‰`ô½#D—¯xÊ»›®÷ïHÞ,ZwUsmŠönj¾wö¹ *Å s› i«%8ÅÄ`º¥™©íA¢L¤%0¦RJTe²"’ZE“F@«£”ÊM±m]:! `MYi4r¢M0––°[)e²©½—’³WK—#/dU¢°Æ´V‹z¨zʰ&î²u{µóõׯ~Õx"1¯'wNèå±smJîŒn[–æ$ÅyÝâãCË®ªø 6æcyÄKlÒo…»N’†cV`ÌbŽ0Æ‘ZNŒêEÛþfe„7ÉpÁÍŒ9b…˜yA®4(lê‹FªËbn@ 8PÚÏñä0aáªig\["ÅM¨„¤ˆ„5f3J×Ó^6Oë#,;O@Œ'R@è# dåø›h|€ùÒÛdžj“4Miú<¡ÅØCÚG”Z"þJ»je2Õ%f7Žª»Î»E„–)bD¡0K£ã¦?¦’˜@Ž”†AÛ4ONVàqãìz>#,áÝ£ §-Âø¼B¨˜uèa?7ö$¡.# …> <íðµflke,šÛKJÔ›MmóÿM^¥µ§q¨Ü¼Ûx¶ìÔ´Ù˜±¥«ËTcu\œì—-Ò[lVwSºéV×R±F‹UË6mË*¤´ÔR.ˆ)ÁZÂ#®7AXŒµ*H#/H#/ˆŸ‰dÞý`d9 š‚#/BɈƒ@Ù¼à}Ï_2Àj×Xör«±ËÃìñí÷xåiëm0orû|æ‹’}B!ˆB’Ê*¤%-?ÛRÂØ€’‚6Ä‘D”X2àÑ8ÎÍÍ™44ztéÇòã¶uÛgî~^ŽóÍç4ñ‹®×71>¸çð/UQ C ø6ÙD©02%$¤Ý–Ê2ZÉInt¦TŠZ¹·6Þ+}ֵ嗧DQlšÖFÒQÓX±·UÝQkÓWµØ,Q1D¨À¦@à€Kd.UÁaf%$›j5ªI¦Ò^Þü€6ÆÀ44õ¨ l"2<ã }[¸Çy±£Hu4Cýâ-mî#*f;tŸš!"‘€ÔV\jÉRˆ†)>. ÂȦHÂe0l`eaFŽÍ´V·PD’Iö¤íÉ#/&¤¶E™¨äÔÈ*A.BC ˆ¶ö»ƒºÄ²'À{U@d(<.e$7ÈObûd‚;Ãj¥Çfß--Ûòñ:”…|9xqÛõ¯„@¬ÅäÕRqFó‡O>~±v}°}u“åÜG%õ‰(ZwB&êuéž]ˆ\°æX4ËžuÖŸT^È)QPÒ¾!‹¢8"";-”œÃä}œ¢op5s!êPL¤µ†î];vØyЇxÙë+ÂZòs«¶]†4ÖE¥)j5Ñ&Ù¯y]TiZÍ6ËíÒïi]FÐF&h†!!¦ý—8fó#*n;y÷Ù1.WlØÞÛ´|š¥Š•g2!{§Ü¼>Ê®kQíû‹ïɘŸ‰çfq©ZÑ´÷•»úp5NÉ™n]ÝéËe‘‡È‚©‹„ÿ¾!¹yŒç–0H'·gÂçMæËdÃ9I11¡”¢Ja GkŠ Åc`Óy(È#«¦vV©Øi6`p´‘”¶ŽÏR6ÈåD´±„ÌG!ðô°xx¢'ŠyÞï0’y#/ª°EÞÁ’?¥–`ÒhTr#,ᛸʧOêPÐ$*=â–dQà‰jHïå‘Õ¤$ ©Q/ó{¶ˆ‡8I6tt9ý+ÔÏ#*gQÒUɳšb?}ŽHìÄ›GÏÓFŠëV×#‘#/ÒtÄb5)¢CyÓ‚94µÑ¶»›aPJ»>1¥t(Ò&2!#04ˆ ƒ#/6ÄHJK•5Ó|£*¥:ª¼”PÏ옹Z¸X÷É$÷s5ÏFƒ„59ÑœlIz ô‹ó:xêÔ‡_õ²ƒàÛÆð†¸ª£ý=¿ÇsEv›Êm,0xÇêvï®ÇÚQŒêO¤52uõ ôO@ z_bjÑyW#,a’‡Ëà£À#Qà¶2áä"²$‰É‘¶1¬ V˜bÌ©¦b¨Ú¥U-M6$Ö#/3¥5üi]ˆH,fm!´³õ6·*Œ•‹feSEH´P²š¤–Ô¢©‘‹Sm²¬´VÍL¶Ê•SD›X©DU5¦Q6j³DÓT´UZ5 #-!#,6{Öú/ænª¿e"~çèüË',ù´Hí«ç©!®ÕN¸‡/Ú”B#*ÔU‘Dh%E6Ñ[ck©Z×-»3Î*ó#/Œ¿¶ÔצÚ/«yib'Þ¶[°zŽþ®:"q@¶"5#*©PF¢È20”ðå…C®@‚~$dWò— z"¾´›Æ1(¨¹’¡ ÅÇ0ú0Œe>õ†›0ûV‡ùl| µ¨E!=þ~'MÁÝÈ£³yvÐÄ…:PñÀ¦¿þàÓ’ECŒ#*‘Bˆ#,@Ùò åQìNjíÚÄix}¤zm"UÓ‰oÄßÙ‹Iâ¶ÔXÛoh†ÞK¦¯Wt^eW-"íKdãJž´&Obí¯bØÎ<ÇyôöñÕ¦ý{ÊÝsfYºeEÔÿ\díu#*›óE/Jaŵ!³Ž#*¾Atch1Ú\×4½ff`ò8G/ÃôVSHæ…°°4.¡k‘#/à|ïoYñ€‰À‰ÞS#6sy¯ÓÎÞŽ‹•éÜÉÔŽjí€kNñ¢mfËUkHEÕ-éñ8˜N:C·qܬ4xxE“ôÃP»Î5XMp5#|µU…ÎÞìMætFÑɵ‘ƒŽJsòGFþVXO8ŠÖ0†¢+&†) ákbãüEç£485EY‚D8˜4º÷οÑí;–ù0,öÀý¿ÀÄš2"M6~èg!I{J¾î>ȧß'Ýк(}æ[Q°š{p‚w:Gú1%z¶Œ‚$ˆ`é‹cÿD!&a""¡" {ÿ#,xqÏ·õ>Kͧ!=ÀG”ÖVüŽÝù:>YžµÊ³‹i·í9z0:°'ɾ42jªhLd,ŠÊJ””%¡EB¤P0|‰¦:íµ»É+võád¯b3)eb¨Å›G¹ÌqÅöñ™ƒåÍ8‡g¡zUˆ–ßÿ‚èifÍbË‹AÂ0rRHLÀ`ÄÓKß#,ˆâ†å²B4Ó ªeR±Æ¼½Ÿ[‚Ì.1ã€ÀÄ_FN9ali7’)#qéãH¬ @cax}L„ i]ÅØ&µi︷“©í¹Ä0ѳ&?DªÐ™lGo“d± —è Z…™Šå%áÔ:íLýÅ :㈠ֱ£œh‘"b‡ÕtÁB5צ0ÕKU7W†:xœýô6q—@ðìdÃÁ§RɹÞ46§&` 6¨ÑFaйˆ@{Ù#*œ;7SªqĨ‘(ÏB \i¸¹¶ª#/Œ-¼h½aÛ½ #*äE2cÀ.P¥•cDV0…B’‚Ä#*„RÈD!a#/b#*H4ñlpR#Ô)âªÙ¡óù¼)yK‚uìTuÀ“Ä¥>¾}îß'}UˆIL‹5BA¢Š‹E£Âj¬T;ìž´üéŽå\öYR#,{u¼#,£&Zi‚ÏK-Ô§0ú•ä᣻¦¾ÓR)Ñ¡¬½Ù»!JÈr]íâÞ‘p©1ï×EdÙ*ôÂ’Ê ŒBÚ¸”ƒHm‘õ7öé<±>$7ñJˆTIj¨öÆˆŠ»d$FƱµø¼¯3Ö÷¡Kž:Jòå2Ryç˜m÷Ý$Yë»â‡£85CíãeEƒ\Hˆañ*… 2!ÖtË»MD#,¦tÑi€Ç’rô´pÀ‰«¹AÕd…ý=SE#,ºBFا4œët“)Çep¾Ÿ#*îiŒ´Ä÷‘cwrŠû§ƒXf#/Ç/º#/*ãÐ.Û#f#*Á¥š¹RÊ8@€KaËÖ“æï7r´äH‘ñ7Cm´ìeøi5ª#/ m|Ê؟²ßEšZO¿…ûóÊë Š¹Ta®+Ó0$- Lœpˆ˜¡HRZ˜ÑT:,®‹v=AäjYGí’±•…òdÔ׈F~R|ôRºáº©pJ蹯-¥Ðw„DßÚªÍ4³ƒ¡#,S¥Cæu/'›ˆ£EÍ–ñ·O‘õ—©Ùõ¨t=I½%,fÛ<r΀biZåSEѵÁÅ?YWtPi«º¸h\=5Z>•m®ÎKƒ8',6,£q‚[(;<3³šÄ’ú¦t›ý_Á”Ú0ù{ýzàÒΉS®#/*±‘‰UO#–·wZ¥"UzÍ̺š]¯"Ù`‰½.Y,Š@"©'QŒa[ãÞPuê¦AOY#*/w.ˆÜXˆnãÛ:þ±#,½Â#/dq7ñ('‘—ók4»¿4(Žýe8Ò+_V¯^zLÝÜ΃îl29p5özLƒ¢#*,ˆ,Œ rNZ4u øù¡!œ´-ûO—À€Ü²Ž‡E–í \(rH= aCcñ‚jëëóìW=›Ží3& õa÷ça}³Ðê×70(ÜXßËÝ·by+Õ1‡Œ¢'‘L#/J%ã¯FXD3&*ñ^yÓuç›x¼çmu‰YTª“mµ&ÛKHîuÓ¶òíuäÑt”…¨‚ÁOÃå¸Üo( ¶d+?Šý!Z½X–ÒR¸A@~ I#!¿Ø#,ýÒ_ö>+¶4 +4©… ωV†[Ha¤”Ì2‘dD™ªŸFL“âœoêë#/nK½·f²#,å.™p¸±‡ÄVŒ}ZÐÆ2¦V†Á°Ò¥q¹fˆÚdebÀ™rÈ5ÂØf¨Ê²S„4ÛÞ‘³·%™ð´Ž¥ÕÕ뮽KzéEÓ±¦&#,t›T›Ý1`VtIœPhˆäYLg6t|:Óiµ¶Gnña§ˆmãÆ,xͲ6²„$lÔ¼pÖ!vm:‰¨<4…¼8d°ØzÌXF"ꀨÆ4ƒKª y˜†m–ÌS#*K7(Õ¹}q#*þN&Ú¤NÀâ®~wRÈLl²–#´ªF@\s ¦1à§7™a¶UAoóÊ'Ý襥‹¬Qêôˆ"åþEåãÓ/@n"lŸåÞïðÙ¾ Í8:œM¥ÜIÓÖ>ª”ê€bHˆh×y•šK*5’¶&Z6-&¶£T¥ö®Uù—+])_`²#*û°Ø[ ¤´L”…+, A}fCÞ‘]8îOËÀc£¦5Ë)EÍýMª`åô{€P#*!èíµš²tÐv˜ïêoã·CÁçul#*Xáó@ÿx¿L;ú²§ù$ƒ#,îI±¦êT2'ΦÚ×[½ëݾ+÷mñÿ×]k„¸hÔáUü¯Éd[JËÍîŸ9m›°öñÔÍn6˜I6ö5cpß«2™B$îôM™ó&WÛæ7¹öhúÉ…dDñØJ¢ØLR"j$n@äudñÅ&/m¥Ç÷S}ZÆBa™$&L›|æ}zìcŠ3ÕY¾ÞFZj¤‰TÅ ,8ç¤Ü÷\°ºD¹–ÖK\ö¦þ/=€bÚ)–ä°å~…/¤»–úé†ËÓâyÐ$/áç¯ÛmØÎÔpCÝì1k{O+½Ì ¶¿ÉˆƒI3×î”äñ£óGuô¤éݬ}.xý+4OÇ]‹>ØÛ¼á컈TQ•©7þ^ÇÄSfÀÌx¢‹íÁF˜è±w¿oGÙ„÷EçQñPT6Ô2ˆgÓ˜©¡¥„1^Š7O~Æ£Þf8ù×ÝìMG牦¾©9²6‰¾Y›ÛbšË«£…JÎDÑÐ;>©O#/ÌjjíÓØc ïì¢Ñˆúb9d}Üeõïxù\–7NˆÝbg[yÂ}ƒ öà XÔ#îÐÑ`8#ö¡˜ÜFN[þ–ÙØeðX –çiÏVú».¥”™ùÝ]„cL>·0‰pÓªAk €nÛµ„X#/UL J`¢2Ë%Ã5CÛz$‘,„‹ ¼ˆ& ¼å-hi#,þ:^ýE·VýJo¨ÞÕ͘Ãþ£&ר_³ ]T,Dˆ·x±Êˆ´˜ˆI¡•å”eˆ¨°H$7[a;‘ÁHá€TF"€£LDo#*J"#/|H+‹‚ B#b7DÔRŽ6šÏë™sÄëëäsË ô§!ðâêÑè w~Ÿæº^wU3±kmVº%ÓŠ#/ø1÷qL¼ÀêùðÝÓÓ€2æi->q<O]¾‘#,~áõ´4èÓwR`†ÚÔXXÎB<¤ËSDé]=x4°Á×Qkˆhè:Ó„nâäy -VÄ[Ëô@áQš|Ð 5ç—<Á4zÑǵ㴧3`,_Ö#,¡"ŠKת%Gh‘ÌÐÙÐMï®qiˆQMCTlÙFUs(V‚ &Ú#q „h‘Fˆ šI¦´¦Ö»UÔ›5ª™WU±¢¹™x¹ywi[Ík|¦È‘a"@ #*E@Då침ç#,`÷Õ<¼ŠË0>¾¯‚R´×°¥1´ÍÒen¦GBØÑ+F¾ú$ßÛâ02“qãO£Iôfâ#,®¿K²œ#/—T¶ùÜ% Ñ“”œƒcPÖ)Ž'-ªMù´E¨+j“ê8–Ã<?ªálxÐl6%²Ë³#È—#, tÅCà;ä87;¢å÷3!eÕVX"1Ü3·<‡ŸñèOOb%â†q-vÞM¹”dmЯIÞ†± lëàø›2ed^àiÎo÷×a·Xø"ŒTñ?e½GÓz¾Ç¯j33ÛŬZfáæ:ï@ܶ•»^£Ìñ#*É€C¹¶šŠµj·¯h××ø·]ÍUb$Ve r§#,ꟲ³®ŒØ²A#/_ht˜¶L1üX¤6F#,£|ie‘C#*ñ'Û#,Ÿ?çû¿Ïý?“@¸y¥-NuF½Í1}·IÞšöøæðMñµ¬6=‡¥BéJz޼öÕÕ»¬¡¤”$55@^òAyÈ*CõÊÁa¸Uƒ¯«31ë_•ÁëP¸B¼‘¶ôÛIE`¡I±>ïo"â‘Ó#,ê.ˆ.þ¼8‹ÐÎðÑÂâ”áÔm)Øô^F–ÆÓ`úÀnh¡’¿ê|Ž:ÐÊiÓlpÙîÉŠ¶@ê ?.éÿ Ì5;ï |øœm@×R¨¨ãòý¹Ï3•Uð¶x<fƒLËm÷¨Êq¯-úKDÄZ\&¶dfê‡@:ñ†J_#*ÃÔ)š§‚#*ØFBçRÄ:x¼lã´Ø½¶†ñ?6#Œ;þî^-¶û:c(˜ÒÉC̺ëd¤À£>A›*²é$¼v‡@üuqÈ·~òj|çðÙ4³ÓfMèQ@#, }™¡ª'Õ‘ÿ<„vS3Îz<•f,+¡©ß Mµ#,,â\4æ)#,R(ý?¯˜fÉ#dB¦œVÅhóÞ¿ªŸ©†þ÷áΛÂ8 èÌdén槤DUNçĶÝ#†Ð´"¼V£GÙ#*h(Ñé)‹x£ÛL1íf&g#/ëÃNœ•c¡Ðžk‰žÔ2 r@²þ;Î.wèúl|¸éèÄ4ô# Š"i;!“ÙÖC@×dž#*É!ÚÈ‚·Vêkc[§ßT^6ŠÖe¢µklZ±ª6¢¶ÔhŲ́µ’ÛdÔVƶ׋PR@RB’@”'š6 ànQ;Oâ¾ËŒž уIÚªdb 0dH?˜4&•W¢ÊBÁ#/’\¼:vÎÆÛ®íÃ8!¸€rÎ;e©¿¤Á`ºvU½†`†0¶a—×@‡ñ;•ÁL1°küTqv…c¯îž¿mµL|@:é«¡ä#,ÛËl›l`¹fØÖjMP9LÆËó•’vå ¢¢žà÷A#,žG£+åý# AAEH±8emæÁ³0ô(&Õ6R¢P»Jœ=9—#*¤«ò©ã¦iÔº?›A7aOæ!7[ÔìØD ÜÀí¾÷9‰Ál€vH?iÀ8åߦŠ_BCÐDêšÇ+qQ#*ïˆf-æo;cD·7|PP´&©«[4«ŽÑŒ\Œâ$Êl·@>§'ɘ)…†À¨”>ˆTMqJÀÕ~¹*ªJ<\¡Ý${»jõÞÎs/H™çBQªš‰¤@´yA~¨Z)YÂY‰R7‡Ü#*îH®§2FÊTý‘F‚…l5¥Ãòç¨Þ¾ù™À´„Ì‚Cd'Tà23ˆoHÉ6eT‚hªÕ#/€×Š}}ž#,÷§¯åêàmÒ5žfA˜ˆJ#/'Üî»·«|h)Œ›[à¶Å/›>Sé¬Â÷ËG’µ^ˆ~Ãå³^I·É ønWÐÕ°¬5nç*"a,“22©rå93ɳC;P¡[r!{n˯Å4ž6²Lbø?Uع`±#*˜ ª£‹.êLóéÛ@tÏôiè]Tü½(ËØP›@ oÈÙ~Aä(>“Ö7g§au9ùΧLFeþ¥«¶6‹j¢IYYªC\V®‰jÈS!I#/ªF¹6#,sai³ƒÒ˜Ì¸ÐG2—rLo#/@©¦ÁÆÄ"d ^¦íåºëgsI–·uÚRM©Fm#,qwQ¯f©æÒþ#ã2Øx…”3x``6qÁƒ2K-c"ŒF‰hÀqCRB7ƒhdq¸4e´N<…8:5£*hU0‚$A‘1§¨‘+kñ„Æ!°k´#Œ†ýû‰'é-jöì½f°¦©Œ!uÎÍx¢®oœ®™l›jM®t“æîÒnR£iU‹±¸¸¥¶#/!*†##/Œl¢3A,,¬æ¡i#b£i™1‚˜Õ,qÑkDHb†ša`†Á©ª”Ô43(ØÆ©$4¦ÓbK6ÌÄȔԽuvòí\–îw8mÉ“}-ÛË®[sGeï75æó¼‰£B¥¨dn[çë½ÞÌØf`c[0¥”kSIy’â‹ Á¬<b3A±´ƒUÒâ"T„XÁá6jÕ† ŠÀ Á€Üv;ŠjÆ3Œšcy‘SC[y&j*ÓcϘg1#,0ØqöÕZÆ,äËa# ¶E’‰>xÇ Ûa3áQÆM¦ÅÍÀ—t¾è-´°È1œå6†ûiFÚ—¦9Ó>¸¼½xÓvÚh$#,«Ö×KF‰ø73®ÕÞäÁ«-0ŽaËNlÌ,–«ÛÎÊ»s¤ÍÈöëµ¼QW³$ÌŽöþKŽÂ“]“8¦ƒ+‚ÁQK-+L#i¶œ–¶DíJØf:¬ «#/6“Ç‘¸Ò-¥Œ„I˜Ùhí‘•¡F‚h‰*ÐRGŒ‰ÍmŒcbMÙÆ†32KkLa›ë—8á„iäx±#,[2’XÙpÃ1xâ¼@âæ–î¸ò•©a ‰ #s&#,ç¾Ñ±µ©>ÆG¦~#L“aB]/s‰iÖn„m7dÜÒ–P9åLÖêjÆßçs[s{žJˆ€wŸ#,%c/9ŒY<èA vâ|¬K$¤ÜÚÚ0qÃ3zÂ4¸i#v#,0W#,¤ÌbÛ1½½Pƒ©°óòÒÈ#/û †|ÊÕÈÌÅ,Î6êþ¦ÆR\10ìK #,ÄpdÇܾ‰†Ð½ÏáÜÙ°DðîcI%.dûÏKñbç™=ïnž^ìt´›ÑÎ$ÞH¨Ìm»9a]ÈWÑŠ¸Ì{]dÃó[JdÀá0Æ2#*³6É*mVoŒº]GºqÅÈLJo‹Æõ!±&s€®hÙµ†•ZÌdUG-‰Ò„<#,êQ‹Ð$#-‹ÃqéïäùE5û¬0Іb¨l†û]?v<¬ dðª u ošÀÑà‘‰±6“ÜÅA²Ü,eeU»mƒz@Ú›‹å(ü´ß:á†Ð¦Á¢* œÄf"1EF’{éçsµsh«¥l«Ë«‡”Õ¢¦PÐô "â#,±Ð`ÇHQBbÄ1Œ a#/6¢Ú1"¶B¦ÏùeÞ#*oÜyyŸ)çðâ‚r<Yø~Ý,Ë8¤èèyŸÛ"[÷ÁD..ÿ9·¸PÞ?¯ñŠ¡ýS¶ðgðAQ ¤s ù¿wf½õáºÅÖº´£6OäK¥ˆœÅ](«ô~+´ñºÂçx«ËÎÍ"ƒéç6õŠ=Ò½»#,XÚo¼Öæ¥%+Ý‘½ÝËåÇç̸ùãŽfŽsCão8Ñ‹O’¼«Y¶fºÈ4K*Ì—scÞhD#0¯FtvŸÐ¾gÄe Ráe÷ˆ«_ç\!€%-—¤ˆI!ÉÌQÍèSóÔWª¿Þz›çæS‹Þwiä"‰£#`DF$ž’v›£éÐmUPÅ„0òzH³:–Ï 'L8é·Œá¸N›a$b²ž§kÏsào“zÖÄÅ»ks}þf‡ [óà],o~÷‚B5S»á[†²o%þÒŒ^Æ(¸Ãð8†–r<eaîAÓëé|êañg>\–íÛ..áš„,n\·èä›&=ýP?ÃP<9‰¢”¶X8kºL ‡Ài×-ûjGŒq‘޶‹ü—±õÀ踱³˜(z-ÃF’V%¤àŒ§GôB0øƒ"(Â)ñýn~ß} ðÔŸ#*8 H"#*©¦¯~÷²±[šµÒÅkKrŒ(…¡.d,ò‰ #/l"AùÒ#/ÈŒ²™\3K5bUEÛ¸Úiç›Éæµã¥FñUÙkpªºkWŽ–¯wE¬jó®]5vªé·vé¹v¯QOÒX´¤b¥KsŽí»»m¤Õ-M|[UãkÆKZMÍÛuç›Æ+Z«ÆÔZ`‡½Ã†ÇÖ˪(Cש¥ù ¶’ÄsJˆäˆ’ü1N“ã„ÖE´%Ä CB²ëVm”¶®i’íjìÕ¢ bÈŠó°HB”n…!#*Wƒy²øÚë]{Ú¼B]"µÚöµ‘D‘0ŒD>=ôöká…nUÒê³]kÙmDTV¥$”k(¿©Ý-ƒE6hEH&iJűª*5™¢Ø‰5Ñ£f´›$S43&Vš4Ei¦Ó@lÃV¨…©‰U ”°„øÐ†óáÛ ¦gWìøä&DÞk¾u[^¼ƒIµR)$ ’$ˆ–_yѲþé÷y¯Ýäô<Võæüô§ùòýxCÃúŠƒJæŽÇ,w½–Þí8[çG U ȧŒE$B$u¤¦Q£hß‘Íôï]~i¸³FµtªüŠÛpÕbÉöñ]€Ú7¬®ÅcI§w[¥®í×kXE£Y#/MQãy庛JSmi«ezíÙ¬H’#/”¥RƪÍGüd7ìS‘“,À>E’y($Âd@ÞC(a"ÆIF1ß!¡d!RíÝ’ˆÃ*¨$ &ñŠJ²¨‘™åݰ|&8ÂÈM(9•àå7#*9+ˆCRëÙÈëÆCZØ„ÒyÓÒóY÷a©ïŸšŸÓÃ,}º)սޓýSå˜U,Û•B}3M„!ø"06l=UQý,ácG7µLÌf7?~Ëlc]Ì“MB`ƒ#/a!`Í©¦èà“L3$È>—µ¥æ*ˆQ‰1S<¼OîÅçÏÇjÈ„$Ûiá1°<¦ˆt2b²tÙóJßÕ<˜ã §wXTžD6C™?"ºK±•ö;Þ7B˜²^l3&$¼‰æG;䶤œù qòÖôž3Z6×_B•×W¶Q´ž¢ÓEá;Œ8`Ë,˜iîö{ž °Uþ2r¢HƃÖ;â&ô¹Çùj+ïš2Õåa;v©³ÆËgòãiü8øØÿάø`¨Ø«ôË)Õ+j¥b†ž¸%úöÑG¾Ø¡ÒâÉë#,adPO”Ea$Ö¶+F©-¾X_ZÚºVL?ØÇûH†W #*Ê ¶&p± wQ¶JÖÆòm¹Zñ¯«ÐX¾ï+c#*JÛÛz¹Z¿ÙÈ8廦‹Œú©A#*0Ä@µùٿĨ¼üa{zåïÎ#/`ªò[%Y®ºÏ~,ZØÌ¨(@ûÐ0À’8ž÷ºL‚l%”\gZ›†Ô‘h04OÏ6i„6"æáÄ\Q’AXÁ1’kÍd¼öÉUçu]°RˆŠ","S,©LžX§ V0°ÆB pg8ÒðZ84U¦Ù2 ™ƒlíjÔ¥"PÐKd*n¥Ì¥KR˜ˆP (€ª!B¡B±XňG÷ORMP,0³%›Ÿ@RZ°*$#/#,#‘q@ÔaÚa1æºöºŽP$EcŒ=äÞQ æÿ?_d¨^sx–‡²’ëò?<õ¦’Í]Læ´øµÆYÍ:–.ÈÙƒ·n³lô]Á(Æ3Éj6íÓá¿=Ú s:Î`YPAäE@ ü—„À-oV¯ÅWZÞÌEwéë<4Ïì>d`tW¤#/3µG›Oñýaád^ž5@ûc)£ìeì#,#,(žÃûTF/#œÉûY#,7¢©J¦•EÒV¶výšq>’ô±¨üd7Ï‘á:ÕÖ³æìß©A‹9/·Í6ÙÛÓl7@p?½—p¶\¼d 1QfÚÑÊRt^àî6HhnûTí5g¬Ü}ÎϪQ³DHk¤!Q$´>Ó©ÅÔofNF§TPHmð#,ƒœÃÙHØÙy’æ¨Ún¤+XÛBbÕ[Ã’ƒk8(#,H†ð²‹Ø‹Ú!“)ˆER@#/X+Æ©jJS$Âêl,ˆ‚b¸0àr€–t+Íѳ¶wöû{KÁ(LGí|žÑ=\#Vß}TøFÆrÞív=ÊñEÊ“zž]¢Þàcì?ÈÀ|s†`cÛͦü9A¹µ]©DZ§5–àªdb CJl%Ÿî»ßIB †GÌ2ÇõÙð¸›Á#,’ð•!#*ª–¤$Tb¨„*"ü‚åág|X²,‚t•w`ÕÕ,A)•q4£®ïØ”£/+’Å›,‰Iš„ÙKQä«›-*“h¤¤ØÁãpÐa.mÊå·3‡tÞo.Üu×jc•ÝÛ¤WvÛ¯ç“lr–[Éä·W.æ³,huÑæÛM<æZ¦¥nnmtÛ¥¶ºm²–6ºÅ6îÛ´›%oѺsS™-ɩݺjë.vËE£G6«®ëTù„R¶" óÒÚÅ#/.ö€RÀ zSÑ#*¸mÂk" önôp•ÄOXvˆ…ˆy@pÜôw|/VF¡( B"v±ÂØ‚¢ðûQ<AÞz(?ºqžÅTìAßp}p¨wÀ‘H,Uå£éw„'¨5†¿[<²CáÔÓHz¶ˆyö÷ŠOº„#/Ñî⟧¼év‡_r]⤈Æ2HHff›é×·5W´µmµÌ´A3RÖ¿âSi:½œl(¦%%F¶MXZ´3VùDC"'êõ”²Z‚A4¨RHÈÉ\ÚíίKWxuÎR͢ƔÂX´–#<n\XÆRJ‚x„7rBXq"#/ПàD’G#1‰(ÖéO:Ûà1 ]Ò’’fÊ(#/(hÈI” q²QC X˜!¯UÞnv×¶zQ¤ˆ£^7¨ˆ–#"ÑHÒ±f¸¶`…#/Š´ÆV*#/K†£¦åÀ™)ðJμ·Ñ`„?¾Ç¨2Ǧ0Ò# F#*@hÅ™î?‡øf£×X#,KºEÎØšEà ‘`ÙSC)UYµJªSA!À·cäf#¨ë Ž‚9ŠÁa)6m‘¦Ó&Vµ°Õ«ùu@uy&Å#,j ÇË–N•B‰CRZf&oé5iZŒÖ†ÌEbÀË-â#*é#*CýP¨E«hpÅGÒŽÞ4çâ’#/PlÚå‚€#,ÕÐôöÄò]¢ª¥Un#,…¾î7ÖǤéôÜ6ßôÅO_É##äÂO"Ï/>VÿãŸ1x¤3±¤Ì`˜s(¢¸C2ÖäÀIÚÎ8 Õ!>wrpa2ÂnìŠ,’ª‚ª–ªµ4¨Ñ×]ÍŒï¹5:ÉŠDH¿º®k?ž£šÄ2Û¥Ò@é'Y×#,]ŠÚK×rÖÛ*S÷°®ÁÀ#i!™ ‘,aY$¬QŒN< D)j #,ÈB£ŠDd ¹ª3€¶\ #ý¥Â„%0(D`R #/G:X*7ZÔ„¨„ Ð*Â3ŒªïD°F#/ã#,…ËBÉ-„¶Jiïj¼bôÛ•%¹{Ù«kÅko&‘ĄÙüŽÎUx]—YÅÖÐδU|œIíö¼PîÎÊ«!ýmb@$K0†€M¶—Qáwˆ"zfI^¿X&Y‚`Éš]÷°™Ä‹rŔ¬œÕ¦î`´#*–$•(@XHÈ(Ш9Íù4Õu͹¦™t€#/Mû÷†À¸A&ÃË#*O’tð)‚ƒvJï+Úœ$þYŽ¡ ÐgïD+DÂ@ à††´)F mØrfå÷C±daó`§ðCFÝeAâHÆ@ÚNj{ ÑQYT#*@ ăD¨UÍNAOÆ(9@ Q"F$#/.$¥Š•lÁ²5ø6°HE:eÝŒHÄV†šçPñŸ$X{áá2d ±O™Oú6¼yÀ>ŸßgLhZ‡6AÊR±1m€ÖºYq8Ïã‡#,ýpÅöµÀAü=LÆé÷fbþÿ‚Y#,jÒ4bA ÜÓ4ƉÁ"ÐñÖ›Ó"m¼„²d$ÉEI#P#j¸Ìx2<jŒ¹[nÉ©] ð3Ucú²pͳk`EZÕxñ‘¨ùeàÙÀj¡V^[m…{´Â?Úx=©{W¤M4Â=a¢HÁížD<úÛÃi¡ÜdðTõèÙˆÝ)PCfÚ?D£¨‚¬7…&ãžb#/o‘üñ@‘QL@T¨X ˆ“×CLT#*…Ùì–D,`Qè#*¦<)Ì¡òw™sAÕfá¹ü !•¾óN‘€è¬‡ºwývþ‰Ë#c«jèàþP&GsØŸ€@„"HÁ¤,3FŸ¯Zýj“éÞoÅÁEÔ0SõD##*ÖýŽÎ={úôñnË1ê+èÝ9]*PWð*"¨Øß-4d×î¢ MvãÃĹ6 ŠGÚóTPšœ¡lýÕz0ÁÀ2Ò%AŶ#/del Üßó4j\¥ò£VÞÖ³ L1¶Ð墡8¬6e¢Ã“õe7ËFâÅÝÌtðŽìÊ· 07ɄŊÑLäåuÌŽ+Uâéq(3‚¸7Ò#,EW…“4dD´…¾Y©ùûD{Ó½D7–#*òˆð8þNNe#*ÕÕ說ߓEÅŒ´RÐùQ¢92J Pn£DØ¥ïÀ¸yyxšík'\m$~oOx£à¯Úñ"GßwÇ¥ÞeóÞk/çŽ-9nahª¥ƒï».Qo»‚8USv9”‰{)ÐÓ§¥h”#ú• ·¯ë”;7æ"É;VÜ%mKtZ9Èö4=Kþ ¡gv„Æœº©±M¦–1M+¾‹Òºf÷j]QTÕæìRœ1T¤ êâ#*‰´ƒÞšÁ5¥…«DÞ#Lz„4š1SAØü'w‹'4ƒ²çãs×%ÞïÇtéÎÓ|@Å[t¼Sçž:[Êá4–Ù¥1¬òÓµ)æ—±ý/ZO6o'Nqô!¯YæÀxc¾ÌV=Œž-¨ž4søË5åÛaòdíBÞî¸ñÓ^Ý,)ÊŽ išÎñ¿~Ò»<ðmâ°# »KÊŒ|>Ѫ «°S³¦Z]Zĺ$žêC{¶‡§²SXÐU:W[Šb_«élÅå!³Í\¿Y~÷#/›ÇõY¥ã½ru÷O µptï½;":7#,0¬D1"ñ%‚Àf“ie¹w ín\ˆKƒ²œÔÌ€”nÏ·™à=g°ð%p†']¨•^ì`Ï×®ÿæUÞ/OßÉ™¸â©‡4;¸wcãåççÎp~%ŠëBåœ<Ç•¹z´q™~^4í0ké¹änL!ºT”6ß¾ÚE*‡LuÓH†“¼"QŠ)ƒ¸7uÿ]KùT’Ð!6\Ö|›¦4óÕ<¨Ý˜S )R@Úh‡#©G_.•9Þ4%0P>®¡Ð© Ì[s÷㘎²ƒI©¡ušÕù ~Öoå[Œª«Rª«6»{kI%Ôß©µÊ¿qã•«†¢Ûy,’H‰L#/kx ÒK¥Š¢[V4GsWokWxŒ¯ßêByÏ…dÛºD³0îÕìr¼žtøÃÓVï¨#/¢ÃÉRfIç©C3ݯ/F©;i5¯ä\5ÔØ“ÅT(;À¾W§oKdžp&PƒÚgzÇÛâŽÃÎy#,„Î+`(0Ic@[š•¬ÃBÐUŠbBÒŒåoãêÒúòs&uRÓ=1U‚áP#‡3âXÙ‡tRï&{7z:rJGÁö÷¼îg&¢äПÛÅHÙ$53hžŽBd»“8’ì¶G?#,Ò2wë–›ºy[5½!`T/È#,ì߆XTã’I¢lºC~da…€‚™ùÁ#*M*—k9BL¥÷#N‚÷eЈ?Ja@5ôbÀ^3ˆtþ=ߟ@¬M•=²€†ðàü»#*‰‘KÁFFA¿¼„B$>(Jtãß“jÿÛ-í¿<µ[D[°$E”;÷—«‚íTƒñáÏHöVãòWœó¦C37PNq ÛG1æý£´ë£Zrå=>VllúÏjwK¢¿C›#,Án€ñ‰‘nÜËt(èzNÞ±qÏhðøp:£Ý7Ÿ¸Ú5ë¥øxu^áiÜÜÆß0àVÝ#*1¼34r³`\F¹2îæŽØàÉ£sMDY´ ‘8+´6§˜¡j‚gö"¢‰ L~z÷p!UÇŸ3Æ<•Põs#/9m9=Ôz,¼Š™šßWEáÊÖh£âvñ–9“Ó¤ÄÁ–U§Ô,è€ìUÆùñò˼QL@Q‡"€¢'„#*"„B‘‚j.ƒ]š›žøÀO†ëŽâMGp€ìß¹gÔ9(ù U®Ä™ï;K²-í¢%4¬$3Š#,”ák¿¿ö?¿èñ¸+$GÕOÚ:cD°"@L#`!üÙZ¯›g¼_£¿oÛÞìfÚµ¹5fƵñM5mYCPóEß#/o=ô†#,”>]±!‰ËöÌl;ÝP£¤Žg¹·úo×MÌÏ£«2špãAéšóWiI‘OJ!R‰þé¶45ƒP’Gú˜kÄ׬=ñnÜ/Ç’}w‰wžo‹É•w`?È©ŒOw?5¿ÌÿÛ:ýÈJGþ>‹kê7-g{PJèKõtÞ;$&ñì}wn˜½°ì¬$⪆~)´xÐxÀNQ¡‚±‹‡«®ùa+Òcà‚… yò¿ò}{«rÇ_Ë^Áʾíxm¬;õŽ£ßú³ò¿»ÐÂôUASöÓc;Õ‰ztI#Rù²ë˜îO=ùŽé½c*©Ç#/îýúàº2ækÖæy½QMVf÷ãÆÂàÑ0'ëò0ÍüÎÖuó;v(I ìî0üžg¹VÌjxÑHäîÈX ÓB²d„‹@D LèC§/†ÝÔd¨)JmE%‘0CgFaîÊ#*›?‹Ö:Wu§š²üž4•ùÑQ®"KÜ|¾“PÚ~¡"ØP#*P¬bÒ]?‡]µI‹cUKfÛ4µ-@ ŠE$#;wí°»Þu©$ŠŒÐè\Ö.]¶4ø};ZŠ!@|B3–ÅEŠ×ûÿ=ëÑúÿkÃÌ„#/ŒÈÍ’#fM›DÄÔY1 1FQˆ)²2lM#/L›6MDXÅH~rqàüOwC^awŸIÅ’ÅYñfOš{èãñÓ<ÂòàÁÂq›a'p¸Tèf¦Ã„B6˜ÔFp±¬\Þ9äK‰pDÄ#*Û@yáªíí=•fû}§Ð¾é¼¢hT©´ù….¼³lÇ8™@¨#//mH¤jUg¹zÒ·Ÿ)Éû}™{hóg ¦Q:ÞÒb ¡‰¶ñœLÆô¸_¦mtÒjªrùº¢“ÓY¸ô‚ñ ÈGºãêZ†Ž»´:ºbÄÓв;çG8l–ÚVévO<î¨üþ=¡Ê¥äp" ~uúÃO¹Æ´eÎÙB1uè±ñªIüŒ“/û<ÿ—]ôv¼>d*$zœ´Ÿ±$#,²Ø*˜ÉJ«m6Ç6çUz³tØ[Ã5k¯^w®÷öÛW¥g³\º¾nj¼lî¹)\Õ]®é¹º¤º®‘Þ÷ä+f$¥4´›æÃ¼ÂƒªaH¬0”˜I#*š™C#,±"øh€!•C#/ˆ{ª6è‘Æ©d½RµßJ¼E’DRAdB-¼mÀ«—K–w[—²ÖÛy¯o‚_£ØŸ&/#,eFZb8σÀÑ"´¹d#/‘ÔÐÄ2"†Z¸ÓÝMkUЉ©ªË†) ¢æi©aý,0¯Üýåêp³¼B2ãcbâÓX3•QFÐÃ;‡†?+÷œg8†ÑÒ·‘m Ôm¢VÞHFB#ÈìÖÍ&ÁäJ´«[6h¨¶qˆD„II,"‘HJ`,€RŒ«€³5A”«§s"D<]æÛ¹i:[Å/FÞ8ÔD€¥=66ah’iB0OiŒ.¢œÑPLlÚqN9 È@F2ËmM6¦œM3xˆ5 ŒcpÑ-#/ÕbÈʆńc`éTª+rªÐéIrŽÌ#l®·€&m„UÅ¡4A(ê‘Fä¨W#/ËhÆ:#,‰²¸È™J*7˜JQ£QÊ%#,@Á°id:Yf½Xæî<M·c»Ý7°†¢®nªä‰†´¤¡3ˆiR #/âeJæE¶²¼‹k7¨þc#Ì$æÑ½lc4sFöjJèèÝì\å)ZEiÙ¬FYB²Hì2"ReXÔcp$¼ôÃkOK ·ÛéjgFuªÁóðµ¬YädÓ×V+bOƒ¬-p‘¡è½CTÓºY‹"’@‘¤c#,ªµ<®ÛAš6<2XVƒ¼™©(79#/TiñÄ´‚xQ§údUâiy(ÁH#/ЀwêŒ+(ß)Á‹JÖ“Œ(ÀÐȆ•è\4E‘]–45¡C4+5I)23¤LëFPÒ: F©(C ÇgÐ{l9äXÌ»AtcR1¨Ö•hHXÅ‚Óz£8«@¤¦X”®u¨LÆL+"†##,3›‚¬PÃFˆÄÓFX„QÆ#/"8¬U‚ Ð9AŠ#,#7¸ ¨çÝ4ôÅ_)›x`›|ɧ‚9&1TÐD˜• ˆ›CŽY¼R®RQ7£ÚÃf¤Qn·HÃvT](»gm2tš ·iE/(%ª›$©"ÔbɈšfŠECWæQYžVàÖé†È(ø“ÒF¶Ðµx#/Jùž¦YÊŒM’ï‹ìu¦÷Â…}0'ƒ:fI[}™2”º#*ÆÐÚUDU޵)v°K<+†#,!iT[³šÇYŒhbði)µ–Ä."&˜ãójc€6/'NûˆÁ£`Š¢H€ˆFÄÓ:˜SDD4–ƒb„#/ Ĺ€Æe#, óoÆÙ(ŒšË/[oVë^¥&#,i2·RÅ@Chd‚ái£íJÔ”©d'#*èä®74k¼w8nî¼û;˦5FM®õÕÒßËë‰êäwiÜ–Žú/…¾Zü;IAV¶ÅSfÑ‹„AÖTý¬«Bê!øj§ëCý9/!è2ÌPÍ#/v#ª<§éáF:Å*(µ• ÷ç#*ò\îÉAÔx·ÝzJŠ>üP8ޏOEXÙõIU¡]£öŠÔ–ªJÆÖšf²´[%€pDK–Ù¥ìœä‰í©IQ'…yÁ„МÝtûìã#,*$¨E“éøqÏg>ò`Çã;“}™«0WQF r†·æÅ=ÄIÂÙY áGü¬Y’7EÝÛ×WW6¶ö×]4;º¬ œ¥Qc(PŘR7Åj•BCZ©Sf,¦ òaÚ¥—‰Ss]Ù£–F7‚š€k†m¨’†ÏEüþa°°ØY›(1‰vw’ƸKÊœåöÙ®¼íá÷f‡Ó;È$±Ýª”¾h^^Ô©zÈÞbÐOxjTª/ª; ÝÄÖKÞ¤vé‹éŽŸ6ÜÎ/»W†‰^”D£éP5}º‰:¶’$ÉÚý3Ø`¤âaÁx(aª(Cȉ‰¤ØZשè#*txi¨}_ß÷â;¯«•ób±Ÿ2…2A4<"ÂLméh]v›fúk¬åSéÕû»#,°Oâ>£ê,ÇêÍ^îÜ<ƒôŒ$‰GÏzwéâ#/=“äè·œH¯·u_tå‡×a1´É¥ŠoŸ?¾Ébóbvš)Õ^Îþß^‘nï†3¼3#,-_•„#,º§·ª³¼>'¤‰„";®gЮ:dƒQ*$+‡ØŠdç£SZxH\ÛŠa;*‡ªP½à©$C…ÀÃ/Íñ›¶.¾Ò—¢*ÌulÚk¬¶ØàR;ù}EíĪuçmr1Bô´X<I´äX3h½»[ì—}—±ŠQ¬}_º°b8Už±²FÆÈµÏäÊ´ˆ¾Žu7§#*ĉ¸†Ÿ\L ³)#,\ÕR@—mE„ýg‘¾#,Α9`8™¹±jIÁ#*¤‚;Œá€ÛÏ‘†¢DVeh.‘wmŤ¢‹^9[%¬[Æ*݉ncZ¹¬UÑ£›šÝ-mÓVCX¨µÒÚåd×75«•;½›‘£jJ×ïwâô³º±Zþt·Lm‡eìvÆAÚQ¢á¤º†´Ð»Øùëžµl°0æÌFE.Çm}XÆsö‡ÈÐ߸o"¸5R9 ‘S#*Wë"«š€qH>—ãF$\È@Š))ˆmá¿W»”CñÑñuÐóxPTúàìhøŠ¹þE#*úˆ)©ˆÈÌË’Xø)…M+“º Â#*I0t}¾’î4F4…C#i(I‰D"2Šª»À¸WΑKKªAHÅÁÀdkPL1 «m&¶‹ºÕ«t›#*XDèØäK·#*”™ v÷y5}M›kmøµ¥š£I¬„‰ €‚"üG‰óA°h¨:‚ÿàPOR‚jü"nŠ›s(Ū¬Ð/¸o"FÒ¾FñÇ÷VG–ýR‡Wˆ„ƒGÅTÖÛ›<s~Ëì¶ßÊmlfm&¡M„¶5¤ïó›Ò²#,ädp'QÕ‘_J:¨z^°ÍÐ ==m(TYdÒ>d…á•L¦ÒHK40XÅ¥’´i6,ÐÚ™¢Ôl¥&II6#/mÔ[XÖÔmjm+LªQ£S*m¬[IµšÞ~‹×Ùá[’1ºÃ2"‘hmÉ+‘"q….M¶Â<«)ÈÜaˆP—òpعIQ¼ÐÉ,#/m†ˆ†G”BA´ˆ’™c!0T-"Á‚R"T4ÅÓ†ÄLUÊÂL``bƒ`èÁmˆ6M]Y©ºmn³šÚíZåµ"(U®ÓB‹ä#*’"@¡ŒúÿVv¨Ž<)KH-H4F›»§vbáÚŸ¥]¦õÖêõݚŰ#/#*I#I,f[dZz€åqPÛ]ÚxÜ£8D#'ÊÏÞ:wIÒŸŒ¿Ùëϲ´¹å¢ŠU¯`BB#/ɆùgoîÉ”!h³è×ä8¸Pš8í½õ9;;'Ój—,1Z%ë–¶2iU""†QÑîQ,C4Á¿bU!›5?>œ³‹ÒÓƒ!äÈaAC%[cΘBˆÒ.c‚ŒTKÏü:#/~„z#êEöZÝ}gHQ;šêgvó˼ë·tv–ò˲¦Ò™ú:áé–ÕÍFÚÅ¢ÑmmmrÖË ¶º;«©zÛVòZ¿ºfx‰6jz²K1SÓLðmÔC)XRWÑý:mYÄgëŠGg)öb#,-h#/1"¯›tý‚ á'̇MQ%° Þéô3î—]Ô„¾Ä\ÌX†tÝv{ŸîãÏÚöƺ!žt’¡ÖÏÛÒ¥ÚWWß2ZÏgŒ;mX·ßÏû©–]9!¨EŽY,ëUa7_ŸI[ìkÓ•Îþ}üÞ&úôDNÝŒ:×\•&6RÚÔ›ã¡\ùPVÝï·:uÊÃDΜ¶S’z÷Y#/™ÏëΞÊcC¨Â}ì ’aŽ(%‰3Œ'‚^JRñÕJ‡'Ó¬ô·+>ÎÔ‰Û»¶s!Êî±oãOͳÚ.åâ¡Ä€u_#,öæ3†´d#*ÍzëŌְÁÓ6Û{ÇY*ÌOR͘—Ä.:ã[nÌͧ#,åÜíš3Õñ¬ûjñŠ\Âéès1柮Fgîó†~NnpK(INÇGm"xÓØ N¶ÙùŽ~‚¶ÅÁ⩳J·r°ñÅ Ë4й¥a½5ˆHôW¶5)…dí*#,ªz¿¬\5®YòÔ! ÒñçŠ÷V uÈo1ìÈ2ÝZ dC3¾æø™Ö çñ<*Ö®Â$<¾}#t\Ø£ ÙH„‘öXFF‘àaœ#*tŠE¹#,±]ÐÁÑ8§õÿLzÉÈR9AŵáÉ]Ogmp™éçã¹µÝ|#,®RÀÑór<of}˜lMhŸ”œ<J«ºjÀ…6ò+·EÕx:±`è4zo•…7;$º”‰Æ¬Ö–”ƒbã4¼qkº”!r®èÉ å%IPC®ˆqê=Ãt äBY¿L<-Mš‘ùÖd÷¨Îu,ÙLòçAœxR/ŒV-øÓ†]¢áG0gåÛ¶÷ÓYã´:FÏ3å3¥€ EËTÕÏé%±ÔZ¬á©1¬µŽ#,çKC)%˜½—×¾ÙàòYÞ\Û[ND#/n+š•Åý›í¶-šÆL$ƒ¢fb6߈¸á¯Mo¤NGöwvvnVÓ]‘éXxæâ6¥¥9ŨBzxBI$;¸‹àæyʪͼè±>7µ7@"È#,èð0î ¿ÉµSú,·7¡³fWÑh‰ÓÌ„ášU¹{âlC"´s9•—.ö<W£;/o(Gnk#*û;8‡êãÖ¼k›#˜³.ÒûakÊC;±‡u´'vÚxáÌó¿Ëj=¶ÂÞxëÁÞS”SÉ$ôx34ÑÄsDœiñ/I^Ù¯,bäC‰uòqHrÈg[ZNqEïº+X̘¶È„ŠÌçseSÍ{å9jÜÅj»ÅkB“Õ{‰º£¶ÇhÊcj[KN_ösJ+×å׿–õÑ÷ö`²íÍâàŘæCÎ8-hù*1º}M CÌt9Î#/ª#/ì\[<uFpê¤^Tªc ûÏ ÝÐÄÀ¼àn³àÛãxÉá>—ˆàDz®™×j8:eŸl“Zxô‚%Ýåü¦[gʘwwBÚº¼ª®øºó|m7Të+žz=˜¤ÇvæWlˆ~N×0³ÃÜ»íþphGdÛ®é¤ËƃÛf¼½~§•óäìê½Ö²—^³ñëío\ñà+ÊØD³ŒÃ»Á5Ñóð'®Æƒ"–1±ÖœQØÎ#±ÄÒÊ.&ý‰é\aïX#,³¦#Úr6¥š.@ƒÕßFãv%½…”Ývx—}ØzñП6»hd'(O(im¶æn¼F×ÐŽ4&d¶êK§z¦IáâqÓ}¶5=}tTnœâO‰e3ç½(W;2Å´ƒ|è0¨P;Q®Áài%œa†…Mؤ"Ðt4Ãm®€ÙÁ»‘ºÉîAq<b¥CžÑ—òÄ#,hU6.F>½c¨ŽsJhR:„åqÙ†E°³KeØÏvb»°×(–Nоã¸H:´ã¦{fŠN@í°S#/Ÿõúõ(6+€caP¦ 㿞ú7Jç[%^¶‡gM³=¼ªCf×.h¼01º±Ô`vÞÀj~¶zvë4§Ïüç—Ù:*gw$¶ D;¨©¹‚f¼¦ºgaAKÕ¢X,ЊS7#*"‚‘‚Â*böW£qÂòv*æéÝ]›ôË-ÚXÎÈîè …¥›¤…hÚŽœ³7q•(®ýfµ44z2¸Èl»e‰1¶yL°jÙŽµ9YF£¥Ä™áUíLRg»#Ys¹÷«Ë¾?šëoÈruª‡Ž´’Ž!ˆJRÀ-ÛTÚ5 [û‰»mÃ+Q$•7n|I˜sÐí¨%eØÚ{âØ²øOb ƒ„TûM0"Uò¥Lá7Åh×§Çl‹l!#,Âí<Ki}—ѪåÉo(©¥ÚÝlÂFsbCVÛqkÍÓì¨ø=;…Ú:TPŠ*¦Òˆªššr8㟸vœ‹L…‡×âW\7®œ¡rº.gÄy/,¹Ò_«æ9òÅoC<o>œçÜl&ÒóòàP a‰›ªÆÉåesC\tû0Ùw1¤Ý3ˆjT¥ã º&%°ÄA™§ò8r!E˜ây™ÇP<¯¥ôñMŽ‹¶Åí5Yž(²Óí¦[E7{û¨}u#ÇAÛŒ>ÆøåÎ#,Æ0YVAK_-JR6W;N¸õÇn'¼™6:)!vï@¹#Oé°FëJ®µLŽo‡Þ]±n`C‰ÐDZV#‰X×ÚídSÑcâ+²—:e£¦µ½h1®ýq#/»7,í!Ço^§®g¡²ÅsÆÔûø9šË©ëÉújk/\ÁÛ ¡Ð»®ºË|Pr‚ŸsmuërÒÜzùøÁã¡ÔΆ¦²=o³v2`=w+sÒ_âcU07«¹®+Î]-àË,S^•Ó¼úáõŽÈ[ù(ê§ÍÃD.!/)ëlxÄ–ä§0‡>p™áoÑÒ?NøŒ×Œùr_èõ¼ˆòîûIc TEdg°È•4hø}>M‰MAÑ¥«ÓCï3¦“Ð9ÅÛ#,h«»›³¨þ-#/a2x÷ù…ĬàÁñÁ…@lîœ*"Ú䈀ÅCBkVÀ½MË2*-Ý7=}›ÇSGÉÎOÔwÃ3 yQÌu4éxïl2=Ù©#/‘•WŽïú"[Y!¬*ÃѬ橱òÐ(Cµ{ˆiÀ€˜Î0ª˜aô;¼†&–ÓךÅñUv˜GÍZ j(±Í‰µ¶ðëËr·ëK‹0c8MëESÐcÝܶU#Uu#/†¦ÜTzÓ·0äi¬/#r§ºÕi,ÛsÈ+¼jM‚S&n(3pR;@©z’p€rž"3IÊ£Ù"ºá‰Þ‡†@è8š×bœÂ#*À+ZçE+³+ä`ƒ»ÎÒü#”Ún¬$È%ˆ€>¦ SΞWñ)רnôVf,Š\Så[ˆ„#¬ »~ñ…#/E³î#/ã³%½†?S…ÖÇ"u à‚O7à¼#/ïcg®Ö[mƿհÆ1fýºú¹ÉD¼:ïöR&°Ï Ðy€r2¥¬¬¤’¦º¯Ñ˜X ç¡]@k´z såé—Zt#/y¢o±ÝÊ\Ù£ë+ãÙ˜ØT×öŠ«ô’í¡(ÐIøL=—yÖÒ§³&‡¦ÝÒpC’A10%M–Ä¢ƒT!!aDÚ2HÚ@•dÈ(ÒÇ[š6II´[›^7’w\’JÌÕׯ6»zÍsš½^’©h#*阈¥ˆ ƒ x‰ «PE¨£‚‚Ħíì^Õ#‘@éX,m5€ÔPXPUЉCd±#/,´ FÅ/j‡Fëé~Ó/í5WŽÄ}§bÖL2€t9êׯíñ˜7K\eàd‚¢#Òl(©è4°ÂЖ·#’Æ´ÚÕ¯Û[Em¢ÚÁL„ #*a”’r³DÓ9}kT™Çƃ® ¡¤Õ,mð~ƒÙöÝãÔÕ™e©ÐRßãôбŒc`ÒÅ#/ÝD2†º>œ(ÖŠ«wmkƒPg&ÄËø#,Å1h‘]…2¸™øMO‹7“lTé¸ÃVbã+«†#/RñÚ×ÐK£!#/HRUÐe!Ã)TE|¸ÓâopÇjê›Æ³‘, ,ÊŤÍÐÔq͉¨Òm6–5$RÂ]ÔV6&šcD0€J墣ܔYÈdÛ{‘§„M¶=po™×•Á8ÐhÍàŽB‚Ù7T€²bCš‚Ôxb2Çw.S5—¬2&àiC¡%#/ÄF©Ñ!Óc3aR÷.¢sSFíуMÜU=6µS Ü!µ—IÖÃZº¼âÙη–Vñ“m¤†6X*‘£fäEÓJ#,©¥Ãv¦ÓÑš#&›j#,YÁ¶Ød™ÒZü÷Ƶ:s“³v´ÀXVC3”ﳯ$ÃÁ&´žþonÛÈó»Ét«¬œäÈŒ{±â®±‹W"ˆs#m2‰l4²©½\Êøf•“%+XIwÜ&]J&0gHnÀot†Ú4ë;bµÍ¥"NÁ8Â7N8ë¨ã×gÇ*Lá‘9lw“£4<þlÀ{é1658‚/*N·T!#CLäè†JÇB-£pÊR#/”*à Ѹ)¡ÃHi4ØÄÔ ^5hÛÍÅ·“%ŽºíéÎÃ6¶réñ †@u¨lŠ•®¯4†®®ÖÒj0Ã(ÕYÍ–mÝF?'r%ÆcAÔæNiàÛ}zñ Žã Ó”¿J„FÓDu5OéÊËÜ‘ùÉyTlæWz:DÀšY¦ÆÎ³ŒÇv~i€¤WµßlPË`”¬iªª½–†BŒ„#/Ój²°<#,#hÆi-hœŒÆ¹0ôLÎmª"fæ`éÞÐhÆ>TºwÅFñ†FóHtë4ÛmºÒ æ(¬ÿRV£â¼ÃpÊ(øD#/14”{‘hÂ(ëvSNÐ4Ò1êÀÜ€ù$¯´Ðñ¤‹š$‰ÃÓoÌ¥08âd€ÓZ±™Ù6ôÁ—}X¥d#3»¸HÈmÝ&47,ÍÜhZ#,2j“#*Š…”l› „•5$ÈÄDÚ*‡6‘ð©5Œ;.©PÄ`Íjs¥#,4´ñ˜“C#Q©ùÖbË8ÈÇX3§aÈù…Š,^\Õ²¾LÖìê@^Ç´2ózåÏœªj,DAHŒ£´²î¡ÀÀbm¯™áèõëþü×~×k¢Êd“Y²nŸm«õÙI¾óÄvºÎ±&îM_··Ç÷ï’¡å8#*œ'}ª0O´¾ìÜ,äŸ[ɾÊxÌe¹¼yE€e¾ŸX>ã²@—Í3:ì^އïá¹½½SvFµ4C·#/1²³mlºqáôÄÈ«õ=A_RCÍü@’ïêõ‡èéO¶Š §*×% ¤03‡ÏÃõyÁש‡/0<üSÍc5A8÷wùUc—dî‘€¥8MeøÚÁ#,‚âg¥þùQüú´5 ›fª¥pyr˜gÓy½ÏM¸Þ1µ7tÝÉ„D@täîÝ™ULm=ñ„–;£×è®Ï.CÐ>‰G¤Gh t6aÎèÙY‹h¦¨Ú @Ÿ¯‡Øtøuäc::‡§tò¦ T$hEÍ⢆HvÀC#/ÊE´L—-‰u×[¥^j™M¶ñ¶LmQu×W+NíWuÖ£mNud«DE±A@U"¾"êÀ?¶†³OÓhT'ôqò}<ªúŸÊ+‚‹#*"2aIZØlcHFHÄL”i¢i(Z¦VÂkɰ[V)(ª$¬‘†3eE¢‘–…4Ù&”›%(¦Q *#CZ#/‰H–ŒÅ3E)¤R©FÉ0Û6a”$˜ÖÚH5ypé<åy¦£°ätPÈ_dN0=¼çc9n?$Ü/³eÍöï~g'Q¯ó"HH3‡p‡¡<~~—Æ^Ó—Ç%A÷8$´R8 ¸ÌP¨PÃè0/Z£†Y.#/²ÄLl^ì&>bm¿0C”m{Y²M+N${fkC"`Íq>:Ÿ…é¶í°AÚ—~Gy A$H¬&½»—ÀÈ8Ší:¶ö+‡I F"ÆÀå…U1w.üO¯£Ë0÷jêÏGl`^ª5MHm)ÞT¯¯…мÑI“7¨ôÑdÆ+00#/Ú?¨¨Á¿j5Q&Ûb©DmIkEuª×+/ÕÝnUÔ)51c>»ªæ2¼–š…ÊPJ¤}ibÒEŠÃ€À¸dË#/E…J!ì–~ݳAKQŸ¦å.¸ßÐÍ¡‹>mŒÄG©m@Û1q?º5[cJ¸º<j*(àÉZSR•[(ñ@Ùƒ’#,‚*!wNRš›¡`€(dX±Þ'’#*± ¬XëàÕhÇMî¼™gg+ÛÎ×—;F2•Ñšö•å%ãrÉ6ºíÚ Ópó/ÙËTÜ’ÑpyŒ ¼£ížq¦V‘®Q*Ú”¨'QÕFÌ„Îg›Òyè4%CÕ/3kš¾¦ýM£G½y«¾=À×:í¶û—®¼‡;”Ú6ù5»cM60ŒDlcŒHàÑ…Ÿ×yÀ‘xjpØŒòu·u#ªDèã‹i4Øóôê#˜Þ(È¢'DÍ! xCÂc êG˜Æô’ŒRÉÖØYU&Bà&&€X‚A‘ ™Xš–È,C“1—’D’I"s¸*‡KPõr¾ù0§B‚i¢`#JWÛ¢ZkXHª×§µ²ž‡òcn;ò;HVìûàNîîCÑV?ÙP÷´LGÃO‚1L~ÜãõdS!»HÏ(0¯x–gq7˂۲“ÓÚ@AÉùœÂu' ›Ð²JªAƒ¿››°d=…,’–’áŒ3Ê‚t‚&ž!ž~b!ï>3'†ý…Y5‘X»¾ª-xýšéû7¹ŠÑéwŒdÅgãá匪(ßoàÑ$#lç„÷÷`Gæ¿#*¢:ïÄi1#/šCKè.󅶤‰èý€ ›Oó4D}ô~‘EAI(>E²P™åBÝ´¢R¹ºC6Ó&T6#,š"J‹Av">èn}®¸#ÎÓ˜eªÐ‹êôž»¨›FuÕ~Ú¿î—Ôú³0NÐãcÔ)¥®l«¼ç¾ª2(B°]êË>TT·ÀdfêAiH2ˆH-H£ÈèÔXwiÇi<eº»äÐú½I7®Ð6¢j̨æïõ)‘’øB‘E¤÷T¶›–Qï8vþ‰›õž†9Aƒqb¥¤L½#/,ƒäÖö°[#,ÒÙ£@¨ï÷üü@“/q¥‰8#/±çˆÐqÂw´-7Òb»eRj93>þ©§º Q<:ÇàôÅ"2@Db`ÓíB÷ømEä̾×ðû7ÁDƒƒh>'ÂÃßc¦Ï§ãûláò×9¦%Éõºgá÷FÍqØéÍAªé¢Ä`C$Smn¬Éë#*;NÔèÖ{Òw‚dd5î`\ÀðdåÞ¸"#*ƒS›±ñÞ#,ÌåT˜H%ó¿h¯—>ÚÝM;½í/—QD9äÊðìk#/¼ûáÜãXëÆòFtd,kRÇ£œ”ˆm²YÜõ†ÞÆÙÞD^ñeyz>âª4"RØÃ“u´*é™ákYÔÏhg6UWXu…°ÓAI …")#,—[Þ˜–„©#_C+6‚Üdÿš TTZ'L‰0ß#å4w.äÖhßL 8Æc7)•%0æ™âV*TÌ€2N$oJf(n’ÐQÖBâ¢öˆZãfùÍ#, G:‰æm €.jhÎÎgõ,ÌÙõ³r#,£Å°ÆÈ”ãi8€ÔdÚ,K·Ÿ•<ÎÊ ô˜NØFzcf¶a¹êµëeœ“’Ct<’Á5åB`°’&”ÒÂ#*k#/#,ãð0¨J@bf¨F›ìR42´*ò‘>œ^#,“a†p#*Q#/°Ü†Ú¼Œ´*=i{µ…Š˜ˆT)"©¸PÁž¶¿mSð€˜Àcb°wïÒg®»rqBëJ¶˜hbæ^X@z‡H²™©˜W¡ÆtÊb@ô§(zO/kÙÃ9÷PøéƒFŒrv¡ŸZ¸v“-€¥+x¸0‹d&F955:fbZH¨™@œ“²Îؼ~>_î—²Þù‰mmS×L¦g:uqÑ€vXpI—Û²“,™¯Ná¿$ŒrÊoµH•ìÖÄ¥eÀ–xðžÞüp"±Ž Ñ#,Ê‘ZCCbDVÜ4%b Y1Še¤/BV²`’æAZ"ª”q'y˜å•°^ÀW¥™”ŒöÝaš•˜ó#º·KAv÷†=ëy£ÓŠËÁtá0%ÌoF1ÙÒP創ªŽÒ<Ê–27×1çKeh#,bì¢Ç-Nã¯w¥ƒ*#,^kß,<Ê0há‡~Y´ï\Æ`ÚÙêÀGsjs&´…!ßH’Út˜m*XeaLà>‡ªKK{;¤ÌI©0¶Ûm,ÅÉR=s§“™iIeó»K'Ðôå±ç¶#,Œ’úŒ‰Í.IˆfáÛpÞQ{HhM)ïjºlCl‚oO‚ݶةhw%„^Ì Õ-²šu8‚Çd;KÙ.žõeÖψ[m0Zu-eÄ¡ÑJV ‹—Mýš’-º»c¼Ägg…8!9Àû#/UóÚ$T°CóÃÆÖçšaU»ÆD<DC$–Ê0ëN“ŠŽ,9ï4`>ƒ’γܶhÄ\2y”ÖgÛ2F\BÅ>þ´xXX½q-BÕuS(yÄ×^ŒNí¼'×Xªñs&âiÒtîJ¥k޵#/µ‘eP#(k—„+r¹Ã•U[^0V$#/˜ké&õ`I’¥G@8…ºŸL½(‡"ß‘kgÌ•šfÚj2n#/)öZZXRZ:.îåÀ÷Œ=õŒ¢÷è"2pk“*Ð"ª}*eÇÄÂfÁÐ7§mÌtàÏÀpûõÇ~3·9B.ñ!ÁÉxuÏ8[sdÝ8|°P8o¡nI\DøéøË¸Dp8o¬#/®½4i²5çRŠu#*Å8¤Ú¤<Ì@# c,²Ä´lÀV"„*0aª:³M±@9ÒÆµ¥Ëˆ{ Ý-$]ÒA!'>wÂŽ¶³¬×a^pÛÞÌÚÖc4/_L|œÊvÔ`óñãó\ó†4æÏ:äa4µ‘ÏY¢ºÙÞPìÓR3Cj¦:ØÖ+.™&.×Û®¼uÞ…ÒÜ)UÁ9M(è=JdÝ9$Ÿ§_çøÊ4øm9§M¡KÙÃùæ¤ý=4sÚ·ÝÐ>ÁPb@P“sexÑÝÝGÀuóXxë§‘65;ŽSã? TÔÚ‡ÓŸ,Ì‹ž“Sz_.B=±É5Sœ<’GÁ,-&jeJÁ³†pѼ˜,LŽˆHd–°å Š–›lìþw¦”úmDÓÀª²¥È,PÐö.&Çã_—MÑ l:0‰Ñ¡V‘A ßJ,y#,Žš¡BPtžlÆ\bäù1)’ø½›¹mÒú5eaFUYK·Wiêö¡˜K#/œò±ÍSõÂv"roÏ6Ožç4e;Ñ@L4ÀÓH§ˆªÓ˜6ã‹ÑŽÂhÙ9’‡hôZbmÙ4ÐÖPå½1¼¶çu ^& w0¶YÆ¢/LÜÌÕ„Rï;&m¦ž ®íxnòfœ‰]-Êåë#,Ì#*ük4Ò&§n½§«¨&³[T¶¥‡O]nN2AË«&Ý«&šoÆBÃGåÐË®‘M3w†ÙqX‚ùaÒ7ˆâD²žwd,á´K D#,U)[ÛŽû‘Ö$„ƒ@tG¶.M"]Ĺ5vmM"ÐjvÓI13?~HâÓáÛ#,µ"GÁ†žjWF/#/#,K4m Šæ©CU&Æ;À÷nÀ’øY‡^IF#*¬áÍ0Qds°0bšøP›Ã|1‹šÆá®–ÄA `Œ‚ÜЕa¨»5IBkØfM7L¡ ŽAŒCN‚-.N³03'ÓðòäÇ—vk¡¼gt;Ï{’Œ¬•&ᣙbª%#*˜8é’°¡qŶfj61AHP¥)K‚ÀIŽ4o‰ÝÌÌèÙØ«ÝİѵŠÛXMd9”°ÚD¸q43‰1‹¡P,pĨo¿…Xä$#V’2®[läÀM£”‚1`ºSFΦ‘ÝBFÖêJ€l#/.hE€Æ®•Õ)1⡘”4Eß#/psÏ{¸ãàÄF l4Ðä3tÃD²Å°œ V°†v6ª0*ÂÛ1¤T°ÎÐÑQdn 1*‚†ýy>^w²Äsìp 芃(¢¢"€É]¹Ï»^Šš×vZ¯çë“Ô7#,?w5Š ÂÑv","B@#/‹ kP´UC (#*¶ß€ãVz 9‘—:郸¨\€q#,¯ŠÎ+Ht_¯æ¦ê–Òü¸ßL…*ŽH†v_¨²˜Ò‘6Qš¶ATA³/°Ú»ÀœÏ–fqÏyy,37êi1ÔyMŽ)ôX#,&A¸Ñ)õWVª”©±—fM†g;» k—d \¨C9È×óK5òíé]yë«’ªŸU¨‹ú ›£ g.e+ÙH¬ˆ¼‰¾¤9_®°—ªd ¢‘†’œ)7‡vpÒÆˆ?–Ýé¦NÁ¡o\I}×,±Þ\©‡+,YÄL"«U?,“LwA™)å+H¾’&™2wäívÇÜÄsVš<º;ÛGìsuÔˆpœa€Í#*µ+öÄC”¸Ù}5S±n‰^Fãs¯mÍkÞç¬Örâ(².nôÎ7ßVeŸ9•s> (A=´`ˇà|Ôè9e¾Dʳ9ß^Ø¢{¢#*ÙöÁ¾ë¡¿78ÃVH'Ö@H3‚5RE<Råj4S‰Á‘!&}Ç…}çlÜÌc¶êà;IZ0i(ÚcHQ;d‹^“!2Jf¼KNñ¹5æîÑš‘]ço^p•éÓÕÒ¹q&8å ÔrK0Ä$(,ƒM4¬´[Êšõ<õºæIK³[n·¶àÛPÒI=ðÏ®,ੲ¥=+K8Ö\†¸í„òàifní5aÅÑŠÌÌÑÔ«3I8…`È2!ñ)†Ç èìíÏ·¿ÌøÃ'†{‘#/Gè€ôÁQìG´6›Œàþf¡$Y9)“çµ¶ŠªŒ@ˆ4:HñÜÂÛ‚#,¡]’&!’˜W‡Ä:o‡(nB¥šë"h¶#/:x‰A¼ ==6 ÌåÄ’ÞÇb<YiÞöÇqœð±Ûñ‡ù¬!êÛÏÊ+uw}•.=~¤žŒÎ‡D‹ú²ní:˜uŸ¬Ù4(PøNk±ƒ·e†Dâ¼äÔã#,T#NþìLɦ•—`píݨÕrd.0)2å“-ö&§æÊ™“n±“w,7¸ù ( ›XMÔ " íŠ2Š>õ¶õÑÖ¢šº±«ŠðIAtÀ¹¡´æQ4pÌ|l¤µE—-"1ÓËÍŒ6‚ò@61ý;}¿K4Úb©¬DõÐR?i¬ã†tÈkÔÒŒ™Ò²iw#,öž ?6PŠ ¿T%R+~¥mÛf[M$¢±l)FM¶Mi•÷f²[^š×,0•*(¸ ¬ 04ˆ‰r#iQRö0YV¢È‹d‚·HŽˆD€°B&h¯LPw($öeèÊŠ•!tËþŒ#*ìTCg†U·¸ÔÀêûlÎ,"`ÈŒŠÀ#/B#*ê½ü|9|_ §Ø¦¥AR†ü.ã0Ô,¢²2Œ‚¯;~{ƒVúÃñצvž¨ãžÏ,kŽ[·Xé#,âèшÍÁ±CÖ<yÖ•ÄêÉ©î$高µÌbΚˆJ)c€p0dX„F‰šBJ#,…j\¤j±D€(ÈÙ\Mp¨‘2YM1:ŒJ±ªÀ²Ó.[jå/[dÚ®ÎÊéWVܼݮ´U<ÜFÛªMkh¢é\@ë9·œ¸oÓdVm6ð¶À8`•ÍU⥅ 72,Às4µ§Ü€=ÁÔñ=<^Ia 1V=¼ý¾êfnNf0šƒ*Ì‚BšÃzÖL‰_\lÜ3ÄžHLë¡ÓÌ;ç›.ƒ¹Ü@ä%‰#* Åó@V‹ºrÙ˜oôÔ%ß2ɢϊ¢Íô0€öP$Yu©%!((ŽY!C4ãRØ/¶ÔQ†ÿ17w´ð›,@#*-„n¨äBŠIóüš¨ù’c–ÁÆ÷€ü ÇÇNƒ|0V!<ÇAD¹ã;04U×;‚‹RIA@ ZlTj"¥xŠíêÌJL°XéùoÄ,%Øþ¾XÀÖÕ—Žvq1úÌÎDßZ#,Šó÷Õ›žGêù@ý ö¢€àpŠÒXb’ ÒS*œ9ÙO߸An‚¹ë9BPR:¤Iû›OR|0§{Áà{ %àåãròI¦³m¢™´š’•K*™1¶%(eªØÕ˜k ¡6Vb«IWð4V®3˜¢2$€ÅŠWž „tó'¦8±UÑ‘ <¶#aà¢N¾™¿Ï59¡¢Þt!¨Ý—GVƒÔ íX!°M¼°îÈ#*‘ #*0}ÑÑŸ28O¯5Kxléön¤œùÚ*‡Á´OYﺂb ª#*¨íbü3×Ó $:N~;øÅ½õøv–õ×¹7Àk>½f9”¸^Œ2j•h«Íø½>nÏí©Èk ‰ÛDÕ3£vwwHƒraÛ… joJÜPmÈ‘«%—rX>tDÙA«”á ðÑÇH³¤1D’WÎÂ#«ãzÖÄ&‡¤%ÃÐÖ`A•XQ[ÔíÇ1ÂI›`@éi“BJZ·ÅXâÜ ˆÁ¨kÊÄYK’hHM…í£¶RÀÓm©Õ“‚p6¡ÈAH#* ®#…¹CyBUË(nCMdÍ5¡lˆ˜.éÚîôENzé ! ;BÖ‹Fˆƒè2²¹J5 ßäh`}OF´·ZÓ„¿9`3ù“d]S“æX¸@5$×Ûèz”²Yî+¡gwB0T¡W¾ÝÿE êcDR1‚M:î?h*{;!â‚øxxi&;ˆ!¸ Š#CG4U&ç„z.–7ü#Z|<å#*^þó³Öw†#/¶*y25Päx(Î+4S(•ñêöù‚ß{aˆP”•¤TÄ–÷ê}{~yõO·õô2tª“;@-œk4©#/S°ÛBáÞ—g?œœû5fÆÛj±¸”1ŒSfµË<gï?“‡¿wÓÃÛ¹TD*b!p"7søäмÀ¤÷€Ovî»ú.óRtjû;[u\#,›DÔ<€ÀP¸öÒY³^óüô5Ôícš÷y‚çOÞHX´.…>Q´þ;Xˆ«¨vÅ•x(ôÓk, N½ÚÓk5ý”Þ¯«`Hd£3=uÔFÄhÒnuÝrF$Š"ÁJ.*(KHS>bSv\—Š¥ÛNRQ´¥”a¤6ŒQònÚ,äl–5 µ&Ò!.n’K&Æ”A#¿ …G´ýiÚ$Z†âÛ¶}^ãÃÆQAEWȯ¶Ç‘‚ög¬< +5L'œÓé} §¤çÔ__áb,–Òj•f6”²Ú È‚#,Á|#,ÃÔ‚tÈ„„,HTjR66!K2U6üý¯Ñù‘Q¾ö«é¿‘†‘hÄØØj™¶*Åe)RªyÀ>^®üfDEØ4aú#*ˆšþÈJZá¾{‰™…"ò!’žLâ™Á5$`äNPd2Ò5EEŒScXZÊØ¢ØÙ‘‹c+M(¶h1=7ÚMµ "@ˆg —€„^§ù å~‘TØ»ü:ÝAçú~ùw_q$ð#*ñ½aÅ£'¼}›êÙS^eMW!aWÛ²’b|á˜7‡`á"F=¡«Á®´-ÌQÓI޽¨¾'¥Ï¢}´ÕxÛô^öT©mŠ6ûÎWö3û¿:$Š›ò]ìö)0ï €PÞÈPŒXD#,ÃùPÞ›:5ñö`-1¶ ØõªlúrAÎÈ™ )îZ€B„‚ô#/&» ‹çÑ·›Ö¸¦µ&®nª‰kIe¦u6W¾íå1¯V1!s[}6yNÍAþ$6PF…`65‘/*4øÐ #4ˆÈf÷Ø¿M¼¿4~iÑ󬌘eë„ÝáË^ *I¯Ni`MÄÆhvø([;3‰iHÚy—ËíÈ+«`šŸ”"MÎ%«YkfJ8Ô™§óÑñEËz¯‹{SßÎãÿm$sÒÄ}²fh‡ä#,At±Ì~oÀE#/A(óóm¾Y}¼nÉAªY¦•$%"£-ŒTPj#j“j…-û[oµ«ÆV©1‚¬Š 0ˆÏó§³¶ÎÙf„‘¸’)THÂmB®¯À.mˆ±„^q°ˆš6™²AòvîC¨T#,úÀ=ŒúãžõÛ²ô;®:‘Hÿ`‘W–ѪŒmAjPª4&Úl±±V£)k6¿n¿!Ã=:›üݽ´ªË%$å5öãùYõB†@ÇEõ9ÆÚûÚk‹ox„‘µ%)”p‹,*²Ä¿Hð7;ç‘V"´¥·÷žIdní™bJ8,,ŒN(&xݬlÁÉÑUÿ³²¨ØØÀ;!…^X¯:×Mãò[¬Òjh¥KzÍ…vÓ»6»»+ƼÞVº¦Ñd¶ôÖ䨷›ºÊnÌÊ®¹»j*çjl™e«Ë»i“k»«»µ²l©*dJlÚCE„ˆ#/1rR,$0uyvºr¯"o%¶a¦õåÄUJilš“*UéZê×AEÝ@…°‹$AÆ ‰#/$R×®î[µÝºË[.šé+‚"g\6<Õ0(ѯhFÑöÕÊ6'î%øI7øƒqd8о4d-‘QŠ ™’1À*ˆ’þ:"9‡ôokÌÜ1Ãp¯àbÛM$CFÔI7œb€ÃP8ÀÝã³ÄÞÜíuêÓªæ‹r1îEÛün_¶à†Ô‹˜Ñ|JžÏ—|óoŠvpáŒ#/fo‰¬7 ƒ•)·uF±±êÜn%Ä…»ñãÁöþ¢Ó#cÔ‰¡ª©S‹¥ñ:3¬[À¦³M4ÀeÂßg‘™‡®B†vÇœA$QGÊ)‰Ä¼.#,õêLqá)Ñ®b~l"‹±$H;Ø`ȵR]@ÝÒbz}7˜º²"îü‹ïÊIy#*ˆ;r¿Õô:}ÒV]×J“×[Ø7ëM#/ØvòÜÄÜï´G#†˜G¼‰4û}áÄÏY5y7jÀùE’ hŠTp7ÃmuS©ï5ps.1û§¬–[!P?s°ì\ø0†”2|З~¥~ÈfÒHý´V0Ô䎦蔤OTê>Ä¢qfª›”ÈÙAJÒu2Ø*Ø„Ïq!¥µQ{†´Ìö'X›GS„½ºÙ€Bˆé†G%±Žß!®ÔÙ´“¦¬RòÒ4S*M¢¯â”¦h"QQ‹V!¥pýÓ‰«Îùçž_æJÉv˜ÑÑÉ#±U¬mœáÖA.îqµÿ/£˜m‘^hΙ-S¬ÔgÌÑÐB»{œ'9—[ýô!D¹kšgÏ2Žë-“=Vmá6[dS)„Õ#C“÷$ ¶""³=ÕvÎÖ߯[$“…ŒGX ÒÿXÕûê«À0ÚˆŒ‹G¡[eopŠ®¾)ã¾”(‡ÜØç#*p0a9QõdìJgÜO*Óc4ÃŽ˜v+iã#,nlA‚rËCzY”Ê-4\Ž!!Òx£–»ò“pú™²À’˜ccò4s·ŠÛYø€…cïIÊÁ##Üj/´yÒq^’ E0{ag3´òöèd@Þæe¼§²Q½Vü½ä;¾ÿmµ`4Ö%k¤ûlî<b”º(‰>Üà„Ð?#,_Àx€ÈA6Ídméˆ,¤Aê#*kßÀ|ÖY…<ò^õ”€„qqÝ3æÏ·[ù¤üw¿NÝ€|‘eyô5 lT&¯×aVÑgöÿèÿåÿwýÿüÚ¿øÿÏÿý¿Ãþ¯ùÿøÿŸþ#,–]ÿòéÿ·þ?ñÿÏþûðúýßFñú>Oÿ??ÓÙùÿãü¼ŸþïòÿÿÏû¿·ü¿û¿þ_ôù9Oý=/‡ýßóéÿ§ÿîíþÿŸþ}ý?WÝöSæPû~dÀüCðˆóð?*&J^!d$Ì«‡ötФ#¼…AÜD¢#*áÁª`ñ”ÄJÕ‘q?èdÐ'÷$‚¨¨CCtºŒþ£þ@ž©îëHfgÕóÚ›kð*ºÄ¢9g\„‚=Zí.Í6ˆk3’BšÌAÄFÙ`þ‹<8ÞÊàY:Çü7ïÚ™›Jš¡ý‚Û¡âÄG«ûÉî‹þ´c¢FG¸Å.f;k·½î?Ñ[›°TŸóNXs‘Œ÷rûm1¬öæS¬€½ z®#,E˜£ëý¸ÏV¸ÿ|úŽÙÔŸéðŽg¹gõ_Ï1x·¸QCâUË*À†˜ ÁþëJ’”X.–H‰&RHCD$wû1ýPÜ'ƒCŽ o÷µ‹ž=ÿKáaN–&„Ìs+j²3Á[3?Úâí,{R¦¤ˆo½)žz\L¢ŒÒë!TøÞÕn(ÎJ‡—šW#,ÂŽO݃FÈ8žõ‹ï‡Ž½¹˜ø¢3Á´¥RreºpÐÒðe–%²ØÁª%ƒ”>m=³z*(íZ¦Ãn:.k,°F™ Õʉš–6‚XŒb‰bµÒa!&aÅåGÊY°²]É`Ë«vL„“‘•MŰ×Â!bàÞŠFîîÝ4A#,hÆó)¥&%aËÞÖKF5n¡ðCA§×\ÆQê™°›=NŽîì6P®"”Å’#.H²F#¹yÛÈÌ1—CŸ®ù Û‰™ùåžN~‚¶y”ë³y.‚u§HØÑ®Á’À¡ w!†<±DÎ-sÐõŸëVvú¨áç‹À@ºõ›5NØ–ºµš©ŠïIdÁ:1b‘q#‚êðÂ]ÂŽ3d0UÊñóöû¡¿ªp»kÈÁUE¤™åt#,ãû}<¾ïÖGñ#,/•íNÃ4DTdôÅ#*ŒP¤ÆÜ»ºàÔÛu—Àˆ9™BFA5íwK†Ç54ÿxÒ–#/€ø H!.wwz<ǯ°LÍ]Ölk’„‰D†½C)—˜Pߟ N¥.$ 壯åÄfgßÿœM&†a~«FN½Æ|®îÛ"ˆ°"aŸ=¶t5hl-ßÓZÄé`Ôj$ ª@”Lh¡xÜME(mA¶6Ô²fÛE²V2F’aF2#/šúnÚ»m¶ø|:Õº"xióù#/‹œüHýqURÔU¼à Š#/[N‡´ 2âS@FHÀØ)ÑÒ5áõ~“Ig·¶‹Á~¹|-p~™Æ¸˜§B¶?ðãS9>#óò_ª’"ŒøˆuÁ0W^ÎŽßðÉËå’´]Lô¢aͲ6r]ÔCã#/¿÷OòÂ>‚'Ëû}à ÝÇZBwn.7ÅPJâ„›‚t€;35v礀uÙÅ+,mD2€HÎΕ=ÛCéÓËmO˜ÏFœè‰óÔnñó˜Ú”6aƒ(idÇj¾V&è#,³QÄVa~Ú-€Ÿu›w…,øÍÁ [¢²ZûºWØf%¤ßÝršÑ¢ß·Í»,kx´[ëkš’±ô5]5£Å¶ôÑ«ÙjÞ¦µ&Å Ö¯|Ö¹h4Â’ O?fóL4ë'elÖæôP8LÉá¡5EiMŒþZéÖÜÿÎPÇõ‚s’)ÝD#,Ç{£V.xŽ¿$&Z÷øð7‰gÔ=ñ1^׿^í©ë¥£€P\‚wÚt‡¢ýÑPh5É@$gY¼ti¡oøý“¿Ãì”têzUÞ¡©ö‡1|¡u?±€Qn*u>SR?ûb«¬#*P ˆ"A‘gMr=8m»¶¹²Ú²[i™®Ýµ]–¯’Å6jM{^Õ~‰mH¡(9#Þ{;>¿–šÈ¶|ÄÕ„éÝïOz/§£îùºiÚf_-?{Öq2c®k$Šz¢|eˆ2Ýø‡åÿ¹Cóm½ÿÞçû·…JÐx^'Å$‚ÀYÿŸd#/B#/ÿÚ%MdÃßû©ÿqÿã#*H*ž°C.¾¿ü'g/ýí£ÿ˜\‡ùòeÐpØ,òÅh?ññ‡þ_îm~…ú|Þÿ±ØiæÐìŽ\Ä<éwtzñã‡mø½N0ØzK½þž#;â3Þ8×ÿ-§×æ:ÿî2ð¤ý1ûˆ—ŽQH@ü¿ò¥ßï—ùX2)Á†É“øÙïóÚkÿ޶wmá‹p¡]DÝ«þ^Á¿#*Ê =þfb~-`†¸©q$ B߯¥øhµœ•ÛÄ⨊gßf«…ÆY̘wÈânÓ§m3 ÊÊÇòç,Má†/-„±¿Ñ8¨–¼§0aw<~_o,Áм²L¸ÙB·9Á—††Š$\ 0Zpá¬8Cè Ãr†¾‚§@ùdyòöΰM…Mð„vE½Rh{Ìx¶’HÀ„œÃ‹×³g«gìÿ™¦çñ?oê5~oÛÿ‹¹"œ(Hní±€ +#<== diff --git a/.gitignore b/waflib/.gitignore index 8d35cb3..8d35cb3 100644 --- a/.gitignore +++ b/waflib/.gitignore diff --git a/Build.py b/waflib/Build.py index 1afcba6..1afcba6 100644 --- a/Build.py +++ b/waflib/Build.py diff --git a/waflib/COPYING b/waflib/COPYING new file mode 100644 index 0000000..a4147d2 --- /dev/null +++ b/waflib/COPYING @@ -0,0 +1,25 @@ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/ConfigSet.py b/waflib/ConfigSet.py index b300bb5..b300bb5 100644 --- a/ConfigSet.py +++ b/waflib/ConfigSet.py diff --git a/Configure.py b/waflib/Configure.py index d0a4793..d0a4793 100644 --- a/Configure.py +++ b/waflib/Configure.py diff --git a/Context.py b/waflib/Context.py index bb47c92..bb47c92 100644 --- a/Context.py +++ b/waflib/Context.py diff --git a/Errors.py b/waflib/Errors.py index bf75c1b..bf75c1b 100644 --- a/Errors.py +++ b/waflib/Errors.py diff --git a/Options.py b/waflib/Options.py index ad802d4..ad802d4 100644 --- a/Options.py +++ b/waflib/Options.py diff --git a/README.md b/waflib/README.md index c5361b9..c5361b9 100644 --- a/README.md +++ b/waflib/README.md diff --git a/Runner.py b/waflib/Runner.py index 261084d..261084d 100644 --- a/Runner.py +++ b/waflib/Runner.py diff --git a/Scripting.py b/waflib/Scripting.py index 749d4f2..749d4f2 100644 --- a/Scripting.py +++ b/waflib/Scripting.py diff --git a/TaskGen.py b/waflib/TaskGen.py index a74e643..a74e643 100644 --- a/TaskGen.py +++ b/waflib/TaskGen.py diff --git a/Tools/__init__.py b/waflib/Tools/__init__.py index 079df35..079df35 100644 --- a/Tools/__init__.py +++ b/waflib/Tools/__init__.py diff --git a/Tools/ar.py b/waflib/Tools/ar.py index b39b645..b39b645 100644 --- a/Tools/ar.py +++ b/waflib/Tools/ar.py diff --git a/Tools/asm.py b/waflib/Tools/asm.py index b6f26fb..b6f26fb 100644 --- a/Tools/asm.py +++ b/waflib/Tools/asm.py diff --git a/Tools/bison.py b/waflib/Tools/bison.py index eef56dc..eef56dc 100644 --- a/Tools/bison.py +++ b/waflib/Tools/bison.py diff --git a/Tools/c.py b/waflib/Tools/c.py index effd6b6..effd6b6 100644 --- a/Tools/c.py +++ b/waflib/Tools/c.py diff --git a/Tools/c_aliases.py b/waflib/Tools/c_aliases.py index c9d5369..c9d5369 100644 --- a/Tools/c_aliases.py +++ b/waflib/Tools/c_aliases.py diff --git a/Tools/c_config.py b/waflib/Tools/c_config.py index d2b3c0d..d2b3c0d 100644 --- a/Tools/c_config.py +++ b/waflib/Tools/c_config.py diff --git a/Tools/c_osx.py b/waflib/Tools/c_osx.py index f70b128..f70b128 100644 --- a/Tools/c_osx.py +++ b/waflib/Tools/c_osx.py diff --git a/Tools/c_preproc.py b/waflib/Tools/c_preproc.py index 7e04b4a..7e04b4a 100644 --- a/Tools/c_preproc.py +++ b/waflib/Tools/c_preproc.py diff --git a/Tools/c_tests.py b/waflib/Tools/c_tests.py index f858df5..f858df5 100644 --- a/Tools/c_tests.py +++ b/waflib/Tools/c_tests.py diff --git a/Tools/ccroot.py b/waflib/Tools/ccroot.py index cfef8bf..cfef8bf 100644 --- a/Tools/ccroot.py +++ b/waflib/Tools/ccroot.py diff --git a/Tools/clang.py b/waflib/Tools/clang.py index 3828e39..3828e39 100644 --- a/Tools/clang.py +++ b/waflib/Tools/clang.py diff --git a/Tools/clangxx.py b/waflib/Tools/clangxx.py index 152013c..152013c 100644 --- a/Tools/clangxx.py +++ b/waflib/Tools/clangxx.py diff --git a/Tools/compiler_c.py b/waflib/Tools/compiler_c.py index 2dba3f8..2dba3f8 100644 --- a/Tools/compiler_c.py +++ b/waflib/Tools/compiler_c.py diff --git a/Tools/compiler_cxx.py b/waflib/Tools/compiler_cxx.py index 1af65a2..1af65a2 100644 --- a/Tools/compiler_cxx.py +++ b/waflib/Tools/compiler_cxx.py diff --git a/Tools/compiler_d.py b/waflib/Tools/compiler_d.py index 43bb1f6..43bb1f6 100644 --- a/Tools/compiler_d.py +++ b/waflib/Tools/compiler_d.py diff --git a/Tools/compiler_fc.py b/waflib/Tools/compiler_fc.py index 96b58e7..96b58e7 100644 --- a/Tools/compiler_fc.py +++ b/waflib/Tools/compiler_fc.py diff --git a/Tools/cs.py b/waflib/Tools/cs.py index aecca6d..aecca6d 100644 --- a/Tools/cs.py +++ b/waflib/Tools/cs.py diff --git a/Tools/cxx.py b/waflib/Tools/cxx.py index 194fad7..194fad7 100644 --- a/Tools/cxx.py +++ b/waflib/Tools/cxx.py diff --git a/Tools/d.py b/waflib/Tools/d.py index e4cf73b..e4cf73b 100644 --- a/Tools/d.py +++ b/waflib/Tools/d.py diff --git a/Tools/d_config.py b/waflib/Tools/d_config.py index 6637556..6637556 100644 --- a/Tools/d_config.py +++ b/waflib/Tools/d_config.py diff --git a/Tools/d_scan.py b/waflib/Tools/d_scan.py index 14c6c31..14c6c31 100644 --- a/Tools/d_scan.py +++ b/waflib/Tools/d_scan.py diff --git a/Tools/dbus.py b/waflib/Tools/dbus.py index d520f1c..d520f1c 100644 --- a/Tools/dbus.py +++ b/waflib/Tools/dbus.py diff --git a/Tools/dmd.py b/waflib/Tools/dmd.py index 8917ca1..8917ca1 100644 --- a/Tools/dmd.py +++ b/waflib/Tools/dmd.py diff --git a/Tools/errcheck.py b/waflib/Tools/errcheck.py index de8d75a..de8d75a 100644 --- a/Tools/errcheck.py +++ b/waflib/Tools/errcheck.py diff --git a/Tools/fc.py b/waflib/Tools/fc.py index d9e8d8c..d9e8d8c 100644 --- a/Tools/fc.py +++ b/waflib/Tools/fc.py diff --git a/Tools/fc_config.py b/waflib/Tools/fc_config.py index 222f3a5..222f3a5 100644 --- a/Tools/fc_config.py +++ b/waflib/Tools/fc_config.py diff --git a/Tools/fc_scan.py b/waflib/Tools/fc_scan.py index 12cb0fc..12cb0fc 100644 --- a/Tools/fc_scan.py +++ b/waflib/Tools/fc_scan.py diff --git a/Tools/flex.py b/waflib/Tools/flex.py index 2256657..2256657 100644 --- a/Tools/flex.py +++ b/waflib/Tools/flex.py diff --git a/Tools/g95.py b/waflib/Tools/g95.py index f69ba4f..f69ba4f 100644 --- a/Tools/g95.py +++ b/waflib/Tools/g95.py diff --git a/Tools/gas.py b/waflib/Tools/gas.py index 77afed7..77afed7 100644 --- a/Tools/gas.py +++ b/waflib/Tools/gas.py diff --git a/Tools/gcc.py b/waflib/Tools/gcc.py index acdd473..acdd473 100644 --- a/Tools/gcc.py +++ b/waflib/Tools/gcc.py diff --git a/Tools/gdc.py b/waflib/Tools/gdc.py index d89a66d..d89a66d 100644 --- a/Tools/gdc.py +++ b/waflib/Tools/gdc.py diff --git a/Tools/gfortran.py b/waflib/Tools/gfortran.py index 1050667..1050667 100644 --- a/Tools/gfortran.py +++ b/waflib/Tools/gfortran.py diff --git a/Tools/glib2.py b/waflib/Tools/glib2.py index 949fe37..949fe37 100644 --- a/Tools/glib2.py +++ b/waflib/Tools/glib2.py diff --git a/Tools/gnu_dirs.py b/waflib/Tools/gnu_dirs.py index 2847071..2847071 100644 --- a/Tools/gnu_dirs.py +++ b/waflib/Tools/gnu_dirs.py diff --git a/Tools/gxx.py b/waflib/Tools/gxx.py index 22c5d26..22c5d26 100644 --- a/Tools/gxx.py +++ b/waflib/Tools/gxx.py diff --git a/Tools/icc.py b/waflib/Tools/icc.py index b6492c8..b6492c8 100644 --- a/Tools/icc.py +++ b/waflib/Tools/icc.py diff --git a/Tools/icpc.py b/waflib/Tools/icpc.py index 8a6cc6c..8a6cc6c 100644 --- a/Tools/icpc.py +++ b/waflib/Tools/icpc.py diff --git a/Tools/ifort.py b/waflib/Tools/ifort.py index 74934f3..74934f3 100644 --- a/Tools/ifort.py +++ b/waflib/Tools/ifort.py diff --git a/Tools/intltool.py b/waflib/Tools/intltool.py index af95ba8..af95ba8 100644 --- a/Tools/intltool.py +++ b/waflib/Tools/intltool.py diff --git a/Tools/irixcc.py b/waflib/Tools/irixcc.py index c3ae1ac..c3ae1ac 100644 --- a/Tools/irixcc.py +++ b/waflib/Tools/irixcc.py diff --git a/Tools/javaw.py b/waflib/Tools/javaw.py index f6fd20c..f6fd20c 100644 --- a/Tools/javaw.py +++ b/waflib/Tools/javaw.py diff --git a/Tools/ldc2.py b/waflib/Tools/ldc2.py index a51c344..a51c344 100644 --- a/Tools/ldc2.py +++ b/waflib/Tools/ldc2.py diff --git a/Tools/lua.py b/waflib/Tools/lua.py index 15a333a..15a333a 100644 --- a/Tools/lua.py +++ b/waflib/Tools/lua.py diff --git a/Tools/md5_tstamp.py b/waflib/Tools/md5_tstamp.py index 6428e46..6428e46 100644 --- a/Tools/md5_tstamp.py +++ b/waflib/Tools/md5_tstamp.py diff --git a/Tools/msvc.py b/waflib/Tools/msvc.py index 17b347d..17b347d 100644 --- a/Tools/msvc.py +++ b/waflib/Tools/msvc.py diff --git a/Tools/nasm.py b/waflib/Tools/nasm.py index 411d582..411d582 100644 --- a/Tools/nasm.py +++ b/waflib/Tools/nasm.py diff --git a/Tools/nobuild.py b/waflib/Tools/nobuild.py index 2e4b055..2e4b055 100644 --- a/Tools/nobuild.py +++ b/waflib/Tools/nobuild.py diff --git a/Tools/perl.py b/waflib/Tools/perl.py index 32b03fb..32b03fb 100644 --- a/Tools/perl.py +++ b/waflib/Tools/perl.py diff --git a/Tools/python.py b/waflib/Tools/python.py index 25841d0..25841d0 100644 --- a/Tools/python.py +++ b/waflib/Tools/python.py diff --git a/Tools/qt5.py b/waflib/Tools/qt5.py index 4f9c690..4f9c690 100644 --- a/Tools/qt5.py +++ b/waflib/Tools/qt5.py diff --git a/Tools/ruby.py b/waflib/Tools/ruby.py index 8d92a79..8d92a79 100644 --- a/Tools/ruby.py +++ b/waflib/Tools/ruby.py diff --git a/Tools/suncc.py b/waflib/Tools/suncc.py index 33d34fc..33d34fc 100644 --- a/Tools/suncc.py +++ b/waflib/Tools/suncc.py diff --git a/Tools/suncxx.py b/waflib/Tools/suncxx.py index 3b384f6..3b384f6 100644 --- a/Tools/suncxx.py +++ b/waflib/Tools/suncxx.py diff --git a/Tools/tex.py b/waflib/Tools/tex.py index eaf9fdb..eaf9fdb 100644 --- a/Tools/tex.py +++ b/waflib/Tools/tex.py diff --git a/Tools/vala.py b/waflib/Tools/vala.py index 822ec50..822ec50 100644 --- a/Tools/vala.py +++ b/waflib/Tools/vala.py diff --git a/Tools/waf_unit_test.py b/waflib/Tools/waf_unit_test.py index a71ed1c..a71ed1c 100644 --- a/Tools/waf_unit_test.py +++ b/waflib/Tools/waf_unit_test.py diff --git a/Tools/winres.py b/waflib/Tools/winres.py index 586c596..586c596 100644 --- a/Tools/winres.py +++ b/waflib/Tools/winres.py diff --git a/Tools/xlc.py b/waflib/Tools/xlc.py index 134dd41..134dd41 100644 --- a/Tools/xlc.py +++ b/waflib/Tools/xlc.py diff --git a/Tools/xlcxx.py b/waflib/Tools/xlcxx.py index 76aa59b..76aa59b 100644 --- a/Tools/xlcxx.py +++ b/waflib/Tools/xlcxx.py diff --git a/Utils.py b/waflib/Utils.py index b4665c4..b4665c4 100644 --- a/Utils.py +++ b/waflib/Utils.py diff --git a/__init__.py b/waflib/__init__.py index 079df35..079df35 100644 --- a/__init__.py +++ b/waflib/__init__.py diff --git a/ansiterm.py b/waflib/ansiterm.py index 0d20c63..0d20c63 100644 --- a/ansiterm.py +++ b/waflib/ansiterm.py diff --git a/extras/__init__.py b/waflib/extras/__init__.py index c8a3c34..c8a3c34 100644 --- a/extras/__init__.py +++ b/waflib/extras/__init__.py diff --git a/extras/autowaf.py b/waflib/extras/autowaf.py index a4a06ba..a4a06ba 100644 --- a/extras/autowaf.py +++ b/waflib/extras/autowaf.py diff --git a/extras/batched_cc.py b/waflib/extras/batched_cc.py index aad2872..aad2872 100644 --- a/extras/batched_cc.py +++ b/waflib/extras/batched_cc.py diff --git a/extras/biber.py b/waflib/extras/biber.py index fd9db4e..fd9db4e 100644 --- a/extras/biber.py +++ b/waflib/extras/biber.py diff --git a/extras/bjam.py b/waflib/extras/bjam.py index 8e04d3a..8e04d3a 100644 --- a/extras/bjam.py +++ b/waflib/extras/bjam.py diff --git a/extras/blender.py b/waflib/extras/blender.py index e5efc28..e5efc28 100644 --- a/extras/blender.py +++ b/waflib/extras/blender.py diff --git a/extras/boo.py b/waflib/extras/boo.py index 06623d4..06623d4 100644 --- a/extras/boo.py +++ b/waflib/extras/boo.py diff --git a/extras/boost.py b/waflib/extras/boost.py index c2aaaa9..c2aaaa9 100644 --- a/extras/boost.py +++ b/waflib/extras/boost.py diff --git a/extras/build_file_tracker.py b/waflib/extras/build_file_tracker.py index c4f26fd..c4f26fd 100644 --- a/extras/build_file_tracker.py +++ b/waflib/extras/build_file_tracker.py diff --git a/extras/build_logs.py b/waflib/extras/build_logs.py index cdf8ed0..cdf8ed0 100644 --- a/extras/build_logs.py +++ b/waflib/extras/build_logs.py diff --git a/extras/buildcopy.py b/waflib/extras/buildcopy.py index a6d9ac8..a6d9ac8 100644 --- a/extras/buildcopy.py +++ b/waflib/extras/buildcopy.py diff --git a/extras/c_bgxlc.py b/waflib/extras/c_bgxlc.py index 6e3eaf7..6e3eaf7 100644 --- a/extras/c_bgxlc.py +++ b/waflib/extras/c_bgxlc.py diff --git a/extras/c_dumbpreproc.py b/waflib/extras/c_dumbpreproc.py index ce9e1a4..ce9e1a4 100644 --- a/extras/c_dumbpreproc.py +++ b/waflib/extras/c_dumbpreproc.py diff --git a/extras/c_emscripten.py b/waflib/extras/c_emscripten.py index e1ac494..e1ac494 100644 --- a/extras/c_emscripten.py +++ b/waflib/extras/c_emscripten.py diff --git a/extras/c_nec.py b/waflib/extras/c_nec.py index 96bfae4..96bfae4 100644 --- a/extras/c_nec.py +++ b/waflib/extras/c_nec.py diff --git a/extras/cabal.py b/waflib/extras/cabal.py index e10a0d1..e10a0d1 100644 --- a/extras/cabal.py +++ b/waflib/extras/cabal.py diff --git a/extras/cfg_altoptions.py b/waflib/extras/cfg_altoptions.py index 47b1189..47b1189 100644 --- a/extras/cfg_altoptions.py +++ b/waflib/extras/cfg_altoptions.py diff --git a/extras/clang_compilation_database.py b/waflib/extras/clang_compilation_database.py index 4d9b5e2..4d9b5e2 100644 --- a/extras/clang_compilation_database.py +++ b/waflib/extras/clang_compilation_database.py diff --git a/extras/codelite.py b/waflib/extras/codelite.py index 523302c..523302c 100644 --- a/extras/codelite.py +++ b/waflib/extras/codelite.py diff --git a/extras/color_gcc.py b/waflib/extras/color_gcc.py index b68c5eb..b68c5eb 100644 --- a/extras/color_gcc.py +++ b/waflib/extras/color_gcc.py diff --git a/extras/color_rvct.py b/waflib/extras/color_rvct.py index f89ccbd..f89ccbd 100644 --- a/extras/color_rvct.py +++ b/waflib/extras/color_rvct.py diff --git a/extras/compat15.py b/waflib/extras/compat15.py index 0e74df8..0e74df8 100644 --- a/extras/compat15.py +++ b/waflib/extras/compat15.py diff --git a/extras/cppcheck.py b/waflib/extras/cppcheck.py index 13ff424..13ff424 100644 --- a/extras/cppcheck.py +++ b/waflib/extras/cppcheck.py diff --git a/extras/cpplint.py b/waflib/extras/cpplint.py index e3302e5..e3302e5 100644 --- a/extras/cpplint.py +++ b/waflib/extras/cpplint.py diff --git a/extras/cross_gnu.py b/waflib/extras/cross_gnu.py index 309f53b..309f53b 100644 --- a/extras/cross_gnu.py +++ b/waflib/extras/cross_gnu.py diff --git a/extras/cython.py b/waflib/extras/cython.py index 481d6f4..481d6f4 100644 --- a/extras/cython.py +++ b/waflib/extras/cython.py diff --git a/extras/dcc.py b/waflib/extras/dcc.py index c1a57c0..c1a57c0 100644 --- a/extras/dcc.py +++ b/waflib/extras/dcc.py diff --git a/extras/distnet.py b/waflib/extras/distnet.py index 09a31a6..09a31a6 100644 --- a/extras/distnet.py +++ b/waflib/extras/distnet.py diff --git a/extras/doxygen.py b/waflib/extras/doxygen.py index 28f56e9..28f56e9 100644 --- a/extras/doxygen.py +++ b/waflib/extras/doxygen.py diff --git a/extras/dpapi.py b/waflib/extras/dpapi.py index b94d482..b94d482 100644 --- a/extras/dpapi.py +++ b/waflib/extras/dpapi.py diff --git a/extras/eclipse.py b/waflib/extras/eclipse.py index bb78741..bb78741 100644 --- a/extras/eclipse.py +++ b/waflib/extras/eclipse.py diff --git a/extras/erlang.py b/waflib/extras/erlang.py index 49f6d5b..49f6d5b 100644 --- a/extras/erlang.py +++ b/waflib/extras/erlang.py diff --git a/extras/fast_partial.py b/waflib/extras/fast_partial.py index b3af513..b3af513 100644 --- a/extras/fast_partial.py +++ b/waflib/extras/fast_partial.py diff --git a/extras/fc_bgxlf.py b/waflib/extras/fc_bgxlf.py index cca1810..cca1810 100644 --- a/extras/fc_bgxlf.py +++ b/waflib/extras/fc_bgxlf.py diff --git a/extras/fc_cray.py b/waflib/extras/fc_cray.py index da733fa..da733fa 100644 --- a/extras/fc_cray.py +++ b/waflib/extras/fc_cray.py diff --git a/extras/fc_nag.py b/waflib/extras/fc_nag.py index edcb218..edcb218 100644 --- a/extras/fc_nag.py +++ b/waflib/extras/fc_nag.py diff --git a/extras/fc_nec.py b/waflib/extras/fc_nec.py index 67c8680..67c8680 100644 --- a/extras/fc_nec.py +++ b/waflib/extras/fc_nec.py diff --git a/extras/fc_open64.py b/waflib/extras/fc_open64.py index 413719f..413719f 100644 --- a/extras/fc_open64.py +++ b/waflib/extras/fc_open64.py diff --git a/extras/fc_pgfortran.py b/waflib/extras/fc_pgfortran.py index afb2817..afb2817 100644 --- a/extras/fc_pgfortran.py +++ b/waflib/extras/fc_pgfortran.py diff --git a/extras/fc_solstudio.py b/waflib/extras/fc_solstudio.py index 53766df..53766df 100644 --- a/extras/fc_solstudio.py +++ b/waflib/extras/fc_solstudio.py diff --git a/extras/fc_xlf.py b/waflib/extras/fc_xlf.py index 5a3da03..5a3da03 100644 --- a/extras/fc_xlf.py +++ b/waflib/extras/fc_xlf.py diff --git a/extras/file_to_object.py b/waflib/extras/file_to_object.py index 1393b51..1393b51 100644 --- a/extras/file_to_object.py +++ b/waflib/extras/file_to_object.py diff --git a/extras/fluid.py b/waflib/extras/fluid.py index 4814a35..4814a35 100644 --- a/extras/fluid.py +++ b/waflib/extras/fluid.py diff --git a/extras/freeimage.py b/waflib/extras/freeimage.py index f27e525..f27e525 100644 --- a/extras/freeimage.py +++ b/waflib/extras/freeimage.py diff --git a/extras/fsb.py b/waflib/extras/fsb.py index 1b8f398..1b8f398 100644 --- a/extras/fsb.py +++ b/waflib/extras/fsb.py diff --git a/extras/fsc.py b/waflib/extras/fsc.py index c67e70b..c67e70b 100644 --- a/extras/fsc.py +++ b/waflib/extras/fsc.py diff --git a/extras/gccdeps.py b/waflib/extras/gccdeps.py index d9758ab..d9758ab 100644 --- a/extras/gccdeps.py +++ b/waflib/extras/gccdeps.py diff --git a/extras/gdbus.py b/waflib/extras/gdbus.py index 0e0476e..0e0476e 100644 --- a/extras/gdbus.py +++ b/waflib/extras/gdbus.py diff --git a/extras/gob2.py b/waflib/extras/gob2.py index b4fa3b9..b4fa3b9 100644 --- a/extras/gob2.py +++ b/waflib/extras/gob2.py diff --git a/extras/halide.py b/waflib/extras/halide.py index 6078e38..6078e38 100644 --- a/extras/halide.py +++ b/waflib/extras/halide.py diff --git a/extras/javatest.py b/waflib/extras/javatest.py index 979b8d8..979b8d8 100755 --- a/extras/javatest.py +++ b/waflib/extras/javatest.py diff --git a/extras/kde4.py b/waflib/extras/kde4.py index e49a9ec..e49a9ec 100644 --- a/extras/kde4.py +++ b/waflib/extras/kde4.py diff --git a/extras/local_rpath.py b/waflib/extras/local_rpath.py index b2507e1..b2507e1 100644 --- a/extras/local_rpath.py +++ b/waflib/extras/local_rpath.py diff --git a/extras/lv2.py b/waflib/extras/lv2.py index 815987f..815987f 100644 --- a/extras/lv2.py +++ b/waflib/extras/lv2.py diff --git a/extras/make.py b/waflib/extras/make.py index 933d9ca..933d9ca 100644 --- a/extras/make.py +++ b/waflib/extras/make.py diff --git a/extras/midl.py b/waflib/extras/midl.py index 43e6cf9..43e6cf9 100644 --- a/extras/midl.py +++ b/waflib/extras/midl.py diff --git a/extras/msvcdeps.py b/waflib/extras/msvcdeps.py index fc1ecd4..fc1ecd4 100644 --- a/extras/msvcdeps.py +++ b/waflib/extras/msvcdeps.py diff --git a/extras/msvs.py b/waflib/extras/msvs.py index 8aa2db0..8aa2db0 100644 --- a/extras/msvs.py +++ b/waflib/extras/msvs.py diff --git a/extras/netcache_client.py b/waflib/extras/netcache_client.py index dc49048..dc49048 100644 --- a/extras/netcache_client.py +++ b/waflib/extras/netcache_client.py diff --git a/extras/objcopy.py b/waflib/extras/objcopy.py index 82d8359..82d8359 100644 --- a/extras/objcopy.py +++ b/waflib/extras/objcopy.py diff --git a/extras/ocaml.py b/waflib/extras/ocaml.py index afe73c0..afe73c0 100644 --- a/extras/ocaml.py +++ b/waflib/extras/ocaml.py diff --git a/extras/package.py b/waflib/extras/package.py index c06498e..c06498e 100644 --- a/extras/package.py +++ b/waflib/extras/package.py diff --git a/extras/parallel_debug.py b/waflib/extras/parallel_debug.py index 35883a3..35883a3 100644 --- a/extras/parallel_debug.py +++ b/waflib/extras/parallel_debug.py diff --git a/extras/pch.py b/waflib/extras/pch.py index 103e752..103e752 100644 --- a/extras/pch.py +++ b/waflib/extras/pch.py diff --git a/extras/pep8.py b/waflib/extras/pep8.py index 676beed..676beed 100644 --- a/extras/pep8.py +++ b/waflib/extras/pep8.py diff --git a/extras/pgicc.py b/waflib/extras/pgicc.py index 9790b9c..9790b9c 100644 --- a/extras/pgicc.py +++ b/waflib/extras/pgicc.py diff --git a/extras/pgicxx.py b/waflib/extras/pgicxx.py index eae121c..eae121c 100644 --- a/extras/pgicxx.py +++ b/waflib/extras/pgicxx.py diff --git a/extras/proc.py b/waflib/extras/proc.py index 764abec..764abec 100644 --- a/extras/proc.py +++ b/waflib/extras/proc.py diff --git a/extras/protoc.py b/waflib/extras/protoc.py index f3cb4d8..f3cb4d8 100644 --- a/extras/protoc.py +++ b/waflib/extras/protoc.py diff --git a/extras/pyqt5.py b/waflib/extras/pyqt5.py index c21dfa7..c21dfa7 100644 --- a/extras/pyqt5.py +++ b/waflib/extras/pyqt5.py diff --git a/extras/pytest.py b/waflib/extras/pytest.py index 7dd5a1a..7dd5a1a 100644 --- a/extras/pytest.py +++ b/waflib/extras/pytest.py diff --git a/extras/qnxnto.py b/waflib/extras/qnxnto.py index 1158124..1158124 100644 --- a/extras/qnxnto.py +++ b/waflib/extras/qnxnto.py diff --git a/extras/qt4.py b/waflib/extras/qt4.py index 90cae7e..90cae7e 100644 --- a/extras/qt4.py +++ b/waflib/extras/qt4.py diff --git a/extras/relocation.py b/waflib/extras/relocation.py index 7e821f4..7e821f4 100644 --- a/extras/relocation.py +++ b/waflib/extras/relocation.py diff --git a/extras/remote.py b/waflib/extras/remote.py index 3b038f7..3b038f7 100644 --- a/extras/remote.py +++ b/waflib/extras/remote.py diff --git a/extras/resx.py b/waflib/extras/resx.py index caf4d31..caf4d31 100644 --- a/extras/resx.py +++ b/waflib/extras/resx.py diff --git a/extras/review.py b/waflib/extras/review.py index 561e062..561e062 100644 --- a/extras/review.py +++ b/waflib/extras/review.py diff --git a/extras/rst.py b/waflib/extras/rst.py index f3c3a5e..f3c3a5e 100644 --- a/extras/rst.py +++ b/waflib/extras/rst.py diff --git a/extras/run_do_script.py b/waflib/extras/run_do_script.py index f3c5812..f3c5812 100644 --- a/extras/run_do_script.py +++ b/waflib/extras/run_do_script.py diff --git a/extras/run_m_script.py b/waflib/extras/run_m_script.py index b5f27eb..b5f27eb 100644 --- a/extras/run_m_script.py +++ b/waflib/extras/run_m_script.py diff --git a/extras/run_py_script.py b/waflib/extras/run_py_script.py index 3670381..3670381 100644 --- a/extras/run_py_script.py +++ b/waflib/extras/run_py_script.py diff --git a/extras/run_r_script.py b/waflib/extras/run_r_script.py index b0d8f2b..b0d8f2b 100644 --- a/extras/run_r_script.py +++ b/waflib/extras/run_r_script.py diff --git a/extras/sas.py b/waflib/extras/sas.py index 754c614..754c614 100644 --- a/extras/sas.py +++ b/waflib/extras/sas.py diff --git a/extras/satellite_assembly.py b/waflib/extras/satellite_assembly.py index 005eb07..005eb07 100644 --- a/extras/satellite_assembly.py +++ b/waflib/extras/satellite_assembly.py diff --git a/extras/scala.py b/waflib/extras/scala.py index a9880f0..a9880f0 100644 --- a/extras/scala.py +++ b/waflib/extras/scala.py diff --git a/extras/slow_qt4.py b/waflib/extras/slow_qt4.py index ec7880b..ec7880b 100644 --- a/extras/slow_qt4.py +++ b/waflib/extras/slow_qt4.py diff --git a/extras/softlink_libs.py b/waflib/extras/softlink_libs.py index 50c777f..50c777f 100644 --- a/extras/softlink_libs.py +++ b/waflib/extras/softlink_libs.py diff --git a/extras/stale.py b/waflib/extras/stale.py index cac3f46..cac3f46 100644 --- a/extras/stale.py +++ b/waflib/extras/stale.py diff --git a/extras/stracedeps.py b/waflib/extras/stracedeps.py index 37d82cb..37d82cb 100644 --- a/extras/stracedeps.py +++ b/waflib/extras/stracedeps.py diff --git a/extras/swig.py b/waflib/extras/swig.py index fd3d6d2..fd3d6d2 100644 --- a/extras/swig.py +++ b/waflib/extras/swig.py diff --git a/extras/syms.py b/waflib/extras/syms.py index dfa0059..dfa0059 100644 --- a/extras/syms.py +++ b/waflib/extras/syms.py diff --git a/extras/ticgt.py b/waflib/extras/ticgt.py index f43a7ea..f43a7ea 100644 --- a/extras/ticgt.py +++ b/waflib/extras/ticgt.py diff --git a/extras/unity.py b/waflib/extras/unity.py index 78128ed..78128ed 100644 --- a/extras/unity.py +++ b/waflib/extras/unity.py diff --git a/extras/use_config.py b/waflib/extras/use_config.py index ef5129f..ef5129f 100644 --- a/extras/use_config.py +++ b/waflib/extras/use_config.py diff --git a/extras/valadoc.py b/waflib/extras/valadoc.py index c50f69e..c50f69e 100644 --- a/extras/valadoc.py +++ b/waflib/extras/valadoc.py diff --git a/extras/waf_xattr.py b/waflib/extras/waf_xattr.py index 351dd63..351dd63 100644 --- a/extras/waf_xattr.py +++ b/waflib/extras/waf_xattr.py diff --git a/extras/why.py b/waflib/extras/why.py index 1bb941f..1bb941f 100644 --- a/extras/why.py +++ b/waflib/extras/why.py diff --git a/extras/win32_opts.py b/waflib/extras/win32_opts.py index 9f7443c..9f7443c 100644 --- a/extras/win32_opts.py +++ b/waflib/extras/win32_opts.py diff --git a/extras/wix.py b/waflib/extras/wix.py index d87bfbb..d87bfbb 100644 --- a/extras/wix.py +++ b/waflib/extras/wix.py diff --git a/extras/xcode6.py b/waflib/extras/xcode6.py index 91bbff1..91bbff1 100644 --- a/extras/xcode6.py +++ b/waflib/extras/xcode6.py diff --git a/fixpy2.py b/waflib/fixpy2.py index 24176e0..24176e0 100644 --- a/fixpy2.py +++ b/waflib/fixpy2.py diff --git a/processor.py b/waflib/processor.py index 2eecf3b..2eecf3b 100755 --- a/processor.py +++ b/waflib/processor.py diff --git a/waflib/waf b/waflib/waf new file mode 100755 index 0000000..e22930a --- /dev/null +++ b/waflib/waf @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +# Minimal waf script for projects that include waflib directly + +from waflib import Context, Scripting + +import inspect +import os + +def main(): + script_path = os.path.abspath(inspect.getfile(inspect.getmodule(main))) + project_path = os.path.dirname(script_path) + Scripting.waf_entry_point(os.getcwd(), Context.WAFVERSION, project_path) + +if __name__ == '__main__': + main() @@ -0,0 +1,193 @@ +#!/usr/bin/env python +import os +import shutil +import subprocess +import waflib.Options as Options +import waflib.extras.autowaf as autowaf + +BLOP_VERSION = '1.0.1' + +# Mandatory waf variables +APPNAME = 'blop-lv2' # Package name for waf dist +VERSION = BLOP_VERSION # Package version for waf dist +top = '.' # Source directory +out = 'build' # Build directory + +def options(ctx): + ctx.load('compiler_c') + ctx.load('lv2') + autowaf.set_options(ctx) + opt = ctx.get_option_group('Configuration options') + opt.add_option('--rate', type='int', default=48000, + dest='rate', + help='ideal sample rate for oscillator wave tables [Default: 48000]') + +def configure(conf): + autowaf.display_header('Blop.LV2 Configuration') + conf.load('compiler_c', cache=True) + conf.load('lv2', cache=True) + conf.load('autowaf', cache=True) + autowaf.set_c_lang(conf, 'c99') + + autowaf.check_pkg(conf, 'lv2', atleast_version='1.2.0', uselib_store='LV2') + + autowaf.check_function(conf, 'c', 'sinf', + header_name = 'math.h', + lib = 'm', + define_name = 'HAVE_SINF', + mandatory = False) + + conf.check_cc(define_name = 'HAVE_LIBDL', + lib = 'dl', + mandatory = False) + + autowaf.check_function(conf, 'c', 'getopt_long', + header_name = 'getopt.h') + + + conf.write_config_header('blop_config.h', remove=False) + + # Set env.pluginlib_PATTERN + pat = conf.env.cshlib_PATTERN + if pat[0:3] == 'lib': + pat = pat[3:] + conf.env.pluginlib_PATTERN = pat + conf.env.pluginlib_EXT = pat[pat.rfind('.'):] + + conf.define('BLOP_SHLIB_EXT', conf.env.pluginlib_EXT) + + autowaf.display_summary(conf) + autowaf.display_msg(conf, 'LV2 bundle directory', conf.env.LV2DIR) + autowaf.display_msg(conf, 'Ideal sampling rate', + Options.options.rate) + print('') + +def build_plugin(bld, lang, bundle, name, source, defines=None, lib=[]): + # Build plugin library + penv = bld.env.derive() + penv.cshlib_PATTERN = bld.env.pluginlib_PATTERN + obj = bld(features = '%s %sshlib' % (lang,lang), + env = penv, + source = source, + includes = ['.', 'src/include'], + name = name, + target = os.path.join(bundle, name), + uselib = ['LV2'], + lib = ['m'] + lib, + install_path = '${LV2DIR}/' + bundle) + if defines != None: + obj.defines = defines + + # Install data file + data_file = '%s.ttl' % name + bld.install_files('${LV2DIR}/' + bundle, os.path.join(bundle, data_file)) + +def build(bld): + for i in bld.path.ant_glob('blop.lv2/*.ttl'): + bld(features = 'subst', + is_copy = True, + source = i, + target = 'blop.lv2/%s' % i.name, + install_path = '${LV2DIR}/blop.lv2') + + bld(features = 'subst', + source = 'blop.lv2/manifest.ttl.in', + target = 'blop.lv2/manifest.ttl', + LIB_EXT = bld.env.pluginlib_EXT, + install_path = '${LV2DIR}/blop.lv2') + + plugins = ''' + adsr + adsr_gt + amp + branch + dahdsr + difference + fmod + interpolator + product + random + ratio + sum + sync_pulse + sync_square + tracker + '''.split() + + # Simple (single source file) plugins + for i in plugins: + build_plugin(bld, 'c', 'blop.lv2', i, + ['src/%s.c' % i]) + + # Low pass filter + build_plugin(bld, 'c', 'blop.lv2', 'lp4pole', + ['src/lp4pole.c', 'src/lp4pole_filter.c']) + + # Oscillators + for i in ['pulse', 'sawtooth', 'square', 'triangle']: + lib = [] + if bld.is_defined('HAVE_LIBDL'): + lib += ['dl'] + build_plugin(bld, 'c', 'blop.lv2', i, + ['src/%s.c' % i, 'src/wavedata.c'], + lib=lib) + + # Sequencers + for i in [16, 32, 64]: + uri = 'http://drobilla.net/plugins/blop/sequencer_%d' % i + build_plugin(bld, 'c', 'blop.lv2', 'sequencer_%d' % i, + ['src/sequencer.c'], + defines=['SEQUENCER_MAX_INPUTS=%d' % i, + 'SEQUENCER_URI="%s"' % uri]) + + # Quantisers + for i in [20, 50, 100]: + uri = 'http://drobilla.net/plugins/blop/quantiser_%d' % i + build_plugin(bld, 'c', 'blop.lv2', 'quantiser_%d' % i, + ['src/quantiser.c'], + defines=['QUANTISER_MAX_INPUTS=%d' % i, + 'QUANTISER_URI="%s"' % uri]) + + # Wavegen + wavegen = bld(features = 'c cprogram', + source = ['src/wavegen.c', 'src/wdatutil.c'], + target = 'src/wavegen', + name = 'wavegen', + includes = ['.', 'src/include'], + lib = ['m'], + install_path = None) + + wavegen.post() + + # Waveform data source + for i in ['parabola', 'sawtooth', 'square']: + bld(rule = '${SRC} -r %d -f 12 -s 1 -m 128 -g 1.0 -w %s -p %s -o ${TGT}' % ( + Options.options.rate, i, i), + source = wavegen.link_task.outputs[0], + target = 'src/%s_data.c' % i, + name = i) + + penv = bld.env.derive() + penv.cshlib_PATTERN = bld.env.pluginlib_PATTERN + + bld(features = 'c cshlib', + source = bld.path.get_bld().make_node('src/%s_data.c' % i), + target = 'blop.lv2/%s_data' % i, + includes = ['.', 'src/include'], + env = penv, + install_path = '${LV2DIR}/blop.lv2', + uselib = ['LV2']) + +def lint(ctx): + subprocess.call('cpplint.py --filter=+whitespace/comments,-whitespace/tab,-whitespace/braces,-whitespace/labels,-build/header_guard,-readability/casting,-readability/todo,-build/include src/* serd/*', shell=True) + +def posts(ctx): + path = str(ctx.path.abspath()) + autowaf.news_to_posts( + os.path.join(path, 'NEWS'), + {'title' : 'BLOP.LV2', + 'description' : autowaf.get_blurb(os.path.join(path, 'README')), + 'dist_pattern' : 'http://download.drobilla.net/blop-lv2-%s.tar.bz2'}, + { 'Author' : 'drobilla', + 'Tags' : 'LV2, Blop.lv2' }, + os.path.join(out, 'posts')) |