pax_global_header00006660000000000000000000000064143450715710014521gustar00rootroot0000000000000052 comment=a072d8c4991fc10bb9237ab0051ea599ad21b93c pd-freeverb-1.3.0/000077500000000000000000000000001434507157100137235ustar00rootroot00000000000000pd-freeverb-1.3.0/Jezar_readme.txt000066400000000000000000000154251434507157100170630ustar00rootroot00000000000000Freeverb - Free, studio-quality reverb SOURCE CODE in the public domain ----------------------------------------------------------------------- Written by Jezar at Dreampoint - http://www.dreampoint.co.uk Introduction ------------ Hello. I'll try to keep this "readme" reasonably small. There are few things in the world that I hate more than long "readme" files. Except "coding conventions" - but more on that later... In this zip file you will find two folders of C++ source code: "Components" - Contains files that should clean-compile ON ANY TYPE OF COMPUTER OR SYSTEM WHATSOEVER. It should not be necessary to make ANY changes to these files to get them to compile, except to make up for inadequacies of certain compilers. These files create three classes - a comb filter, an allpass filter, and a reverb model made up of a number of instances of the filters, with some features to control the filters at a macro level. You will need to link these classes into another program that interfaces with them. The files in the components drawer are completely independant, and can be built without dependancies on anything else. Because of the simple interface, it should be possible to interface these files to any system - VST, DirectX, anything - without changing them AT ALL. "FreeverbVST" - Contains a Steinberg VST implementation of this version of Freeverb, using the components in (surprise) the components folder. It was built on a PC but may compile properly for the Macintosh with no problems. I don't know - I don't have a Macintosh. If you've figured out how to compile the examples in the Steinberg VST Development Kit, then you should easilly figure out how to bring the files into a project and get it working in a few minutes. It should be very simple. Note that this version of Freeverb doesn't contain predelay, or any EQ. I thought that might make it difficult to understand the "reverb" part of the code. Once you figure out how Freeverb works, you should find it trivial to add such features with little CPU overhead. Also, the code in this version of Freeverb has been optimised. This has changed the sound *slightly*, but not significantly compared to how much processing power it saves. Finally, note that there is also a built copy of this version of Freeverb called "Freeverb3.dll" - this is a VST plugin for the PC. If you want a version for the Mac or anything else, then you'll need to build it yourself from the code. Technical Explanation --------------------- Freeverb is a simple implementation of the standard Schroeder/Moorer reverb model. I guess the only reason why it sounds better than other reverbs, is simply because I spent a long while doing listening tests in order to create the values found in "tuning.h". It uses 8 comb filters on both the left and right channels), and you might possibly be able to get away with less if CPU power is a serious constraint for you. It then feeds the result of the reverb through 4 allpass filters on both the left and right channels. These "smooth" the sound. Adding more than four allpasses doesn't seem to add anything significant to the sound, and if you use less, the sound gets a bit "grainy". The filters on the right channel are slightly detuned compared to the left channel in order to create a stereo effect. Hopefully, you should find the code in the components drawer a model of brevity and clarity. Notice that I don't use any "coding conventions". Personally, I think that coding conventions suck. They are meant to make the code "clearer", but they inevitably do the complete opposite, making the code completely unfathomable. Anyone whose done Windows programming with its - frankly stupid - "Hungarian notation" will know exactly what I mean. Coding conventions typically promote issues that are irrelevant up to the status of appearing supremely important. It may have helped back people in the days when compilers where somewhat feeble in their type-safety, but not in the new millenium with advanced C++ compilers. Imagine if we rewrote the English language to conform to coding conventions. After all, The arguments should be just as valid for the English language as they are for a computer language. For example, we could put a lower-case "n" in front of every noun, a lower-case "p" in front of a persons name, a lower-case "v" in front of every verb, and a lower-case "a" in front of every adjective. Can you imagine what the English language would look like? All in the name of "clarity". It's just as stupid to do this for computer code as it would be to do it for the English language. I hope that the code for Freeverb in the components drawer demonstrates this, and helps start a movement back towards sanity in coding practices. Background ---------- Why is the Freeverb code now public domain? Simple. I only intended to create Freeverb to provide me and my friends with studio-quality reverb for free. I never intended to make any money out of it. However, I simply do not have the time to develop it any further. I'm working on a "concept album" at the moment, and I'll never finish it if I spend any more time programming. In any case, I make more far money as a contract programmer - making Mobile Internet products - than I ever could writing plugins, so it simply doesn't make financial sense for me to spend any more time on it. Rather than give Freeverb to any particular individual or organisation to profit from it, I've decided to give it away to the internet community at large, so that quality, FREE (or at the very least, low-cost) reverbs can be developed for all platforms. Feel free to use the source code for Freeverb in any of your own products, whether they are also available for free, or even if they are commercial - I really don't mind. You may do with the code whatever you wish. If you use it in a product (whether commercial or not), it would be very nice of you, if you were to send me a copy of your product - although I appreciate that this isn't always possible in all circumstances. HOWEVER, please don't bug me with questions about how to use this code. I gave away Freeverb because I don't have time to maintain it. That means I *certainly* don't have time to answer questions about the source code, so please don't email questions to me. I *will* ignore them. If you can't figure the code for Freeverb out - then find somebody who can. I hope that either way, you enjoy experimenting with it. Disclaimer ---------- This software and source code is given away for free, without any warranties of any kind. It has been given away to the internet community as a free gift, so please treat it in the same spirit. I hope this code is useful and interesting to you all! I hope you have lots of fun experimenting with it and make good products! Very best regards, Jezar. Technology Consultant Dreampoint Design and Engineering http://www.dreampoint.co.uk //ends pd-freeverb-1.3.0/LICENSE.txt000066400000000000000000000432541434507157100155560ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. pd-freeverb-1.3.0/Makefile000066400000000000000000000005141434507157100153630ustar00rootroot00000000000000# Makefile for freeverb~ for Makefile.pdlibbuilder lib.name = freeverb freeverb~.class.sources := freeverb~.c datafiles = \ freeverb~-help.pd \ freeverb-meta.pd \ output~.pd \ LICENSE.txt \ README.txt \ README.md \ Jezar_readme.txt \ voice.wav PDLIBBUILDER_DIR=pd-lib-builder/ include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder pd-freeverb-1.3.0/README.md000066400000000000000000000013341434507157100152030ustar00rootroot00000000000000freeverb - Freeverb is an implementation by Olaf Mattes, based on the Freeverb code put nicely in the public domain by "Jezar". This git-fork of the Pure-data library freeverb is cloned from https://git.puredata.info/cgit/svn2git/libraries/freeverb~.git, which is the svn-to-git from https://sourceforge.net/p/pure-data/svn/HEAD/tree/trunk/externals/freeverb~/. This repository replaces the Library Template Makefile by the pd-lib-builder buildsystem. This to simplify creation of a deken package of the libary. See the original README.txt for more information. For bugs found in this version, please report them to me. Olaf is not responsible for bugs introduced by me. Fred Jan Kraan fjkraan@electrickery.nl 2022-12-10 pd-freeverb-1.3.0/README.txt000066400000000000000000000047341434507157100154310ustar00rootroot00000000000000freeverb~ version 1.2 reverb external for Pure Data and Max/MSP written by Olaf Matthes based on Freeverb, the free, studio-quality reverb SOURCE CODE in the public domain, Written by Jezar at Dreampoint - http://www.dreampoint.co.uk. Freeverb is Public Domain software. The Pd-Max/MSP portions of this software are published under GPL terms, see file LICENSE. This is software with ABSOLUTELY NO WARRANTY. Use it at your OWN RISK. It's possible to damage e.g. hardware or your hearing due to a bug or for other reasons. Changes for 1.3.0: - Updated Makefile to properly conform to tips&tricks, - Updated maintainer email, - Changed version format to conform with major.minor.bugfix. Recent changes (1.2.3): - renamed library from freeverb~ to freeverb. The tilde in the directory name gives problems with cross-compilation and packaging. - updated the Makefile.pdlibbuilder to the latest cross-compilation enabled one. Changes for 1.2.2: - fixed the NaN/denormal check, - added functionality to allow filtering on the first delayed signal. Changes for 1.2.1: - added check for NANs - added a hand unrolled version of the perform routine for DSP vector sizes that are a multiple of 8. This should speed up things a bit Below some notes taken from Freeverb readme: ------------------------------------------------------------------------------------- Note that this version of Freeverb doesn't contain predelay, or any EQ. I thought that might make it difficult to understand the "reverb" part of the code. Once you figure out how Freeverb works, you should find it trivial to add such features with little CPU overhead. Technical Explanation --------------------- Freeverb is a simple implementation of the standard Schroeder/Moorer reverb model. I guess the only reason why it sounds better than other reverbs, is simply because I spent a long while doing listening tests in order to create the values found in "tuning.h". It uses 8 comb filters on both the left and right channels), and you might possibly be able to get away with less if CPU power is a serious constraint for you. It then feeds the result of the reverb through 4 allpass filters on both the left and right channels. These "smooth" the sound. Adding more than four allpasses doesn't seem to add anything significant to the sound, and if you use less, the sound gets a bit "grainy". The filters on the right channel are slightly detuned compared to the left channel in order to create a stereo effect. pd-freeverb-1.3.0/denorm-test.pd000066400000000000000000000054351434507157100165200ustar00rootroot00000000000000#N canvas 664 271 620 382 10; #X symbolatom 18 351 72 0 0 0 - - -, f 72; #X obj 18 323 makefilename %.70f; #N canvas 0 50 190 245 nan 0; #X obj 45 17 inlet; #X obj 46 173 outlet; #X obj 45 74 t b f; #X msg 46 96 2; #X obj 46 143 * 0; #X obj 46 118 pow 1024; #X msg 45 49 1024; #X connect 0 0 6 0; #X connect 2 0 3 0; #X connect 2 1 5 1; #X connect 3 0 5 0; #X connect 4 0 1 0; #X connect 5 0 4 0; #X connect 6 0 2 0; #X restore 18 44 pd nan; #X obj 18 20 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #N canvas 0 50 168 259 inf 0; #X obj 45 17 inlet; #X obj 46 173 outlet; #X obj 45 74 t b f; #X msg 46 96 2; #X obj 46 118 pow 1024; #X msg 45 49 1024; #X connect 0 0 5 0; #X connect 2 0 3 0; #X connect 2 1 4 1; #X connect 3 0 4 0; #X connect 4 0 1 0; #X connect 5 0 2 0; #X restore 71 44 pd inf; #X obj 71 20 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X floatatom 18 181 8 0 0 0 - - -, f 8; #X msg 72 116 1; #X msg 72 86 0; #X msg 106 202 \; pd dsp 1; #X msg 106 241 \; pd dsp 0; #X obj 106 179 loadbang; #N canvas 0 50 200 224 unsig~ 0; #X obj 32 40 inlet~; #X obj 32 122 snapshot~; #X obj 61 89 metro 200; #X obj 61 62 tgl 15 1 empty empty empty 17 7 0 10 -262144 -1 -1 1 1 ; #X obj 32 153 outlet; #X connect 0 0 1 0; #X connect 1 0 4 0; #X connect 2 0 1 0; #X connect 3 0 2 0; #X restore 18 266 pd unsig~; #X floatatom 18 296 17 0 0 0 - - -, f 17; #X text 183 133 Small floats which can't be expressed with the bits of the datatype are also denormal \, more specifically: subnormal. Computations with subnormal numbers are still possible \, but very CPU intensive. Test: click 1 first \, then 0 to see how small the numbers become. If all is OK \, numbers smaller than ~1e-19 are flushed to zero. If not OK \, numbers smaller than 1e-39 are seen. These are subnormals. Check CPU load difference. It is always possible to recover from subnormals by sending a normal number (like 1) in.; #X text 184 320 Katja Vetter Jan 2013; #X text 183 261 IIR filters have internal feedback delay lines \, therefore objects like [lop~] \, [hip~] and [biquad~] must be protected against denormals.; #X text 183 18 NaN and inf are denormal numbers. When inf or nan starts recirculating in a feedback delay line \, the object can't do further calculations \, even if the input goes back to normal. Therefore Pd must avoid writing nan or inf into a feedback delay line. Test: click nan or inf first \, and 1 thereafter. If all is OK \, the output returns to normal. If not OK \, inf or nan will stay at the output and the patch must be reloaded to recover.; #X obj 18 216 freeverb~; #X connect 1 0 0 0; #X connect 2 0 6 0; #X connect 3 0 2 0; #X connect 4 0 6 0; #X connect 5 0 4 0; #X connect 6 0 18 0; #X connect 7 0 6 0; #X connect 8 0 6 0; #X connect 11 0 9 0; #X connect 12 0 13 0; #X connect 13 0 1 0; #X connect 18 0 12 0; pd-freeverb-1.3.0/firstpassfilter.txt000066400000000000000000000041261434507157100177130ustar00rootroot00000000000000 Part of the freeverb design is a comb filter which consists of a delay buffer and a filter section. The incoming audio is delayed and send to both the filter and the output. The filter output is fed to both the delay buffer and the filter input. This means the first reflected signal is not filtered, only the later reflections. The result is a clear reverb, characteristic of freeverb. The [firstpassfilter 1( message switches from the traditional output to a filtered outlet, having all reflections pass through the filter. The effect is quite distinct for high [damping( values. ASCII art presentation of comb_processL: +---------------------<<------------------------+ | | combfeedback -----(*) | | +----------+ | input -----(+)----| bufcombL |----+------------ output | +----------+ | | | | combdamp2 ---------------------------(*) | | +--------------+ | (+)----| filterstoreL |----+---- firstpassfilter output | +--------------+ | combdamp1 ---------------------------(*) | | | +------------<<-----------+ (combdamp2 = 1 - combdamp1) allpass_processL: input -----+---------------------------------------(*)----- -1 | | | +-------------+ bufout | (+)---| bufallpassL |-------+------------(+)----- output | +-------------+ | | | allpassfeedback ----(*)--------<<---------------+ pd-freeverb-1.3.0/freeverb-meta.pd000066400000000000000000000006371434507157100170020ustar00rootroot00000000000000#N canvas 1940 319 437 334 10; #X text 10 10 META this is a prototype of a libdir meta file; #X text 10 30 NAME freeverb; #X text 10 90 DESCRIPTION Freeverb is a simple implementation of the standard Schroeder/Moorer reverb model; #X text 10 130 LICENSE GNU GPL; #X text 10 50 AUTHOR Olaf Matthes and Jezar Wakefield; #X text 10 70 MAINTAINER Fred Jan Kraan ; #X text 10 150 VERSION 1.3.0; pd-freeverb-1.3.0/freeverb~-help.pd000066400000000000000000000222701434507157100171770ustar00rootroot00000000000000#N canvas 486 90 570 530 10; #X obj 0 712 cnv 15 552 21 empty empty empty 20 12 0 14 -233017 -33289 0; #X obj 0 373 cnv 3 550 3 empty empty inlets 8 12 0 13 -228856 -1 0 ; #N canvas 1025 419 348 320 META 0; #X text 12 25 LICENSE GPL v2; #X text 12 45 DESCRIPTION stereo reverb using the Schroeder/Moorer model; #X text 12 82 INLET_0 signal roomsize damping width wet dry print freeze bypass; #X text 12 112 INLET_1 signal; #X text 12 132 OUTLET_0 signal; #X text 12 152 OUTLET_1 signal; #X text 12 5 KEYWORDS signal reverb; #X text 12 172 AUTHOR Olaf Matthes. Based on Freeverb by Jeremy "Jezar" Wakefield from http://www.dreampoint.co.uk; #X text 12 205 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42. Fred Jan Kraan adapted the patch 2015-02-02 ; #X text 12 64 VERSION v1.2.2; #X restore 496 714 pd META; #X obj 0 615 cnv 3 550 3 empty empty outlets 8 12 0 13 -228856 -1 0 ; #X obj 0 673 cnv 3 550 3 empty empty arguments 8 12 0 13 -228856 -1 0; #N canvas 316 424 428 109 Related_objects 0; #X obj 0 0 cnv 15 425 20 empty empty empty 3 12 0 14 -204280 -1 0; #X text 6 1 Related Objects; #X restore 205 714 pd Related_objects; #X obj 86 384 cnv 17 3 50 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 0 0 cnv 15 552 40 empty empty freeverb~ 3 12 0 18 -204280 -1 0; #X text 110 381 signal; #X obj 86 587 cnv 17 3 17 empty empty 1 5 9 0 16 -228856 -162280 0 ; #X obj 86 624 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X text 110 624 signal; #X text 110 583 signal; #X obj 74 315 output~; #N canvas 1111 348 450 300 load 0; #X obj 118 168 soundfiler; #X obj 118 98 loadbang; #X obj 3 3 cnv 15 425 20 empty empty empty 3 12 0 14 -204280 -1 0; #X text 9 4 load voice.wav file; #X obj 118 122 \$0; #X msg 118 144 read -resize voice.wav \$1-waveTable; #X floatatom 118 192 5 0 0 0 - - -, f 5; #X connect 0 0 6 0; #X connect 1 0 4 0; #X connect 4 0 5 0; #X connect 5 0 0 0; #X restore 431 328 pd load voice; #X text 12 23 stereo reverb using the Schroeder/Moorer model; #X obj 482 10 freeverb~; #X obj 74 101 tabplay~ \$0-waveTable; #X obj 431 349 table \$0-waveTable; #X obj 75 230 freeverb/freeverb~; #X obj 74 57 bng 25 250 50 0 empty empty empty 17 7 0 10 -4034 -258113 -1; #X msg 400 116 wet \$1; #X msg 448 116 dry \$1; #X msg 23 101 print; #X obj 403 61 hsl 128 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144 -1 -1 0 1; #N canvas 1 80 450 300 inv 0; #X obj 154 69 inlet; #X obj 154 179 outlet; #X msg 154 124 1; #X obj 154 97 t b f; #X obj 154 151 -; #X connect 0 0 3 0; #X connect 2 0 4 0; #X connect 3 0 2 0; #X connect 3 1 4 1; #X connect 4 0 1 0; #X restore 448 89 pd inv; #X floatatom 506 114 5 0 0 0 - - -, f 5; #X text 391 45 dry; #X text 516 44 wet; #X floatatom 407 90 5 0 0 0 - - -, f 5; #N canvas 1 80 450 300 percussion 0; #X obj 264 129 metro 580; #X obj 293 151 delay 120; #X msg 293 172 0; #X obj 219 193 noise~; #X obj 249 216 *~; #X msg 264 172 1; #X msg 175 172 0; #X obj 131 216 *~; #X msg 146 172 1; #X obj 146 129 metro 700; #X obj 175 151 delay 200; #X obj 87 193 osc~ 400; #X obj 146 47 inlet; #X obj 130 253 outlet~; #X obj 248 253 outlet~; #X obj 146 85 t f f; #X connect 0 0 1 0; #X connect 0 0 5 0; #X connect 1 0 2 0; #X connect 2 0 4 1; #X connect 3 0 4 0; #X connect 4 0 14 0; #X connect 5 0 4 1; #X connect 6 0 7 1; #X connect 7 0 13 0; #X connect 8 0 7 1; #X connect 9 0 8 0; #X connect 9 0 10 0; #X connect 10 0 6 0; #X connect 11 0 7 0; #X connect 12 0 15 0; #X connect 15 0 9 0; #X connect 15 1 0 0; #X restore 231 101 pd percussion; #X text 105 59 play wavefile; #X obj 231 57 tgl 25 0 empty empty start 1 15 1 12 -90049 -1 -1 0 1 ; #X text 266 63 percussion; #X text 111 401 bypass r; #X text 223 402 - bypass reverb processing 0 or 1; #X text 111 440 dry u; #X text 222 441 - level of unprocessed signal \, between 0 and 1 (default: 0), f 52; #X text 111 421 damping s; #X text 222 422 - amount of damping of room's surfaces (default: 0.5) ; #X text 112 489 freeze t; #X text 222 487 - start/stop freeze of reverb tail \, using 1 or 0 ; #X text 223 381 - left input signal; #X text 247 582 - right input signal; #N canvas 497 242 613 636 More_Info 0; #X msg 25 67 roomsize \$1; #X msg 25 112 damping \$1; #X msg 25 156 width \$1; #X msg 25 200 wet \$1; #X msg 25 244 dry \$1; #X msg 59 267 print; #X msg 78 306 freeze \$1; #X msg 83 344 bypass \$1; #X obj 83 325 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X obj 78 287 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X text 154 299 - start and stop "freeze" mode (off by default). If on \, reverb tail gets freezed (sample and hold).; #X obj 37 221 hsl 60 18 0 1 0 1 empty empty dry 2 9 1 12 -225271 -1 -1 0 0; #X obj 37 177 hsl 60 18 0 1 0 1 empty empty wet 2 9 1 12 -225271 -1 -1 1770 0; #X obj 37 133 hsl 60 18 0 1 0 1 empty empty width 2 9 1 12 -262131 -1 -1 5900 0; #X obj 37 89 hsl 60 18 0 2 0 1 empty empty damping 2 9 1 12 -261689 -1 -1 5900 0; #X obj 37 44 hsl 60 18 0.11 1.1 0 1 empty empty roomsize 2 9 1 12 -261689 -1 -1 4410 0; #X text 117 43 - size of the room to be simulated. Larger values result in longer reverb. Values above 1 will result in feedback or 'room resonance' (i.e. reverb getting louder); #X floatatom 7 48 3 0 0 0 - - -, f 3; #X text 116 135 - stereo width of the reverb \, i.e. how much of the reverb part from the left and right channel mix. Turning this to 1 (nearly gives two separate mono reverbs.; #X text 115 177 - level of the wet (reverbed) signal \, between 0 and 1; #X text 113 222 - level of the dry (i.e. unprocessed or original) signal \, between 0 and 1 Note that wet and dry signals mix and thus can cause clipping if both are set at high levels.; #X text 115 267 - print the current values of these parameters.; #X text 157 333 - bypass reverb processing when set to 1 Can be used to compare reverbed signal with original signal \, and to save CPU when reverb is not needed.; #X floatatom 7 93 3 0 0 0 - - -, f 3; #X floatatom 7 138 3 0 0 0 - - -, f 3; #X floatatom 7 181 3 0 0 0 - - -, f 3; #X floatatom 7 225 3 0 0 0 - - -, f 3; #X text 114 90 - amount of damping of the room's surfaces. <=1 means nearly no damping \, resulting in a lot of reflection (long reverb) \, >1 means high damping of signals (short reverb).; #X obj 27 575 output~; #X obj 0 0 cnv 15 425 20 empty empty empty 3 12 0 14 -204280 -1 0; #X text 6 1 More messages; #X obj 96 462 tabplay~ \$0-waveTable; #X obj 96 426 bng 25 250 50 0 empty empty empty 17 7 0 10 -4034 -258113 -1; #N canvas 1 80 450 300 percussion 0; #X obj 264 129 metro 580; #X obj 293 151 delay 120; #X msg 293 172 0; #X obj 219 193 noise~; #X obj 249 216 *~; #X msg 264 172 1; #X msg 175 172 0; #X obj 131 216 *~; #X msg 146 172 1; #X obj 146 129 metro 700; #X obj 175 151 delay 200; #X obj 87 193 osc~ 400; #X obj 146 47 inlet; #X obj 130 253 outlet~; #X obj 248 253 outlet~; #X obj 146 85 t f f; #X connect 0 0 1 0; #X connect 0 0 5 0; #X connect 1 0 2 0; #X connect 2 0 4 1; #X connect 3 0 4 0; #X connect 4 0 14 0; #X connect 5 0 4 1; #X connect 6 0 7 1; #X connect 7 0 13 0; #X connect 8 0 7 1; #X connect 9 0 8 0; #X connect 9 0 10 0; #X connect 10 0 6 0; #X connect 11 0 7 0; #X connect 12 0 15 0; #X connect 15 0 9 0; #X connect 15 1 0 0; #X restore 253 462 pd percussion; #X text 127 433 play wavefile; #X obj 253 426 tgl 25 0 empty empty start 1 15 1 12 -90049 -1 -1 0 1; #X text 288 432 percussion; #X obj 26 530 freeverb/freeverb~; #X obj 85 364 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X msg 85 382 firstpassfilter \$1; #X text 209 374 - change the comb filter output signal. The default starts filtering on the second returned signal. This setting allows filtering on the first returned (=delayed) signal.; #X connect 0 0 37 0; #X connect 1 0 37 0; #X connect 2 0 37 0; #X connect 3 0 37 0; #X connect 4 0 37 0; #X connect 5 0 37 0; #X connect 6 0 37 0; #X connect 7 0 37 0; #X connect 8 0 7 0; #X connect 9 0 6 0; #X connect 11 0 4 0; #X connect 11 0 26 0; #X connect 12 0 3 0; #X connect 12 0 25 0; #X connect 13 0 2 0; #X connect 13 0 24 0; #X connect 14 0 1 0; #X connect 14 0 23 0; #X connect 15 0 0 0; #X connect 15 0 17 0; #X connect 31 0 37 0; #X connect 31 0 37 1; #X connect 32 0 31 0; #X connect 33 0 37 0; #X connect 33 1 37 1; #X connect 35 0 33 0; #X connect 37 0 28 0; #X connect 37 1 28 1; #X connect 38 0 39 0; #X connect 39 0 37 0; #X restore 429 275 pd More_Info; #X text 87 686 1: float not used; #X text 110 506 print; #X text 222 507 - print the current values of the above parameters ; #X text 110 525 roomsize s; #X text 222 526 - size of the room to be simulated (default=0.85); #X text 110 543 wet r; #X text 222 544 - level of reverbed signal \, between 0 and 1 (default: 0.3); #X text 110 563 width s; #X text 222 564 - stereo width of reverb (default: 1); #X text 112 470 firstpassfilter f; #X text 222 468 - enables comb filtering on first pass \, using 1 or 0; #X obj 86 651 cnv 17 3 17 empty empty 1 5 9 0 16 -228856 -162280 0 ; #X text 110 651 signal; #X text 224 624 - left output signal; #X text 224 651 - right output signal; #X connect 17 0 19 0; #X connect 17 0 19 1; #X connect 19 0 13 0; #X connect 19 1 13 1; #X connect 20 0 17 0; #X connect 21 0 19 0; #X connect 22 0 19 0; #X connect 23 0 19 0; #X connect 24 0 21 0; #X connect 24 0 25 0; #X connect 24 0 29 0; #X connect 25 0 22 0; #X connect 25 0 26 0; #X connect 30 0 19 0; #X connect 30 1 19 1; #X connect 32 0 30 0; pd-freeverb-1.3.0/freeverb~-test.pd000066400000000000000000000035401434507157100172250ustar00rootroot00000000000000#N canvas 32 711 598 353 10; #X obj 83 94 freeverb~/freeverb~; #X floatatom 327 285 0 0 0 0 - - -; #X obj 327 159 cputime; #X obj 327 19 loadbang; #X obj 327 103 metro 1000; #X msg 327 47 1; #X floatatom 327 75 0 0 0 0 - - -; #X obj 327 131 t b b; #X obj 327 219 * 0.1; #X obj 327 188 int; #X text 372 75 <-- on/off; #N canvas 0 50 450 250 (subpatch) 0; #X array \$0-load 100 float 0; #X coords 0 10 99 0 200 140 1 0 0; #X restore 85 135 graph; #X obj 161 7 noise~; #X msg 83 29 bypass \$1; #X obj 83 6 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 ; #X msg 177 298 \; pd dsp 0; #X msg 103 297 \; pd dsp 1; #N canvas 533 341 450 300 arrayWriter 0; #X obj 56 43 inlet; #X obj 56 217 outlet; #X obj 75 184 tabwrite \$0-load; #X obj 168 125 f; #X obj 195 125 + 1; #X obj 187 185 moses 100; #X msg 183 97 0; #X obj 238 69 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X floatatom 257 187 5 0 0 0 - - -, f 5; #X obj 168 149 t f f f; #X obj 95 125 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 56 78 t f f b; #X obj 257 218 outlet; #X connect 0 0 11 0; #X connect 3 0 4 0; #X connect 3 0 9 0; #X connect 4 0 3 1; #X connect 5 1 7 0; #X connect 6 0 3 1; #X connect 7 0 6 0; #X connect 8 0 12 0; #X connect 9 0 2 1; #X connect 9 1 5 0; #X connect 9 2 8 0; #X connect 11 0 1 0; #X connect 11 1 2 0; #X connect 11 2 3 0; #X connect 11 2 10 0; #X restore 327 253 pd arrayWriter; #X floatatom 408 284 0 0 0 0 - - -; #X obj 162 51 *~; #X obj 177 30 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X connect 2 0 9 0; #X connect 3 0 5 0; #X connect 4 0 7 0; #X connect 5 0 6 0; #X connect 6 0 4 0; #X connect 7 0 2 0; #X connect 7 1 2 1; #X connect 8 0 17 0; #X connect 9 0 8 0; #X connect 12 0 19 0; #X connect 13 0 0 0; #X connect 14 0 13 0; #X connect 17 0 1 0; #X connect 17 1 18 0; #X connect 19 0 0 0; #X connect 19 0 0 1; #X connect 20 0 19 1; pd-freeverb-1.3.0/freeverb~.c000066400000000000000000000647541434507157100161050ustar00rootroot00000000000000/* -------------------------- freeverb~ --------------------------------------- */ /* */ /* Tilde object that implements the Schroeder/Moorer reverb model. */ /* Written by Olaf Matthes . */ /* Get source at http://www.akustische-kunst.org/ */ /* */ /* Based on freeverb by Jeremy "Jezar" Wakefield http://www.dreampoint.co.uk */ /* Freeverb is Public Domain software. The Pd/Max/MSP portions are GPL 2 or up. */ /* */ /* Parts of this program are free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 2 */ /* of the License, or (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* */ /* Based on PureData by Miller Puckette and others. */ /* Also compiles for Max/MSP. */ /* */ /* ---------------------------------------------------------------------------- */ #ifdef _MSC_VER #pragma warning( disable : 4091 ) #pragma warning( disable : 4244 ) #pragma warning( disable : 4305 ) #define inline __inline #endif #ifdef PD #include "m_pd.h" #else // Max/MSP #include "ext.h" #include "z_dsp.h" #define t_floatarg double #endif #include #include #define LOGTEN 2.302585092994 #define numcombs 8 #define numallpasses 4 #define muted 0 #define fixedgain 0.015 #define scalewet 3.0 #define scaledry 2.0 #define scaledamp 0.4 #define scaleroom 0.28 #define offsetroom 0.7 #define initialroom 0.5 #define initialdamp 0.5 #define initialwet 1.0/scalewet #define initialdry 0.0 #define initialwidth 1.0 #define initialmode 0 #define initialbypass 0 #define freezemode 0.5 #define stereospread 23 /* these values assume 44.1KHz sample rate they will probably be OK for 48KHz sample rate but would need scaling for 96KHz (or other) sample rates. the values were obtained by listening tests. */ static const int combtuningL[numcombs] = { 1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617 }; static const int combtuningR[numcombs] = { 1116+stereospread, 1188+stereospread, 1277+stereospread, 1356+stereospread, 1422+stereospread, 1491+stereospread, 1557+stereospread, 1617+stereospread }; static const int allpasstuningL[numallpasses] = { 556, 441, 341, 225 }; static const int allpasstuningR[numallpasses] = { 556+stereospread, 441+stereospread, 341+stereospread, 225+stereospread }; static char *version = "freeverb~ v1.2.3"; #ifdef PD static t_class *freeverb_class; typedef struct _freeverb { t_object x_obj; #else // Max/MSP void *freeverb_class; typedef struct _freeverb { t_pxobject x_obj; #endif /* freeverb stuff */ t_float x_gain; t_float x_roomsize,x_roomsize1; t_float x_damp,x_damp1; t_float x_wet,x_wet1,x_wet2; t_float x_dry; t_float x_width; t_float x_mode; t_float x_bypass; int x_skip; t_float x_allpassfeedback; /* feedback of allpass filters */ t_float x_combfeedback; /* feedback of comb filters */ t_float x_combdamp1; t_float x_combdamp2; t_float x_filterstoreL[numcombs]; /* stores last sample value */ t_float x_filterstoreR[numcombs]; /* buffers for the combs */ t_float *x_bufcombL[numcombs]; t_float *x_bufcombR[numcombs]; int x_combidxL[numcombs]; int x_combidxR[numcombs]; /* buffers for the allpasses */ t_float *x_bufallpassL[numallpasses]; t_float *x_bufallpassR[numallpasses]; int x_allpassidxL[numallpasses]; int x_allpassidxR[numallpasses]; /* we'll make local copies adjusted to fit our sample rate */ int x_combtuningL[numcombs]; int x_combtuningR[numcombs]; int x_allpasstuningL[numallpasses]; int x_allpasstuningR[numallpasses]; int x_firstpassfilter; #ifdef PD t_float x_float; #endif } t_freeverb; //#ifndef IRIX //#define IS_DENORM_FLOAT(v) ((((*(unsigned long*)&(v))&0x7f800000)==0)&&((v)!=0.f)) //#define IS_NAN_FLOAT(v) (((*(unsigned long*)&(v))&0x7f800000)==0x7f800000) //#define IS_DENORM_NAN_FLOAT(v) (IS_DENORM_FLOAT(v)||IS_NAN_FLOAT(v)) //#define FIX_DENORM_NAN_FLOAT(v) ((v)=IS_DENORM_NAN_FLOAT(v)?0.f:(v)) //#else //#define FIX_DENORM_NAN_FLOAT(v); //#endif typedef union ulf { unsigned long ul; float f; } ulf; static inline float fix_denorm_nan_float(float v); static inline float fix_denorm_nan_float(float v) { #ifndef IRIX ulf u; u.f = v; if ((((u.ul & 0x7f800000) == 0L) && (u.f != 0.f)) || ((u.ul & 0x7f800000) == 0x7f800000)) /* if the float is denormal or NaN, return 0.0 */ return 0.0f; #endif //IRIX return v; } /* we need prototypes for Mac for everything */ static void comb_setdamp(t_freeverb *x, t_floatarg val); static void comb_setfeedback(t_freeverb *x, t_floatarg val); static inline t_float comb_processL(t_freeverb *x, int filteridx, t_float input); static inline t_float comb_processR(t_freeverb *x, int filteridx, t_float input); static void allpass_setfeedback(t_freeverb *x, t_floatarg val); static inline t_float allpass_processL(t_freeverb *x, int filteridx, t_float input); static inline t_float allpass_processR(t_freeverb *x, int filteridx, t_float input); t_int *freeverb_perform(t_int *w); t_int *freeverb_perf8(t_int *w); static void dsp_add_freeverb(t_freeverb *x, t_sample *in1, t_sample *in2, t_sample *out1, t_sample *out2, int n); void freeverb_dsp(t_freeverb *x, t_signal **sp); static void freeverb_update(t_freeverb *x); static void freeverb_setroomsize(t_freeverb *x, t_floatarg value); static float freeverb_getroomsize(t_freeverb *x); static void freeverb_setdamp(t_freeverb *x, t_floatarg value); static float freeverb_getdamp(t_freeverb *x); static void freeverb_setwet(t_freeverb *x, t_floatarg value); static float freeverb_getwet(t_freeverb *x); static void freeverb_setdry(t_freeverb *x, t_floatarg value); static float freeverb_getdry(t_freeverb *x); static void freeverb_setwidth(t_freeverb *x, t_floatarg value); static float freeverb_getwidth(t_freeverb *x); static void freeverb_setmode(t_freeverb *x, t_floatarg value); static float freeverb_getmode(t_freeverb *x); static void freeverb_setbypass(t_freeverb *x, t_floatarg value); static void freeverb_mute(t_freeverb *x); static float freeverb_getdb(float f); static void freeverb_print(t_freeverb *x); #ifdef PD void freeverb_tilde_setup(void); #endif #ifndef PD void freeverb_assist(t_freeverb *x, void *b, long m, long a, char *s); #endif static void freeverb_free(t_freeverb *x); void *freeverb_new(t_floatarg val); /* -------------------- comb filter stuff ----------------------- */ static void comb_setdamp(t_freeverb *x, t_floatarg val) { x->x_combdamp1 = val; x->x_combdamp2 = 1-val; } static void comb_setfeedback(t_freeverb *x, t_floatarg val) { x->x_combfeedback = val; } // Big to inline - but crucial for speed static inline t_float comb_processL(t_freeverb *x, int filteridx, t_float input) { t_float output; int bufidx = x->x_combidxL[filteridx]; output = x->x_bufcombL[filteridx][bufidx]; //FIX_DENORM_NAN_FLOAT(output); output = fix_denorm_nan_float(output); x->x_filterstoreL[filteridx] = (output*x->x_combdamp2) + (x->x_filterstoreL[filteridx]*x->x_combdamp1); //FIX_DENORM_NAN_FLOAT(x->x_filterstoreL[filteridx]); x->x_filterstoreL[filteridx] = fix_denorm_nan_float(x->x_filterstoreL[filteridx]); x->x_bufcombL[filteridx][bufidx] = input + (x->x_filterstoreL[filteridx]*x->x_combfeedback); if(++x->x_combidxL[filteridx] >= x->x_combtuningL[filteridx]) x->x_combidxL[filteridx] = 0; if (x->x_firstpassfilter) return x->x_filterstoreL[filteridx]; else return output; } static inline t_float comb_processR(t_freeverb *x, int filteridx, t_float input) { t_float output; int bufidx = x->x_combidxR[filteridx]; output = x->x_bufcombR[filteridx][bufidx]; //FIX_DENORM_NAN_FLOAT(output); output = fix_denorm_nan_float(output); x->x_filterstoreR[filteridx] = (output*x->x_combdamp2) + (x->x_filterstoreR[filteridx]*x->x_combdamp1); //FIX_DENORM_NAN_FLOAT(x->x_filterstoreR[filteridx]); x->x_filterstoreR[filteridx] = fix_denorm_nan_float(x->x_filterstoreR[filteridx]); x->x_bufcombR[filteridx][bufidx] = input + (x->x_filterstoreR[filteridx]*x->x_combfeedback); if(++x->x_combidxR[filteridx] >= x->x_combtuningR[filteridx]) x->x_combidxR[filteridx] = 0; if (x->x_firstpassfilter) return x->x_filterstoreR[filteridx]; else return output; } /* -------------------- allpass filter stuff ----------------------- */ static void allpass_setfeedback(t_freeverb *x, t_floatarg val) { x->x_allpassfeedback = val; } // Big to inline - but crucial for speed static inline t_float allpass_processL(t_freeverb *x, int filteridx, t_float input) { t_float output; t_float bufout; int bufidx = x->x_allpassidxL[filteridx]; bufout = (t_float)x->x_bufallpassL[filteridx][bufidx]; //FIX_DENORM_NAN_FLOAT(bufout); bufout = fix_denorm_nan_float(bufout); output = -input + bufout; x->x_bufallpassL[filteridx][bufidx] = input + (bufout*x->x_allpassfeedback); if(++x->x_allpassidxL[filteridx] >= x->x_allpasstuningL[filteridx]) x->x_allpassidxL[filteridx] = 0; return output; } static inline t_float allpass_processR(t_freeverb *x, int filteridx, t_float input) { t_float output; t_float bufout; int bufidx = x->x_allpassidxR[filteridx]; bufout = (t_float)x->x_bufallpassR[filteridx][bufidx]; //FIX_DENORM_NAN_FLOAT(bufout); bufout = fix_denorm_nan_float(bufout); output = -input + bufout; x->x_bufallpassR[filteridx][bufidx] = input + (bufout*x->x_allpassfeedback); if(++x->x_allpassidxR[filteridx] >= x->x_allpasstuningR[filteridx]) x->x_allpassidxR[filteridx] = 0; return output; } /* -------------------- general DSP stuff ----------------------- */ t_int *freeverb_perform(t_int *w) { // assign from parameters t_freeverb *x = (t_freeverb *)(w[1]); t_float *in1 = (t_float *)(w[2]); t_float *in2 = (t_float *)(w[3]); t_float *out1 = (t_float *)(w[4]); t_float *out2 = (t_float *)(w[5]); int n = (int)(w[6]); int i; t_float outL, outR, inL, inR, input; #ifndef PD if (x->x_obj.z_disabled) goto out; #endif if(x->x_bypass) { // Bypass, so just copy input to output while(n--) { inL = *in1++; // We have to copy first before we can write to output inR = *in2++; // since this might be at the same memory position *out1++ = inL; *out2++ = inR; } } else { // DSP loop while(n--) { outL = outR = 0.; inL = *in1++; inR = *in2++; input = (inL + inR) * x->x_gain; // Accumulate comb filters in parallel for(i=0; i < numcombs; i++) { outL += comb_processL(x, i, input); outR += comb_processR(x, i, input); } // Feed through allpasses in series for(i=0; i < numallpasses; i++) { outL = allpass_processL(x, i, outL); outR = allpass_processR(x, i, outR); } // Calculate output REPLACING anything already there *out1++ = outL*x->x_wet1 + outR*x->x_wet2 + inL*x->x_dry; *out2++ = outR*x->x_wet1 + outL*x->x_wet2 + inR*x->x_dry; } } #ifndef PD out: #endif return(w + 7); } // This is a hand unrolled version of the perform routine for // DSP vector sizes that are multiples of 8 t_int *freeverb_perf8(t_int *w) { // assign from parameters t_freeverb *x = (t_freeverb *)(w[1]); t_float *in1 = (t_float *)(w[2]); t_float *in2 = (t_float *)(w[3]); t_float *out1 = (t_float *)(w[4]); t_float *out2 = (t_float *)(w[5]); int n = (int)(w[6]); int i; t_float outL[8], outR[8], inL[8], inR[8], input[8]; #ifndef PD if (x->x_obj.z_disabled) goto out; #endif if(x->x_bypass) { // Bypass, so just copy input to output for(; n; n -= 8, out1 += 8, out2 += 8, in1 += 8, in2 += 8) { inL[0] = in1[0]; // We have to copy first before we can write to output inR[0] = in2[0]; // since this might be at the same memory position out1[0] = inL[0]; out2[0] = inR[0]; inL[1] = in1[1]; inR[1] = in2[1]; out1[1] = inL[1]; out2[1] = inR[1]; inL[2] = in1[2]; inR[2] = in2[2]; out1[2] = inL[2]; out2[2] = inR[2]; inL[3] = in1[3]; inR[3] = in2[3]; out1[3] = inL[3]; out2[3] = inR[3]; inL[4] = in1[4]; inR[4] = in2[4]; out1[4] = inL[4]; out2[4] = inR[4]; inL[5] = in1[5]; inR[5] = in2[5]; out1[5] = inL[5]; out2[5] = inR[5]; inL[6] = in1[6]; inR[6] = in2[6]; out1[6] = inL[6]; out2[6] = inR[6]; inL[7] = in1[7]; inR[7] = in2[7]; out1[7] = inL[7]; out2[7] = inR[7]; } } else { // DSP loop for(; n; n -= 8, out1 += 8, out2 += 8, in1 += 8, in2 += 8) { outL[0] = outR [0]= 0.; inL[0] = in1[0]; inR[0] = in2[0]; input[0] = (inL[0] + inR[0]) * x->x_gain; outL[1] = outR [1]= 0.; inL[1] = in1[1]; inR[1] = in2[1]; input[1] = (inL[1] + inR[1]) * x->x_gain; outL[2] = outR [2]= 0.; inL[2] = in1[2]; inR[2] = in2[2]; input[2] = (inL[2] + inR[2]) * x->x_gain; outL[3] = outR [3]= 0.; inL[3] = in1[3]; inR[3] = in2[3]; input[3] = (inL[3] + inR[3]) * x->x_gain; outL[4] = outR [4]= 0.; inL[4] = in1[4]; inR[4] = in2[4]; input[4] = (inL[4] + inR[4]) * x->x_gain; outL[5] = outR [5]= 0.; inL[5] = in1[5]; inR[5] = in2[5]; input[5] = (inL[5] + inR[5]) * x->x_gain; outL[6] = outR [6]= 0.; inL[6] = in1[6]; inR[6] = in2[6]; input[6] = (inL[6] + inR[6]) * x->x_gain; outL[7] = outR [7]= 0.; inL[7] = in1[7]; inR[7] = in2[7]; input[7] = (inL[7] + inR[7]) * x->x_gain; // Accumulate comb filters in parallel for(i=0; i < numcombs; i++) { outL[0] += comb_processL(x, i, input[0]); outR[0] += comb_processR(x, i, input[0]); outL[1] += comb_processL(x, i, input[1]); outR[1] += comb_processR(x, i, input[1]); outL[2] += comb_processL(x, i, input[2]); outR[2] += comb_processR(x, i, input[2]); outL[3] += comb_processL(x, i, input[3]); outR[3] += comb_processR(x, i, input[3]); outL[4] += comb_processL(x, i, input[4]); outR[4] += comb_processR(x, i, input[4]); outL[5] += comb_processL(x, i, input[5]); outR[5] += comb_processR(x, i, input[5]); outL[6] += comb_processL(x, i, input[6]); outR[6] += comb_processR(x, i, input[6]); outL[7] += comb_processL(x, i, input[7]); outR[7] += comb_processR(x, i, input[7]); } // Feed through allpasses in series for(i=0; i < numallpasses; i++) { outL[0] = allpass_processL(x, i, outL[0]); outR[0] = allpass_processR(x, i, outR[0]); outL[1] = allpass_processL(x, i, outL[1]); outR[1] = allpass_processR(x, i, outR[1]); outL[2] = allpass_processL(x, i, outL[2]); outR[2] = allpass_processR(x, i, outR[2]); outL[3] = allpass_processL(x, i, outL[3]); outR[3] = allpass_processR(x, i, outR[3]); outL[4] = allpass_processL(x, i, outL[4]); outR[4] = allpass_processR(x, i, outR[4]); outL[5] = allpass_processL(x, i, outL[5]); outR[5] = allpass_processR(x, i, outR[5]); outL[6] = allpass_processL(x, i, outL[6]); outR[6] = allpass_processR(x, i, outR[6]); outL[7] = allpass_processL(x, i, outL[7]); outR[7] = allpass_processR(x, i, outR[7]); } // Calculate output REPLACING anything already there out1[0] = outL[0]*x->x_wet1 + outR[0]*x->x_wet2 + inL[0]*x->x_dry; out2[0] = outR[0]*x->x_wet1 + outL[0]*x->x_wet2 + inR[0]*x->x_dry; out1[1] = outL[1]*x->x_wet1 + outR[1]*x->x_wet2 + inL[1]*x->x_dry; out2[1] = outR[1]*x->x_wet1 + outL[1]*x->x_wet2 + inR[1]*x->x_dry; out1[2] = outL[2]*x->x_wet1 + outR[2]*x->x_wet2 + inL[2]*x->x_dry; out2[2] = outR[2]*x->x_wet1 + outL[2]*x->x_wet2 + inR[2]*x->x_dry; out1[3] = outL[3]*x->x_wet1 + outR[3]*x->x_wet2 + inL[3]*x->x_dry; out2[3] = outR[3]*x->x_wet1 + outL[3]*x->x_wet2 + inR[3]*x->x_dry; out1[4] = outL[4]*x->x_wet1 + outR[4]*x->x_wet2 + inL[4]*x->x_dry; out2[4] = outR[4]*x->x_wet1 + outL[4]*x->x_wet2 + inR[4]*x->x_dry; out1[5] = outL[5]*x->x_wet1 + outR[5]*x->x_wet2 + inL[5]*x->x_dry; out2[5] = outR[5]*x->x_wet1 + outL[5]*x->x_wet2 + inR[5]*x->x_dry; out1[6] = outL[6]*x->x_wet1 + outR[6]*x->x_wet2 + inL[6]*x->x_dry; out2[6] = outR[6]*x->x_wet1 + outL[6]*x->x_wet2 + inR[6]*x->x_dry; out1[7] = outL[7]*x->x_wet1 + outR[7]*x->x_wet2 + inL[7]*x->x_dry; out2[7] = outR[7]*x->x_wet1 + outL[7]*x->x_wet2 + inR[7]*x->x_dry; } } #ifndef PD out: #endif return(w + 7); } static void dsp_add_freeverb(t_freeverb *x, t_sample *in1, t_sample *in2, t_sample *out1, t_sample *out2, int n) { if(n & 7) // check whether block size is multiple of 8 dsp_add(freeverb_perform, 6, x, in1, in2, out1, out2, n); else dsp_add(freeverb_perf8, 6, x, in1, in2, out1, out2, n); } void freeverb_dsp(t_freeverb *x, t_signal **sp) { dsp_add_freeverb(x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n); } // ----------- general parameter & calculation stuff ----------- // recalculate internal values after parameter change static void freeverb_update(t_freeverb *x) { int i; x->x_wet1 = x->x_wet*(x->x_width/2 + 0.5); x->x_wet2 = x->x_wet*((1-x->x_width)/2); if (x->x_mode >= freezemode) { x->x_roomsize1 = 1.; x->x_damp1 = 0.; x->x_gain = muted; } else { x->x_roomsize1 = x->x_roomsize; x->x_damp1 = x->x_damp; x->x_gain = (float)fixedgain; } comb_setfeedback(x, x->x_roomsize1); comb_setdamp(x, x->x_damp1); } // the following functions set / get the parameters static void freeverb_setroomsize(t_freeverb *x, t_floatarg value) { x->x_roomsize = (value*scaleroom) + offsetroom; freeverb_update(x); } static float freeverb_getroomsize(t_freeverb *x) { return (x->x_roomsize-offsetroom)/scaleroom; } static void freeverb_setdamp(t_freeverb *x, t_floatarg value) { x->x_damp = value*scaledamp; freeverb_update(x); } static float freeverb_getdamp(t_freeverb *x) { return x->x_damp/scaledamp; } static void freeverb_setwet(t_freeverb *x, t_floatarg value) { x->x_wet = value*scalewet; freeverb_update(x); } static float freeverb_getwet(t_freeverb *x) { return (x->x_wet/scalewet); } static void freeverb_setdry(t_freeverb *x, t_floatarg value) { x->x_dry = value*scaledry; } static float freeverb_getdry(t_freeverb *x) { return (x->x_dry/scaledry); } static void freeverb_setwidth(t_freeverb *x, t_floatarg value) { x->x_width = value; freeverb_update(x); } static float freeverb_getwidth(t_freeverb *x) { return x->x_width; } static void freeverb_setmode(t_freeverb *x, t_floatarg value) { x->x_mode = value; freeverb_update(x); } static float freeverb_getmode(t_freeverb *x) { if (x->x_mode >= freezemode) return 1; else return 0; } static void freeverb_setbypass(t_freeverb *x, t_floatarg value) { x->x_bypass = value; if(x->x_bypass)freeverb_mute(x); } // fill delay lines with silence static void freeverb_mute(t_freeverb *x) { int i; if (freeverb_getmode(x) >= freezemode) return; for (i=0;ix_bufcombL[i], 0x0, x->x_combtuningL[i]*sizeof(t_float)); memset(x->x_bufcombR[i], 0x0, x->x_combtuningR[i]*sizeof(t_float)); } for (i=0;ix_bufallpassL[i], 0x0, x->x_allpasstuningL[i]*sizeof(t_float)); memset(x->x_bufallpassR[i], 0x0, x->x_allpasstuningR[i]*sizeof(t_float)); } } // convert gain factor into dB static float freeverb_getdb(float f) { if (f <= 0) // equation does not work for 0... { return (-96); // ...so we output max. damping } else { float val = (20./LOGTEN * log(f)); return (val); } } static void freeverb_setfirstpassfilter(t_freeverb *x, t_float fpf) { x->x_firstpassfilter = (fpf > 0) ? 1 : 0; } static void freeverb_print(t_freeverb *x) { post("%s:", version); if(x->x_bypass) { post(" bypass: on"); } else post(" bypass: off"); if(!freeverb_getmode(x)) { post(" mode: normal"); } else post(" mode: freeze"); post(" roomsize: %g", freeverb_getroomsize(x)*scaleroom+offsetroom); post(" damping: %g %%", freeverb_getdamp(x)*100); post(" width: %g %%", x->x_width * 100); post(" wet level: %g dB", freeverb_getdb(freeverb_getwet(x)*scalewet)); post(" dry level: %g dB", freeverb_getdb(freeverb_getdry(x)*scaledry)); post(" firstpassfilter: %s", (x->x_firstpassfilter) ? "on" : "off"); } // clean up static void freeverb_free(t_freeverb *x) { int i; #ifndef PD dsp_free((t_pxobject *)x); // Free the object #endif // free memory used by delay lines for(i = 0; i < numcombs; i++) { t_freebytes(x->x_bufcombL[i], x->x_combtuningL[i]*sizeof(t_float)); t_freebytes(x->x_bufcombR[i], x->x_combtuningR[i]*sizeof(t_float)); } for(i = 0; i < numallpasses; i++) { t_freebytes(x->x_bufallpassL[i], x->x_allpasstuningL[i]*sizeof(t_float)); t_freebytes(x->x_bufallpassR[i], x->x_allpasstuningR[i]*sizeof(t_float)); } } void *freeverb_new(t_floatarg f) { int i; int sr = (int)sys_getsr(); #ifdef PD t_freeverb *x = (t_freeverb *)pd_new(freeverb_class); // add additional signal inlets and signal outlets inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); outlet_new(&x->x_obj, gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #else // Max/MSP t_freeverb *x = (t_freeverb *)newobject(freeverb_class); // zero out the struct, to be careful if(x) { for(i = sizeof(t_pxobject); i < sizeof(t_freeverb); i++) ((char*)x)[i] = 0; } dsp_setup((t_pxobject *)x,2); // two signal inlets // two signal outlets outlet_new((t_object *)x, "signal"); outlet_new((t_object *)x, "signal"); #endif // recalculate the reverb parameters in case we don't run at 44.1kHz for(i = 0; i < numcombs; i++) { x->x_combtuningL[i] = (int)(combtuningL[i] * sr / 44100); x->x_combtuningR[i] = (int)(combtuningR[i] * sr / 44100); } for(i = 0; i < numallpasses; i++) { x->x_allpasstuningL[i] = (int)(allpasstuningL[i] * sr / 44100); x->x_allpasstuningR[i] = (int)(allpasstuningL[i] * sr / 44100); } // get memory for delay lines for(i = 0; i < numcombs; i++) { x->x_bufcombL[i] = (t_float*) t_getbytes(x->x_combtuningL[i]*sizeof(t_float)); x->x_bufcombR[i] = (t_float*) t_getbytes(x->x_combtuningR[i]*sizeof(t_float)); x->x_combidxL[i] = 0; x->x_combidxR[i] = 0; } for(i = 0; i < numallpasses; i++) { x->x_bufallpassL[i] = (t_float*) t_getbytes(x->x_allpasstuningL[i]*sizeof(t_float)); x->x_bufallpassR[i] = (t_float*) t_getbytes(x->x_allpasstuningR[i]*sizeof(t_float)); x->x_allpassidxL[i] = 0; x->x_allpassidxR[i] = 0; } // set default values x->x_allpassfeedback = 0.5; x->x_skip = 1; // we use every sample freeverb_setwet(x, initialwet); freeverb_setroomsize(x, initialroom); freeverb_setdry(x, initialdry); freeverb_setdamp(x, initialdamp); freeverb_setwidth(x, initialwidth); freeverb_setmode(x, initialmode); freeverb_setbypass(x, initialbypass); // buffers will be full of rubbish - so we MUST mute them freeverb_mute(x); x->x_firstpassfilter = 0; return (x); } #ifdef PD void freeverb_tilde_setup(void) { freeverb_class = class_new(gensym("freeverb~"), (t_newmethod)freeverb_new, (t_method)freeverb_free, sizeof(t_freeverb), 0, A_DEFFLOAT, 0); CLASS_MAINSIGNALIN(freeverb_class, t_freeverb, x_float); class_addmethod(freeverb_class, (t_method)freeverb_dsp, gensym("dsp"), A_NULL); class_addmethod(freeverb_class, (t_method)freeverb_setroomsize, gensym("roomsize"), A_FLOAT, A_NULL); class_addmethod(freeverb_class, (t_method)freeverb_setdamp, gensym("damping"), A_FLOAT, A_NULL); class_addmethod(freeverb_class, (t_method)freeverb_setwidth, gensym("width"), A_FLOAT, A_NULL); class_addmethod(freeverb_class, (t_method)freeverb_setwet, gensym("wet"), A_FLOAT, A_NULL); class_addmethod(freeverb_class, (t_method)freeverb_setdry, gensym("dry"), A_FLOAT, A_NULL); class_addmethod(freeverb_class, (t_method)freeverb_setmode, gensym("freeze"), A_FLOAT, A_NULL); class_addmethod(freeverb_class, (t_method)freeverb_setbypass, gensym("bypass"), A_FLOAT, A_NULL); class_addmethod(freeverb_class, (t_method)freeverb_mute, gensym("clear"), A_NULL); class_addmethod(freeverb_class, (t_method)freeverb_print, gensym("print"), A_NULL); class_addmethod(freeverb_class, (t_method)freeverb_setfirstpassfilter, gensym("firstpassfilter"), A_FLOAT, A_NULL); logpost(NULL, 4, version); } #else // ----------- Max/MSP ----------- void freeverb_assist(t_freeverb *x, void *b, long m, long a, char *s) { switch(m) { case 1: // inlet switch(a) { case 0: sprintf(s, "(signal/message) Left Input & Control Messages"); break; case 1: sprintf(s, "(signal) Right Input"); break; } break; case 2: // outlet switch(a) { case 0: sprintf(s, "(signal) Left Output"); break; case 1: sprintf(s, "(signal) Right Output"); break; } break; } } extern "C" void main(void) { setup((t_messlist **)&freeverb_class,(method)freeverb_new, (method)freeverb_free, (short)sizeof(t_freeverb), 0L, A_DEFFLOAT, 0); addmess((method)freeverb_dsp, "dsp", A_CANT, 0); addmess((method)freeverb_assist, "assist", A_CANT, 0); addmess((method)freeverb_setroomsize, "roomsize", A_FLOAT, 0); addmess((method)freeverb_setdamp, "damping", A_FLOAT, 0); addmess((method)freeverb_setwidth, "width", A_FLOAT, 0); addmess((method)freeverb_setwet, "wet", A_FLOAT, 0); addmess((method)freeverb_setdry, "dry", A_FLOAT, 0); addmess((method)freeverb_setmode, "freeze", A_FLOAT, 0); addmess((method)freeverb_setbypass, "bypass", A_FLOAT, 0); addmess((method)freeverb_mute, "clear", 0); addmess((method)freeverb_print, "print", 0); dsp_initclass(); finder_addclass("MSP Delays","freeverb~"); post(version); } #endif pd-freeverb-1.3.0/output~.pd000066400000000000000000000041341434507157100160100ustar00rootroot00000000000000#N canvas 572 427 434 408 10; #X obj 13 106 hsl 42 23 0.01 1 1 0 \$0-v \$0-v volume 7 13 1 9 -245500 -13381 -1 0 0; #X obj 57 106 tgl 18 0 THIS_IS_HERE_TO_GET_RID_OF_THE_OUTLET \$0-dsp-toggle dsp 2 9 1 9 -262144 -195568 -33289 0 1; #N canvas 1019 468 429 371 dsp 0; #X obj 36 30 inlet; #X obj 117 227 select 0 1; #X msg 150 252 6; #X obj 117 86 route dsp; #X obj 117 59 receive pd; #X msg 36 228 dsp \$1; #X obj 36 253 send pd; #X msg 231 279 set \$1; #X msg 117 279 color \$1 20 12; #X obj 231 310 send \$0-dsp-toggle; #X msg 117 251 0; #X obj 251 129 loadbang; #X obj 231 99 sig~ 1; #X obj 231 191 snapshot~; #X obj 251 158 delay 100; #X obj 117 138 change -1; #X obj 2 2 cnv 15 425 20 empty empty empty 3 12 0 14 -204280 -1 0; #X text 6 3 Retrieve and set DSP state; #X connect 0 0 5 0; #X connect 0 0 15 0; #X connect 1 0 10 0; #X connect 1 1 2 0; #X connect 2 0 8 0; #X connect 3 0 15 0; #X connect 4 0 3 0; #X connect 5 0 6 0; #X connect 7 0 9 0; #X connect 8 0 9 0; #X connect 10 0 8 0; #X connect 11 0 14 0; #X connect 12 0 13 0; #X connect 13 0 1 0; #X connect 13 0 7 0; #X connect 14 0 13 0; #X connect 15 0 7 0; #X connect 15 0 1 0; #X restore 82 148 pd dsp logic; #X obj 188 31 inlet~; #X obj 74 268 line~; #X obj 174 328 *~; #X obj 194 358 dac~; #X text 200 51 audio in; #X obj 250 31 inlet~; #X obj 236 327 *~; #X obj 188 102 hip~ 3; #X obj 250 102 hip~ 3; #X obj 10 283 send pd; #X msg 10 262 dsp 1; #X obj 74 247 pack 0 50; #X text 141 246 <-- make a ramp to avoid clicks or zipper noise; #X msg 74 212 0; #X obj 74 189 moses 0.011; #X text 294 103 filter out DC; #X obj 4 3 cnv 15 425 20 empty empty empty 3 12 0 14 -204280 -1 0; #X text 10 3 dac~ and DSP switch abstraction; #X text 14 376 Created by Katja Vetter after an idea by Claude Heiland-Allen ; #X connect 0 0 13 0; #X connect 0 0 17 0; #X connect 1 0 2 0; #X connect 3 0 10 0; #X connect 4 0 9 0; #X connect 4 0 5 0; #X connect 5 0 6 0; #X connect 8 0 11 0; #X connect 9 0 6 1; #X connect 10 0 5 1; #X connect 11 0 9 1; #X connect 13 0 12 0; #X connect 14 0 4 0; #X connect 16 0 14 0; #X connect 17 0 16 0; #X connect 17 1 14 0; #X coords 0 0 1 1 65 39 1 10 90; pd-freeverb-1.3.0/pd-lib-builder/000077500000000000000000000000001434507157100165165ustar00rootroot00000000000000pd-freeverb-1.3.0/pd-lib-builder/Makefile.pdlibbuilder000066400000000000000000001266041434507157100226270ustar00rootroot00000000000000# Makefile.pdlibbuilder dated 2019-12-21 version = 0.6.0 # Helper makefile for Pure Data external libraries. # Written by Katja Vetter March-June 2015 for the public domain. No warranties. # Inspired by Hans Christoph Steiner's Makefile Template and Stephan Beal's # ShakeNMake. # # Grab the newest version of Makefile.pdlibbuilder from # https://github.com/pure-data/pd-lib-builder/ # # GNU make version >= 3.81 required. # # #=== characteristics =========================================================== # # # - defines build settings based on autodetected OS and architecture # - defines rules to build Pd class- or lib executables from C or C++ sources # - defines rules for libdir installation # - defines convenience targets for developer and user # - evaluates implicit dependencies for non-clean builds # # #=== basic usage =============================================================== # # # In your Makefile, define your Pd lib name and class files, and include # Makefile.pdlibbuilder at the end of the Makefile. Like so: # # ________________________________________________________________________ # # # Makefile for mylib # # lib.name = mylib # # class.sources = myclass1.c myclass2.c # # datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENSE.txt # # include Makefile.pdlibbuilder # ________________________________________________________________________ # # # For files in class.sources it is assumed that class basename == source file # basename. The default target builds all classes as individual executables # with Pd's default extension for the platform. For anything more than the # most basic usage, continue reading. # # #=== list of Makefile.pdlibbuilder API variables =============================== # # # Variables available for definition in your library Makefile: # # - lib.name # - lib.setup.sources # - class.sources # - common.sources # - shared.sources # - .class.sources # - .class.ldflags # - .class.ldlibs # - cflags # - ldflags # - ldlibs # - datafiles # - datadirs # - makefiles # - makefiledirs # - externalsdir # # Optional multiline defines evaluated per operating system: # # - forLinux # - forDarwin # - forWindows # # Variables available for your makefile or make command line: # # - make-lib-executable # - suppress-wunused # # Path variables for make command line or environment: # # - PDDIR # - PDINCLUDEDIR # - PDBINDIR # - PDLIBDIR # # Standard make variables for make command line or environment: # # - CPPFLAGS # - CFLAGS # - LDFLAGS # - CC # - CXX # - INSTALL # - STRIP # - DESTDIR # # Optional user variables for make command line or environment: # # - PLATFORM # # Deprecated path variables: # # - pdincludepath # - pdbinpath # - objectsdir # # #=== descriptions of Makefile.pdlibbuilder API variables ======================= # # # lib.name: # Name of the library directory as it will be installed / distributed. Also the # name of the lib executable in the case where all classes are linked into # a single binary. # # lib.setup.sources: # Source file(s) (C or C++) which must be compiled only when linking all classes # into a single lib binary. # # class.sources: # All sources files (C or C++) for which the condition holds that # class name == source file basename. # # .class.sources: # Source file(s) (C or C++) specific to class . Use this for # multiple-source classes or when class name != source file basename. # # common.sources: # Source file(s) which must be statically linked to each class in the library. # # shared.sources: # Source file(s) (C or C++) to build a shared dynamic link lib, to be linked # with all class executables. # # cflags, ldflags, ldlibs: # Define cflags (preprocessor&compiler), ldflags (linker) and ldlibs (dynamic # link libs) for the whole library. These flags are added to platform-specific # flags defined by Makefile.pdlibbuilder. # # .class.ldflags and .class.ldlibs: # Define ldflags resp. ldlibs specific to class . These flags are # added to platform-specific flags defined by Makefile.pdlibbuilder, and flags # defined in your Makefile for the whole library. Note: cflags can not be # defined per class in the current implementation. # # datafiles and datadirs: # All extra files you want to include in binary distributions of the # library: abstractions and help patches, example patches, meta patch, readme # and license texts, manuals, sound files, etcetera. Use 'datafiles' for all # files that should go into your lib rootdir and 'datadirs' for complete # directories you want to copy from source to distribution. # # forLinux, forDarwin, forWindows: # Shorthand for 'variable definitions for Linux only' etc. Use like: # define forLinux # cflags += -DLINUX # class.sources += linuxthing.c # endef # # makefiles and makefiledirs: # Extra makefiles or directories with makefiles that should be made in sub-make # processes. # # make-lib-executable: # When this variable is defined 'yes' in your makefile or as command argument, # Makefile.pdlibbuilder will try to build all classes into a single library # executable (but it will force exit if lib.setup.sources is undefined). # If your makefile defines 'make-lib-executable=yes' as the library default, # this can still be overridden with 'make-lib-executable=no' as command argument # to build individual class executables (the Makefile.pdlibbuilder default.) # # suppress-wunused: # When this variable is defined ('yes' or any other value), -Wunused-variable, # -Wunused-parameter, -Wunused-value and -Wunused-function are suppressed, # but the other warnings from -Wall are retained. # # PDDIR: # Root directory of 'portable' pd package. When defined, PDINCLUDEDIR and # PDBINDIR will be evaluated as $(PDDIR)/src and $(PDDIR)/bin. # # PDINCLUDEDIR: # Directory where Pd API m_pd.h should be found, and other Pd header files. # Overrides the default search path. # # PDBINDIR: # Directory where pd.dll should be found for linking (Windows only). Overrides # the default search path. # # PDLIBDIR: # Root directory for installation of Pd library directories. Overrides the # default install location. # # DESTDIR: # Prepended path component for staged install. # # PLATFORM: # Target platform for cross compilation in the form of GNU triplet: # cpu-vendor-os. Example: x86_64-w64-mingw32. This specifies the tool chain that # pdlibbuilder will use, if installed and locatable. System and architecture # will then be autodefined accordingly. In most cases no other variables need to # be overridden. # # CPPFLAGS: # Preprocessor flags which are not strictly required for building. # # CFLAGS: # Compiler flags which are not strictly required for building. Compiler flags # defined by Makefile.pdlibbuilder for warning, optimization and architecture # specification are overriden by CFLAGS. # # LDFLAGS: # Linker flags which are not strictly required for building. Linker flags # defined by Makefile.pdlibbuilder for architecture specification are overriden # by LDFLAGS. # # CC and CXX: # C and C++ compiler programs as defined in your build environment. # # INSTALL # Definition of install program. # # STRIP # Name of strip program. Default 'strip' can be overridden in cross compilation # environments. # # objectsdir: # Root directory for installation of Pd library directories, like PDLIBDIR but # not overridable by environment. Supported for compatibility with pd-extended # central makefile, but deprecated otherwise. # # pdincludepath, pdbinpath: # As PDINCLUDEDIR and PDBINDIR but not overridable by environment. Deprecated # as user variables. # # #=== paths ===================================================================== # # # Source files in directories other than current working directory must be # prefixed with their relative path. Do not rely on VPATH or vpath. # Object (.o) files are built in the directory of their source files. # Executables are built in current working directory. # # Default search path for m_pd.h and other API header files is platform # dependent, and overridable by PDINCLUDEDIR: # # Linux: /usr/include/pd # # OSX: /Applications/Pd*.app/Contents/Resources/src # # Windows: %PROGRAMFILES%/Pd/src # %PROGRAMFILES(X86)%/Pd/src (32 bit builds on 64 bit Windows) # # Default search path for binary pd.dll (Windows), overridable by PDBINDIR # # %PROGRAMFILES%/Pd/bin # %PROGRAMFILES(X86)%/Pd/bin (32 bit builds on 64 bit Windows) # # Default location to install pd libraries is platform dependent, and # overridable by PDLIBDIR: # # Linux: /usr/local/lib/pd-externals # OSX: ~/Library/Pd # Windows: %APPDATA%/Pd # # https://puredata.info/docs/faq/how-do-i-install-externals-and-help-files # The rationale for not installing to ~/pd-externals by default on Linux # is that some people share the home dir between 32 and 64 bit installations. # # #=== targets =================================================================== # # # all: build $(executables) plus optional post target # post: target to build after $(executables) # alldebug: build all with -g option turned on for debug symbols # : force clean build of an individual class # .pre: make preprocessor output file in current working directory # .lst: make asm/source output file in current working directory # # install: install executables and data files # clean: remove build products from source tree # # help: print help text # vars: print makefile variables # allvars: print all variables # depend: print generated prerequisites # dumpmachine: print compiler output of option '-dumpmachine' # coffee: dummy target # # Variable $(executables) expands to class executables plus optional shared lib, # or alternatively to single lib executable when make-lib-executable=true. # Targets pre and post can be defined by library makefile. Make sure to include # Makefile.pdlibbuilder first so default target all will not be redefined. # # #=== Pd-extended libdir concept ================================================ # # # For libdir layout as conceived by Hans-Christoph Steiner, see: # # https://puredata.info/docs/developer/Libdir # # Files README.txt, LICENSE.txt and -meta.pd are part of the libdir # convention. Help patches for each class and abstraction are supposed to be # available. Makefile.pdlibbuilder does not force the presence of these files # however. It does not automatically include such files in libdir installations. # Data files you want to include in distributions must be defined explicitly in # your Makefile. # # #=== Makefile.pdlibbuilder syntax conventions ================================== # # # Makefile.pdlibbuilder variable names are lower case. Default make variables, # environment variables, and standard user variables (CC, CXX, CFLAGS, DESTDIR) # are upper case. Use target 'allvars' to print all variables and their values. # # 'Fields' in data variables are separated by dots, like in 'foo.class.sources'. # Words in variables expressing a function or command are separated by dashes, # like in 'make-lib-executable'. # # #=== useful make options ======================================================= # # # Use 'make -d ' to print debug details of the make process. # Use 'make -p ' to print make's database. # # #=== TODO ====================================================================== # # # - decide whether to use -static-libgcc or shared dll in MinGW # - cygwin support # - android support # - figure out how to handle '$' in filenames # - add makefile template targets dpkg-source dist libdir distclean tags? # # #=== end of documentation sections ============================================= # # ################################################################################ ################################################################################ ################################################################################ # GNU make version 3.81 (2006) or higher is required because of the following: # - function 'info' # - variable '.DEFAULT_GOAL' # force exit when make version is < 3.81 ifneq ($(firstword $(sort 3.81 $(MAKE_VERSION))), 3.81) $(error GNU make version 3.81 or higher is required) endif # Relative path to externals root dir in multi-lib source tree like # pd-extended SVN. Default is parent of current working directory. May be # defined differently in including makefile. externalsdir ?= .. # variable you can use to check if Makefile.pdlibbuilder is already included Makefile.pdlibbuilder = true ################################################################################ ### variables: library name and version ######################################## ################################################################################ # strip possibles spaces from lib.name, they mess up calculated file names lib.name := $(strip $(lib.name)) # if meta file exists, check library version metafile := $(wildcard $(lib.name)-meta.pd) ifdef metafile lib.version := $(shell sed -n \ 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' \ $(metafile)) endif ################################################################################ ### variables: files ########################################################### ################################################################################ #=== sources =================================================================== # (re)define .class.sources using file names in class.sources define add-class-source $(notdir $(basename $v)).class.sources += $v endef $(foreach v, $(class.sources), $(eval $(add-class-source))) # derive class names from .class.sources variables sourcevariables := $(filter %.class.sources, $(.VARIABLES)) classes := $(basename $(basename $(sourcevariables))) # accumulate all source files specified in makefile classes.sources := $(sort $(foreach v, $(sourcevariables), $($v))) all.sources := $(classes.sources) $(lib.setup.sources) \ $(shared.sources) $(common.sources) #=== object files ============================================================== # construct object filenames from all C and C++ source file names classes.objects := $(addsuffix .o, $(basename $(classes.sources))) common.objects := $(addsuffix .o, $(basename $(common.sources))) shared.objects := $(addsuffix .o, $(basename $(shared.sources))) lib.setup.objects := $(addsuffix .o, $(basename $(lib.setup.sources))) all.objects = $(classes.objects) $(common.objects) $(shared.objects) \ $(lib.setup.objects) #=== executables =============================================================== # use recursive variables here because executable extension is not yet known # construct class executable names from class names classes.executables = $(addsuffix .$(extension), $(classes)) # construct shared lib executable name if shared sources are defined ifdef shared.sources shared.lib = lib$(lib.name).$(shared.extension) else shared.lib = endif ################################################################################ ### target platform detection ################################################## ################################################################################ #=== target platform =========================================================== # PLATFORM: optional user variable to define target platform for cross # compilation. Redefine build tools accordingly. PLATFORM should match # the exact target prefix of tools present in $PATH, like x86_64-w64-mingw32, # x86_64-apple-darwin12 etc. Tool definitions are exported to ensure submakes # will get the same. ifneq ($(PLATFORM),) ifneq ($(findstring darwin, $(PLATFORM)),) export CC = $(PLATFORM)-cc export CXX = $(PLATFORM)-c++ export CPP = $(PLATFORM)-cc else export CC = $(PLATFORM)-gcc export CXX = $(PLATFORM)-g++ export CPP = $(PLATFORM)-cpp endif STRIP = $(PLATFORM)-strip endif # Let (native or cross-) compiler report target triplet and isolate individual # words therein to facilitate later processing. target.triplet := $(subst -, ,$(shell $(CC) -dumpmachine)) #=== operating system ========================================================== # The following systems are defined: Linux, Darwin, Windows. GNU and # GNU/kFreeBSD are treated as Linux to get the same options. ifneq ($(filter linux gnu% kfreebsd, $(target.triplet)),) system = Linux endif ifneq ($(filter darwin%, $(target.triplet)),) system = Darwin endif ifneq ($(filter mingw% cygwin%, $(target.triplet)),) system = Windows endif # evaluate possible system-specific multiline defines from library makefile $(eval $(for$(system))) # TODO: Cygwin, Android #=== architecture ============================================================== # The following CPU names can be processed by pdlibbuilder: # i*86 Intel 32 bit # x86_64 Intel 64 bit # arm ARM 32 bit # aarch64 ARM 64 bit target.arch := $(firstword $(target.triplet)) ################################################################################ ### variables per platform ##################################################### ################################################################################ #=== flags per architecture ==================================================== # Set architecture-dependent cflags, mainly for Linux. For Mac and Windows, # arch.c.flags are overriden below. To see gcc's default architecture flags: # $ gcc -Q --help=target # ARMv6: Raspberry Pi 1st gen, not detectable from target.arch ifeq ($(shell uname), armv6l) arch.c.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard # ARMv7: Beagle, Udoo, RPi2 etc. else ifeq ($(target.arch), arm) arch.c.flags = -march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard # ARMv8 64 bit, not tested yet else ifeq ($(target.arch), aarch64) arch.c.flags = -mcpu=cortex-a53 # Intel 32 bit, build with SSE and SSE2 instructions else ifneq ($(filter i%86, $(target.arch)),) arch.c.flags = -march=pentium4 -mfpmath=sse -msse -msse2 # Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions else ifeq ($(target.arch), x86_64) arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 # if none of the above architectures detected else arch.c.flags = endif #=== flags and paths for Linux ================================================= ifeq ($(system), Linux) prefix = /usr/local libdir := $(prefix)/lib pkglibdir = $(libdir)/pd-externals pdincludepath := $(wildcard /usr/include/pd) extension = pd_linux cpp.flags := -DUNIX c.flags := -fPIC c.ldflags := -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags c.ldlibs := -lc -lm cxx.flags := -fPIC -fcheck-new cxx.ldflags := -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags cxx.ldlibs := -lc -lm -lstdc++ shared.extension = so shared.ldflags := -rdynamic -fPIC -shared -Wl,-soname,$(shared.lib) endif #=== flags and paths for Darwin ================================================ # LLVM-clang doesn't support -fcheck-new, therefore this flag is only used when # compiling with g++. ifeq ($(system), Darwin) pkglibdir = $(HOME)/Library/Pd pdincludepath := $(firstword $(wildcard \ /Applications/Pd*.app/Contents/Resources/src)) extension = pd_darwin cpp.flags := -DUNIX -DMACOSX -I /sw/include c.flags := c.ldflags := -undefined suppress -flat_namespace -bundle c.ldlibs := -lc cxx.ldflags := -undefined suppress -flat_namespace -bundle cxx.ldlibs := -lc shared.extension = dylib shared.ldflags = -dynamiclib -undefined dynamic_lookup \ -install_name @loader_path/$(shared.lib) \ -compatibility_version 1 -current_version 1.0 ifneq ($(filter %g++, $(CXX)),) cxx.flags := -fcheck-new endif ifeq ($(extension), d_fat) arch := i386 x86_64 else arch := $(target.arch) endif ifneq ($(filter -mmacosx-version-min=%, $(cflags)),) version.flag := $(filter -mmacosx-version-min=%, $(cflags)) else version.flag = -mmacosx-version-min=10.6 endif arch.c.flags := $(addprefix -arch , $(arch)) $(version.flag) arch.ld.flags := $(arch.c.flags) endif #=== flags and paths for Windows =============================================== # Standard paths on Windows contain spaces, and GNU make functions treat such # paths as lists, with unintended effects. Therefore we must use shell function # ls instead of make's wildcard when probing for a path, and use double quotes # when specifying a path in a command argument. # Default paths in Mingw / Mingw-w64 environments. 'PROGRAMFILES' is standard # location for builds with native architecture, 'ProgramFiles(x86)' for i686 # builds on x86_64 Windows (detection method by Lucas Cordiviola). Curly braces # required because of parentheses in variable name. ifeq ($(system), Windows) pkglibdir := $(APPDATA)/Pd ifeq ($(target.arch), i686) programfiles := ${ProgramFiles(x86)} else programfiles := $(PROGRAMFILES) endif pdbinpath := $(programfiles)/Pd/bin pdincludepath := $(programfiles)/Pd/src endif # Store default path to pd.dll in PDBINDIR if the latter is not user-defined. # For include path this is done in the platform-independent paths section below, # but for PDBINDIR it is done here so ld flags can be evaluated as immediate # variables. ifeq ($(system), Windows) ifdef PDDIR PDBINDIR := $(PDDIR)/bin endif PDBINDIR ?= $(pdbinpath) endif # TODO: decide whether -mms-bitfields should be specified. ifeq ($(system), Windows) cpp.flags := -DMSW -DNT ifeq ($(target.arch), i686) arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse else ifeq ($(target.arch), x86_64) cpp.flags := -DMSW -DNT -DPD_LONGINTTYPE=__int64 arch.c.flags := -march=core2 -msse -msse2 -msse3 -mfpmath=sse else arch.c.flags = endif extension = dll c.flags := c.ldflags := -static-libgcc -shared \ -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" c.ldlibs := cxx.flags := -fcheck-new cxx.ldflags := -static-libgcc -static-libstdc++ -shared \ -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" cxx.ldlibs := shared.extension = dll shared.ldflags := -static-libgcc -shared "$(PDBINDIR)/pd.dll" stripflags = --strip-all endif #=== paths ===================================================================== # Platform-dependent default paths are specified above, but overridable. # Path variables in upper case can be defined as make command argument or in the # environment. Variable 'objectsdir' is supported for compatibility with # the build system that pd-l2ork has inherited from pd-extended. PDINCLUDEDIR ?= $(pdincludepath) PDLIBDIR ?= $(firstword $(objectsdir) $(pkglibdir)) ifdef PDDIR PDINCLUDEDIR := $(wildcard $(PDDIR)/src) endif # base path where all components of the lib will be installed by default installpath := $(DESTDIR)$(PDLIBDIR)/$(lib.name) # check if include path contains spaces (as is often the case on Windows) # if so, store the path so we can later do checks with it pdincludepathwithspaces := $(if $(word 2, $(PDINCLUDEDIR)), $(PDINCLUDEDIR)) #=== accumulated build flags =================================================== # From GNU make docs: 'Users expect to be able to specify CFLAGS freely # themselves.' So we use CFLAGS to define options which are not strictly # required for compilation: optimizations, architecture specifications, and # warnings. CFLAGS can be safely overriden using a make command argument. # Variables cflags, ldflags and ldlibs may be defined in including makefile. optimization.flags = -O3 -ffast-math -funroll-loops -fomit-frame-pointer warn.flags = -Wall -Wextra -Wshadow -Winline -Wstrict-aliasing # suppress -Wunused-variable & Co if you don't want to clutter a build log ifdef suppress-wunused warn.flags += $(addprefix -Wno-unused-, function parameter value variable) endif CFLAGS = $(warn.flags) $(optimization.flags) $(arch.c.flags) # preprocessor flags cpp.flags := -DPD -I "$(PDINCLUDEDIR)" $(cpp.flags) $(CPPFLAGS) # flags for dependency checking (cflags from makefile may define -I options) depcheck.flags := $(cpp.flags) $(cflags) # architecture specifications for linker are overridable by LDFLAGS LDFLAGS := $(arch.ld.flags) # now add the same ld flags to shared dynamic lib shared.ldflags := $(shared.ldflags) $(LDFLAGS) # accumulated flags for C compiler / linker c.flags := $(cpp.flags) $(c.flags) $(cflags) $(CFLAGS) c.ldflags := $(c.ldflags) $(ldflags) $(LDFLAGS) c.ldlibs := $(c.ldlibs) $(ldlibs) # accumulated flags for C++ compiler / linker cxx.flags := $(cpp.flags) $(cxx.flags) $(cflags) $(CFLAGS) cxx.ldflags := $(cxx.ldflags) $(ldflags) $(LDFLAGS) cxx.ldlibs := $(cxx.ldlibs) $(ldlibs) ################################################################################ ### variables: tools ########################################################### ################################################################################ # aliases so we can later define 'compile-$1' and set 'c' or 'cxx' as argument compile-c := $(CC) compile-cxx := $(CXX) ################################################################################ ### checks ##################################################################### ################################################################################ # At this point most variables are defined. Now do some checks and info's # before rules begin. # print Makefile.pdlibbuilder version before possible termination $(info ++++ info: using Makefile.pdlibbuilder version $(version)) # Terminate if target triplet remained empty, to avoid all sorts of confusing # scenarios and spurious bugs. ifeq ($(target.triplet),) $(error Command "$(CC) -dumpmachine" did not return a target triplet, \ needed for a build. \ Is compiler "$(CC)" installed in your PATH? ($(PATH)). \ Does compiler "$(CC)" support option "-dumpmachine"?) endif # 'forward declaration' of default target, needed to do checks all: # To avoid unpredictable results, make sure the default target is not redefined # by including makefile. ifneq ($(.DEFAULT_GOAL), all) $(error Default target must be 'all'.) endif # find out which target(s) will be made ifdef MAKECMDGOALS goals := $(MAKECMDGOALS) else goals := all endif # store path to Pd API m_pd.h if it is found ifdef PDINCLUDEDIR mpdh := $(shell ls "$(PDINCLUDEDIR)/m_pd.h") endif # store path to pd.dll; if not found, ls will give a useful error ifeq ($(system), Windows) pddll := $(shell ls "$(PDBINDIR)/pd.dll") endif # when making target all, check if m_pd.h is found and print info about it ifeq ($(goals), all) $(if $(mpdh), \ $(info ++++ info: using Pd API $(mpdh)), \ $(warning Where is Pd API m_pd.h? Do 'make help' for info.)) endif # print target info $(info ++++ info: making target $(goals) $(if $(lib.name),in lib $(lib.name))) # when installing, print installpath info $(if $(filter install install-lib, $(goals)), $(info ++++ info: \ installpath is '$(installpath)')) #=== define executables ======================================================== # By default we build class executables, and optionally a shared dynamic link # lib. When make-lib-executable=yes we build all classes into a single lib # executable, on the condition that variable lib.setup.sources is defined. ifeq ($(make-lib-executable),yes) $(if $(lib.setup.sources), ,\ $(error Can not build library blob because lib.setup.sources is undefined)) executables := $(lib.name).$(extension) else executables := $(classes.executables) $(shared.lib) endif ################################################################################ ### rules: special targets ##################################################### ################################################################################ # Disable built-in rules. If some target can't be built with the specified # rules, it should not be built at all. MAKEFLAGS += --no-builtin-rules .PRECIOUS: .SUFFIXES: .PHONY: all post build-lib \ $(classes) $(makefiledirs) $(makefiles) \ install install-executables install-datafiles install-datadirs \ force clean vars allvars depend help ################################################################################ ### rules: build targets ####################################################### ################################################################################ # Target all forces the build of targets [$(executables) post] in # deterministic order. Target $(executables) builds class executables plus # optional shared lib or alternatively a single lib executable when # make-lib-executable=true. Target post is optionally defined by # library makefile. all: post post: $(executables) all: $(info ++++info: target all in lib $(lib.name) completed) # build all with -g option turned on for debug symbols alldebug: c.flags += -g alldebug: cxx.flags += -g alldebug: all #=== class executable ========================================================== # recipe for linking objects in class executable # argument $1 = compiler type (c or cxx) # argument $2 = class basename define link-class $(compile-$1) \ $($1.ldflags) $($2.class.ldflags) \ -o $2.$(extension) \ $(addsuffix .o, $(basename $($2.class.sources))) \ $(addsuffix .o, $(basename $(common.sources))) \ $($1.ldlibs) $($2.class.ldlibs) $(shared.lib) endef # general rule for linking object files in class executable %.$(extension): $(shared.lib) $(info ++++ info: linking objects in $@ for lib $(lib.name)) $(if $(filter %.cc %.cpp, $($*.class.sources)), \ $(call link-class,cxx,$*), \ $(call link-class,c,$*)) #=== library blob ============================================================== # build all classes into single executable build-lib: $(lib.name).$(extension) $(info ++++ info: library blob $(lib.name).$(extension) completed) # recipe for linking objects in lib executable # argument $1 = compiler type (c or cxx) define link-lib $(compile-$1) \ $($1.ldflags) $(lib.ldflags) \ -o $(lib.name).$(extension) $(all.objects) \ $($1.ldlibs) $(lib.ldlibs) endef # rule for linking objects in lib executable # declared conditionally to avoid name clashes ifeq ($(make-lib-executable),yes) $(lib.name).$(extension): $(all.objects) $(if $(filter %.cc %.cpp, $(all.sources)), \ $(call link-lib,cxx), \ $(call link-lib,c)) endif #=== shared dynamic lib ======================================================== # recipe for linking objects in shared executable # argument $1 = compiler type (c or cxx) define link-shared $(compile-$1) \ $(shared.ldflags) \ -o lib$(lib.name).$(shared.extension) $(shared.objects) \ $($1.ldlibs) $(shared.ldlibs) endef # rule for linking objects in shared executable # build recipe is in macro 'link-shared' lib$(lib.name).$(shared.extension): $(shared.objects) $(info ++++ info: linking objects in shared lib $@) $(if $(filter %.cc %.cpp, $(shared.sources)), \ $(call link-shared,cxx), \ $(call link-shared,c)) #=== object files ============================================================== # recipe to make .o file from source # argument $1 is compiler type (c or cxx) define make-object-file $(info ++++ info: making $@ in lib $(lib.name)) $(compile-$1) \ $($1.flags) \ -o $@ -c $< endef # Three rules to create .o files. These are double colon 'terminal' rules, # meaning they are the last in a rules chain. %.o:: %.c $(call make-object-file,c) %.o:: %.cc $(call make-object-file,cxx) %.o:: %.cpp $(call make-object-file,cxx) #=== explicit prerequisites for class executables ============================== # For class executables, prerequisite rules are declared in run time. Target # 'depend' prints these rules for debugging purposes. # declare explicit prerequisites rule like 'class: class.extension' # argument $v is class basename define declare-class-target $v: $v.$(extension) endef # declare explicit prerequisites rule like 'class.extension: object1.o object2.o' # argument $v is class basename define declare-class-executable-target $v.$(extension): $(addsuffix .o, $(basename $($v.class.sources))) \ $(addsuffix .o, $(basename $(common.sources))) endef # evaluate explicit prerequisite rules for all classes $(foreach v, $(classes), $(eval $(declare-class-target))) $(foreach v, $(classes), $(eval $(declare-class-executable-target))) #=== implicit prerequisites for class executables ============================== # Evaluating implicit prerequisites (header files) with help from the # preprocessor is 'expensive' so this is done conditionally and selectively. # Note that it is also possible to trigger a build via install targets, in # which case implicit prerequisites are not checked. # When the Pd include path contains spaces it will mess up the implicit # prerequisites rules. disable-dependency-tracking := $(strip $(pdincludepathwithspaces)) ifndef disable-dependency-tracking must-build-everything := $(filter all, $(goals)) must-build-class := $(filter $(classes), $(goals)) must-build-sources := $(foreach v, $(must-build-class), $($v.class.sources)) endif # declare implicit prerequisites rule like 'object.o: header1.h header2.h ...' # argument $1 is input source file(s) # dir is explicitly added because option -MM strips it by default define declare-object-target $(dir $1)$(filter %.o: %.h, $(shell $(CPP) $(depcheck.flags) -MM $1)) $(MAKEFILE_LIST) endef # evaluate implicit prerequisite rules when rebuilding everything ifdef must-build-everything $(if $(wildcard $(all.objects)), \ $(info ++++ info: evaluating implicit prerequisites in lib $(lib.name).....) \ $(foreach v, $(all.sources), $(eval $(call declare-object-target, $v)))) endif # evaluate implicit prerequisite rules when selectively building classes ifdef must-build-class $(foreach v, $(must-build-sources), \ $(eval $(call declare-object-target, $v))) $(foreach v, $(shared.sources), \ $(eval $(call declare-object-target, $v))) endif ################################################################################ ### rules: preprocessor and assembly files ##################################### ################################################################################ # Preprocessor and assembly output files for bug tracing etc. They are not part # of the build processes for executables. By default these files are created in # the current working directory. Dependency tracking is not performed, the build # is forced instead to make sure it's up to date. force: #=== preprocessor file ========================================================= # make preprocessor output file with extension .pre # argument $1 = compiler type (c or cxx) define make-preprocessor-file $(info ++++ info: making preprocessor output file $(notdir $*.pre) \ in current working directory) $(compile-$1) -E $< $(c.flags) $($1.flags) -o $(notdir $*.pre) endef %.pre:: %.c force $(call make-preprocessor-file,c) %.pre:: %.cc force $(call make-preprocessor-file,cxx) %.pre:: %.cpp force $(call make-preprocessor-file,cxx) #=== assembly file ============================================================= # make C / assembly interleaved output file with extension .lst # argument $1 = compiler type (c or cxx) define make-assembly-file $(info ++++ info: making assembly output file $(notdir $*.lst) \ in current working directory) $(compile-$1) \ -c -Wa,-a,-ad -fverbose-asm \ $($1.flags) \ $< > $(notdir $*.lst) endef %.lst:: %.c force $(call make-assembly-file,c) %.lst:: %.cc force $(call make-assembly-file,cxx) %.lst:: %.cpp force $(call make-assembly-file,cxx) ################################################################################ ### rules: installation targets ################################################ ################################################################################ #=== strip ===================================================================== # Stripping of installed binaries will only be done when variable 'stripflags' # is defined non-empty. No default definition is provided except for Windows # where the unstripped binaries are large, especially in the case of Mingw-w64. # Note: while stripping all symbols ('-s' or '--strip-all') is possible for # Linux and Windows, in the case of OSX only non-global symbols can be stripped # (option '-x' or '--discard-all'). # Make definition of strip command overridable so it can be defined in an # environment for cross-compilation. STRIP ?= strip # Commands in 'strip-executables' will be executed conditionally in the rule for # target 'install-executables'. strip-executables = cd "$(installpath)" && \ $(foreach v, $(executables), $(STRIP) $(stripflags) '$v';) #=== install =================================================================== # Install targets depend on successful exit status of target all because nothing # must be installed in case of a build error. # -p = preserve time stamps # -m = set permission mode (as in chmod) # -d = create all components of specified directories INSTALL = install INSTALL_PROGRAM := $(INSTALL) -p -m 644 INSTALL_DATA := $(INSTALL) -p -m 644 INSTALL_DIR := $(INSTALL) -m 755 -d # strip spaces from file names executables := $(strip $(executables)) datafiles := $(strip $(datafiles)) datadirs := $(strip $(datadirs)) # Do not make any install sub-target with empty variable definition because the # install program would exit with an error. install: $(if $(executables), install-executables) install: $(if $(datafiles), install-datafiles) install: $(if $(datadirs), install-datadirs) install-executables: all $(INSTALL_DIR) -v "$(installpath)" $(foreach v, $(executables), \ $(INSTALL_PROGRAM) '$v' "$(installpath)";) $(info ++++ info: executables of lib $(lib.name) installed \ from $(CURDIR) to $(installpath)) $(if $(stripflags), $(strip-executables),) install-datafiles: all $(INSTALL_DIR) -v "$(installpath)" $(foreach v, $(datafiles), \ $(INSTALL_DATA) '$(v)' "$(installpath)";) $(info ++++ info: data files of lib $(lib.name) installed \ from $(CURDIR) to $(installpath)) install-datadirs: all $(foreach v, $(datadirs), $(INSTALL_DIR) "$(installpath)/$v";) $(foreach v, $(datadirs), \ $(INSTALL_DATA) $(wildcard $v/*) "$(installpath)/$v";) $(info ++++ info: data directories of lib $(lib.name) installed \ from $(CURDIR) to $(installpath)) ################################################################################ ### rules: distribution targets ################################################ ################################################################################ # TODO # These targets are implemented in Makefile Template, but I have to figure out # how to do it under the not-so-strict conditions of Makefile.pdlibbuilder. # make source package dist: @echo "target dist not yet implemented" # make Debian source package dpkg-source: @echo "target dpkg-source not yet implemented" $(ORIGDIR): $(DISTDIR): ################################################################################ ### rules: clean targets ####################################################### ################################################################################ # delete build products from build tree clean: rm -f $(all.objects) rm -f $(classes.executables) $(lib.name).$(extension) $(shared.lib) rm -f *.pre *.lst # remove distribution directories and tarballs from build tree distclean: clean @echo "target distclean not yet implemented" ################################################################################ ### rules: submake targets ##################################################### ################################################################################ # Iterate over sub-makefiles or makefiles in other directories. # When 'continue-make=yes' is set, sub-makes will report 'true' to the parent # process regardless of their real exit status. This prevents the parent make # from being aborted by a sub-make error. Useful when you want to quickly find # out which sub-makes from a large set will succeed. ifeq ($(continue-make),yes) continue = || true endif # These targets will trigger sub-make processes for entries in 'makefiledirs' # and 'makefiles'. all alldebug install clean distclean dist dkpg-source: \ $(makefiledirs) $(makefiles) # this expands to identical rules for each entry in 'makefiledirs' $(makefiledirs): $(MAKE) --directory=$@ $(MAKECMDGOALS) $(continue) # this expands to identical rules for each entry in 'makefiles' $(makefiles): $(MAKE) --directory=$(dir $@) --makefile=$(notdir $@) $(MAKECMDGOALS) $(continue) ################################################################################ ### rules: convenience targets ################################################# ################################################################################ #=== show variables ============================================================ # Several 'function' macro's cause errors when expanded within a rule or without # proper arguments. Variables which are set with the define directive are only # shown by name for that reason. functions = \ add-class-source \ declare-class-target \ declare-class-executable-target \ declare-object-target \ link-class \ link-lib \ link-shared \ make-object-file \ make-preprocessor-file \ make-assembly-file # show variables from makefiles vars: $(info ++++ info: showing makefile variables:) $(foreach v,\ $(sort $(filter-out $(functions) functions, $(.VARIABLES))),\ $(if $(filter file, $(origin $v)),\ $(info variable $v = $($v)))) $(foreach v, $(functions), $(info 'function' name: $v)) @echo # show all variables allvars: $(info ++++ info: showing default, automatic and makefile variables:) $(foreach v, \ $(sort $(filter-out $(functions) functions, $(.VARIABLES))), \ $(info variable ($(origin $v)) $v = $($v))) $(foreach v, $(functions), $(info 'function' name: $v)) @echo #=== show dependencies ========================================================= # show generated prerequisites rules depend: $(info ++++ info: generated prerequisite rules) $(foreach v, $(classes), $(info $(declare-class-target))) $(foreach v, $(classes), $(info $(declare-class-executable-target))) $(foreach v, $(all.sources), $(info $(call declare-object-target, $v))) @echo #=== show help text ============================================================ # brief info about targets and paths ifdef mpdh mpdhinfo := $(mpdh) else mpdhinfo := m_pd.h was not found. Is Pd installed? endif help: @echo @echo " Main targets:" @echo " all: build executables (default target)" @echo " install: install all components of the library" @echo " vars: print makefile variables for troubleshooting" @echo " allvars: print all variables for troubleshooting" @echo " help: print this help text" @echo @echo " Pd API m_pd.h:" @echo " $(mpdhinfo)" @echo " You may specify your preferred Pd include directory as argument" @echo " to the make command, like 'PDINCLUDEDIR=path/to/pd/src'." @echo @echo " Path for installation of your libdir(s):" @echo " $(PDLIBDIR)" @echo " Alternatively you may specify your path for installation as argument" @echo " to the make command, like 'PDLIBDIR=path/to/pd-externals'." @echo @echo " Default paths are listed in the doc sections in Makefile.pdlibbuilder." @echo #=== platform test ============================================================= # This target can be used to test if the compiler for specified PLATFORM is # correctly defined and available. dumpmachine: @$(CC) -dumpmachine #=== dummy target ============================================================== coffee: @echo "Makefile.pdlibbuilder: Can not make coffee. Sorry." ################################################################################ ### end of rules sections ###################################################### ################################################################################ # for syntax highlighting in vim and github # vim: set filetype=make: pd-freeverb-1.3.0/voice.wav000066400000000000000000003624541434507157100155650ustar00rootroot00000000000000RIFF$WAVEfmt DXdataJCb/g;P? # nB 2  sdvZ"!jPS 4 eYlwcMw5d8F 4D=u >wjv5fg }d..kn }F/rbU@2D\p$y@}Nbu? -vEo}*|y_ZIGn6oW$qt2&u^BK*;h~VkV]bvpMZ#hu7w9K,.q?9h"82He{Oq(.Y0WA]54SM4A N,fDa@V UEx.S- w{J#{&8@h+LU!}Q%bC7m[E =eXMp"B`V)I3Fa%eXi!%0gkMu8X!7:UP&b;Yh4wi4_r&Q!jO(  wh %h  d]u*<Xg:yVe 0iXcd"%c Z: )E}Y*Jut/=nPP]%(Pnc.@EQ)8g]L-GvW]vWyWsF3?#f (Sd>uj\9?[:9p.;O@)FQFsnRb^ZNZ4&d:6X-.%XASk -QxAOe-j7*elU(DD :g ~wu E,7q@ {),t|WsYcdg'U+fL9 /=!\9RM]l~)]y@+\1p\Pc_ Cy4|K{/U,LWp+j RUP;}IhK,h"Wr8i>S$sc&sO?/#eHLz>Byn#x]4Th[.oq3b?iyD1={G#wbv '0JIEjl 4n0I:1jE*@*.tc[*BC4&LDL!Vr^W|;aN5(J U)hss,T"etL>L3858>-v_4rH4%EYV>rBZP/K) WbV,e{ xAe; ~"Fhq J= 5" nv1{rVnF-H&,h fUg0D{=&tn1HjvA(AQj n8=-p@y;m x w z $ 9 W K, >ELC*rhXDb`J#YsDEnD}lEV4 "  I a(x{Q^dI]K !"!!""!  2XPld {hmf E d K 2G[d9J]_S^8?r3?8fBq(?^ Cg!m^Nߚ߽@hMTߎOܩcqY]nkڊ=ُإק֙ԷCfʮכUInP߭a}F 4}GsG (!dF+}"kb/2&{ePD A #~!,[?AJ70MZ>3< [ $ O H 2>_BJ *"gX/J1@tPMOU&0@d  Q ! | # ( o  ^l'%S+x2z #@#"]$&%U%:''&7&'U)+,/+*+\+)(/)**)m))(' &&&$%:&W&%%E%y%$t"!t,l He)oRK_i2kD P H " K - 4   . = ?Ug[1v LGXYR^$k_Rށݠܪ| ڽٝqvYY.$ #у}ЋKZO |aͼͶ·Υoϰ'Ԃտڕ|.(ʖB׾GJl$MGnZ5?9M6f?5p,~``n=e=[e ?WWD z #d+r D!j!X!! | dd]| ]:eV/ 9 R }<]JuO%__QEc_WOh'D8FfSR.g s < .o7Qz&^m^R7o4r#(Urq67JW `޾ݬ'\ڷxH_h֝pԪdя;ѽДЌyg[P2&;/пύYMVJJxqє$ҹ4\o-hҘЀbe\IN`i O(q-YYU33/< m  `+p  q s sl9 &-$,2 p@7gqJwj}9l (i!xi}x)4  m " 0 s7-Q]Zth U3+Kz{]aQ6Ms!ch.PEckFc_ZE5=l( BEy-a !%"U"""",#-#"""J###$$4$$%%$####"&"w!  %DUvO>r&)\ a j Z  OJ4\g  AR?P\QZ!hIXxTg"Brݵ/ـٗٻن٩ؐגֳԊlI2 Ӄ Ӧ;ѻЂA<ан$Ый"JђsOVԴK G֬2]nڎۓ܆QOqA # kG&03ZmrnlGIV l+m6V r   O#;~Eav!* _7R+F7[oL;h: b4 0mtGL`k[,!`kGiw<k o t K   a!<U RGY8@pP-?LrowOVD{!6F%or&$x``Eim& v#vkl4T""ZpM D0S h L '  T (!6aY 50-!. &$Z\ Z X ?  2 o  k1Nmm~pt+N' X*4b&5z]-@(h~T2CUCyC`BߡZ+ ު|މzDLJ 8[JC9?`ޠ޻޽ ^ߴAhD6:^Xth t-\(P)D Fw+WcBtzUQ;7 9 . S ^ |N2E8u`MZc'3U`bI'.QROA|L# yU)] |Ht[ Q P  \  ] H ! }9Wx$2n1f;uF1_B%^<  x@6CHE9*0Fysxs|+j~PH !>M3PM7Z-,Q$?6;k-$?dCBJEV\cN(H6 p?) dO2d@SJ)]0n, `*wB}k:-hC-Y$jB9#o,R4% {fqNgSNEA:;*$ 2?LiD4Y/+SwXZgfN['MK\u-V} Q~Jnp)/n*;Rz#-.Qp )=;Rhsty#''3<HdTEEPNffYj}|{l^W_teQOf[GOK0 $|uifygfjsggldY[dRFROSP]XJ?E`peIWob_KTdeVVY\xulxjU^~mf]K6.CON@9949oZhKjQ00,XC/}ifL70')#{WMYZNK?;!! |x}bUgrueXSZVEPhfO`cNQNNQPN[sY\c\[z~Vgmey~~z}r{zm !+'!/,$0+K[UaqbH]odPZybZltqlukru{{hmzxRA1(9hi)2HMR[``JROGoq{xyjopcAGioSIqe>IJLTdI?4.4&$8%*%!1  bYXgmWXK<&%)81l-jFN J? 'MW y sqq EF#!ll1JcG.  ;OV??5   q2 z.y @1]fw|K # W`)   f `SG~f]kpg U + z; Q_X 3CQRJo,9 Q /h  F B  Q1uI @-6  ]^\C x`i O9M8(' {5#7 @Tj> PsLn ,XD  Vib+7 qyp% I )}`hOsxz0;NT6 @ 0E * N eRm}  / `<{g COxgq0/WG 3RED UfS%,D  + 3Rcr-s- \@ F D{ X 0CT'Z.+ @T]*P jf YmI  \  `X*p -gZS  W !b  LjzUp d  h * Eb?iqzkalWh:5J y t KB?wQ@ 1 f*:3dX&iwESDG ]\'*Js i~i6qf}~ Gp.(C;KzM5'S$t>tSLUNmm4%c(9TX|CU20-@UH{^ D ^v3OyQ? 4/ I2VMQ %inb' \  / 2"$F ,\L6n3(^UTs0rr8*l@-cp4T " 1 fO^6Lj!xpM72C[Ycs1 b%ZJ,R<L\b:Y.1  c {uE y 2 y!Cz _cP\R-(=t  O`+ZPfN- m 9\  (*\g jz   c n5 M 0 [h0aD| * gy1 q  Oip)5k ' ;O   Y8_02S %~ Vu H|3N~:^8Fr " ;W^d[?07FgiI&p| ?tgk`TC}]F R>2fde)u!\(4Mfl8 o jVkFP((  }H/ - xrSkN6u_JG1}~ td+f(&(NWg%gRSE<e[Zr\Eob|eLg`h;FS:y>4UItEK"Yhl,|=;%#^aRnzwRE } (>:N+J=V, -.G[CL$$A Z+;M~`0q*QIH, ?@ w ?MW~x 9j[!dO(}(jlS}p`&\ 8"r]=??jT$M,T6/y@{n"]RSY3* ,=2-m7apW4N.6!@VdDzl6~]n;?KMo2 F|T184X$%`~dEz & wU.RMB6ch(iZfM i}$9vJJ){ZW_9q#(i tgnE!EJ-+Up4IQtM5.Y\~6Z3)`(sv:I:6]uT^wM tpC]8lxGAU0Q#2#[M@>nO?U+"ats  zZdwe:t1/ o $ ! H2Zh/  {1P?x;vd  } N a w r % g  ]AC 7tPG{sdkMgNa? 8@jL`I -  +fzihewc\-J:;+T??xhhXsSRJC&iY{JXGHi>q5Yn%A JRO *L:i^BFzjIoWdnBa& Ta4@?]q3l!r*w*^.}*`@)E! mA|^nKJT,dt<)1CzcZQ; } 4   m  |  O5Bh!w !$')*,b-E-Q-,(+)*)+,*)+--b.// 0S00i1/1 0:/ /$/:.F,**++;+*)a)x))(m'i'p'%$,#!O mH:k3PtrbVb` s  M8mf8@( VTݹXFv#?޵;YTj4YIޱJVv:?-ߞ8$sd8wgJ%<cʄ'$Diљ8֤ #!k4Dؚ҄pFD! S;pQ6\ K x  1 oUJ < qVp   G 2 q`ve{D`G^ tNq%^-2;2= nT=s"!m">&&%O&(,.S-r+-B11.. 000115/-/0Y/(./1 272Q33333n2/f...-,*r*i*=++ +!*+,\+)0(-(.(&%%T%$#0#" . 1ug-~i7nX m>$p.!r$ 1xK 9آ+ 0#*k!ԅh߬?z z #˯rڱ.z)ZO ՝ҭѰΈ6ƶĴ\jä!4/~ˠ̇ky̟3tNen٣s[;S1 3$&*k D  u AziY 3( )  +/3CguwHU'ڜ]ݭݠޤZ*pl۽A` }95{Q4 / , EP"N$-$ %(+++,'-.-,},,,+*u))('(=(V'&N'l(('&T'G(u(&'\% $#!" if5B9o;%3kLhI3r_vuaOiXHbd:4#eqx r,߶֡6 >#&$}Lr'#n"HO  EV5**9_Wsʦ{Nױ WġRsƂŴœ;ŒoՍׅ^uҺV`ΊB!Ϧbѱ>zҗըK5j8Lk  vK8 9 Um9b)y  /4z4MjOw^5bkM '=;c HR r*M: ""%Agfi8G}3bP+$A#|"B2E&-,Cc43[? M  W7Tm@i*G}Bw! 5)Y$SS*z&vW,sf6F{@hg~.X [X\nd/4r! N"t"4!R k ck)lPds0X: Hi* #()$D3ӓͧϢ7asqFb+ ޴0^Ҕuh>ϨʘӸۑڮYlmҋooUcbԵe̒;]ؑ]KgvovLG@O \ } e I@:'I 6ICH Ba7 +c9S+l^}DZg_4:E;ntrUv45% ' w $?Y`d&65l*4u:QDLGCfdQ * J w   d8Bh C2\q5$'k\f9^H!0Z v>| w @>3!%))!@(V7ٴJ5] ivbg_sڡ}Pu>}I(!$ͯߕ[()̃ЛՉܗD5ܣ5pQ_kئ(ԅ?`9zx]{eS@2J[r{ TXI 02& E '>5M%C/$/@ #4l?=NߤP>!]yf+_L&l$?R n y >`~fe`RoYl*WUC.>=*_/g#$iZT&zM IW*_^]@ aC. @JCb Q1R/ /}$qTm(]vٔںYm~8lڥ d٧?`sL+c8_Fߡi!V &\|Es2Bo; `n |utnIV$oS9Wo% K5]Z/T+:]7Qd`418?A2F7f[HGS_PS>D|n m  UmZ6 Xg]a)vJV`[n~"1Y`MSQq\YHZCXg9n|mHNi M J V ItWBVX]f=Ns7%qq`@ޣiqx߭Z1Nސ^C[@N[}HE ~EJ2(tgG 2}Zd )oWqqK6ToP+Ma>0$ (8w !ZDNG,UnY {x &p>WEW-j x / g=v6)GJ`bte{ A!! """#7#=#'#"#W#{###N$$$$$%+%?%5%(%:%B%K%S%:%$f$##! !Y @+mD*Cb9 # !w/4qRQa_xN{%7kߑ`ݸIݏݽV9܄eڟڗۗqzޘߙeA&y4IObL? @ 89lo_@?Wn.H=?^I {phsL(!.Peq39Gr3)ewK-EC/sKvj^A  %|q } , (yjcE a&pC@#z,+ !!p!!!!+"n"""7####+$3$#$##s##"4"! U  h;/NG[,T*SNduaFaR  aD. scUWk&(g 6 Rޮ13ݻ^u\'5݉۵ۃX۩h=ETG9=&v)(e3-Nr{V-_Jl?+@l`_V >3,7tb>0/E2=8el4C^zo(xv 7qt-O^\#arG8qP)A G M / >P"\Jhr"4 ;)}/+ !!!!T""""u"E" "!!!4!W!i!!  ; MKiF\p`?3|YwUnd  2[&d;9DOoS/=sLn SmOc+W)bWA~ ݂Pf1@/݂7ܸde܃X4L*yq z.TpP?\fQ>gL*!3(5P`PuS{N~rP [%f6w2s {Q`Y)lUy[Xxk oJg JX96# D B  e  ? k k ? e{fyQovS.&B,evN $k8r} t  P_> Pd" \[-^C+ak < l  6 W T I.l: 3j]bd$x-m_7SY4%`<|U%FPh r u;>+54 jRS6 |orKw n G1`HlpJV=3le`ֈD5AK{X(S&߂L;<;R/}=o| lc-gjs9- U]g &A| X% N  k j  { t "'o' 2 X Am Q>}>+<2l~1GV kt}GPM a qGxM+Z;FFDp^hho!C! g<w >_mc3ucP"5 o f8&qpz\5VfLC U M_XV@-fUx8JVպ׶wGhI*ј\ͬyU\C8Z$@7ӟtPDm$kf 6Gy1Mf#bh`% xx v > lr W1 n ?#aYAJ AO OOW" j RC@ ya` ?~Ej8Jbw308qzM7o&Pz+j Uh Hg4`*"""#%%C%$$$$##E%% %%&''=((1(''&.&%#$#^#"6"&"!7!)!b! 4-\   gS? P5a}48HkuݙcN@<Vpa^՟ӏOH0"-L &̸lh-yߪ*gA٠P՞;U߷7,,קs؇ H: ]J-0bGU}F(O" l v@$ ~ 0  ^!#R"Jz S[tgYKmX L(nO[ Y,|@B{Qul%8H Y&aP`dC }/"<NX )T3' ".$d%&'))*+ -S-K--.--..--n.c/0D070;0u050g/.-,a+*)Z(['&%1%$#s#3#"!!a0-tLi6 ( R 8  (y7)-\W,Hd7c rb( fk_ڋ' }98 go7E'A]cpEpK @ ~*{l BzbSe^K1;g#J \HzHv1z=!VD-uF1Z56$:ao 3Z,*7Qq6PENv58!fU)p h O  m  6 V l k K 1 i ( S 8 '  7 n =&f/k?VmJY%k/?r_MK:^}o3P%oKba: X\ THX2u9 >  B W ^ + a . Z  #;HWfnyarhxu_E | N : o U  + D P 2n.` %;{PJLGd8OGUm% &;FU"~\ 3mE7)4Ifj#6r2&qP$xkB{,IjC>yZg9j'd>n ,YD B  R r  D i    1 7 2 3 ' ~ ] 4  v M  9 ad;VAg|`TSktwmd-u1r+1(GsM>nd0 ;e{>}5j.lqmeR=M0*(.@(!2k >X4G u 1 , k " L p  K o Wf9  i  B T  a  t  e C$Fm+[JRFiZ3x5U0]BOux@EvV2[1:V / C s  ! = j  \ v { p " Y =  k >  5G,@y\&62F3WK{ ShagMy0BD i5}opmr0n$m/*KqK#:u$3-CcTMd)o"f8:yC7QN( q|T " b . J ] 0 v r n -"q$5;RYI* Tw~mFV 5 ) r ]  5  XFG0#FcPNQ$0r E/*~nA?3&Zg)p!v ? g  G : z Z S J > g;M9 0 R&1D#7 / 5 - > G y M L f ) #g/ fx`#^@EG7 E'/wq"rc&#}+/C;1 V]sL0H1^6O$w[o3};+m VjY8> B+yt2 T ~aY!$%'N()H)v):)('1'<&%%$"!!T1t%yC) & %Tmb`=!}"ECR)߸ݢuڒڠڭۢ@Qޟ[KY2O=!&!$  = %Oy!-xA !s#$&:()+F-.w//i000y0 0@/8.0-,*L)' &c$" ? ;z4tI 8RKpq_E1BXf M>` A C  e B y  gf t\jup"W!UIT=(1N) dPwrFN2d0hvc_I-bT::PnܚTߋ.tjH.`j;Romg\jy} f- =SyMX4 "$%%I$"S!, =p"h4R Hi _  ` + a m ).cc}Q:xTqxޛ؈uqқ= ʐbgɼ~˄HпFnMѮ1z"eލ`htG\#[Lm Z",Zm!!#r%&<( )z))})(E(o'&%$%*$##$%(%M%%V&>&%$#"""k"y! nVF-@X xj~"7.+w;=g<;H*eKkv *3O4OT,' C L lOY|' F=*OJޱݿrf̲mo}ȮˆԚ>?B(! 5kQp>D Uݘoq5]prlb9[U {[:,3a::   O' ] lr]b! #&O(()j))*-/@2845^6J641u-($a!'u1R  \E#:jT6,zF׵ՂԹӃIը֢vײ| VڊAtA^V8 N 5 3"#%C&N'(*,}.`0m2*4Y5566i65O54420R00091t1111a10/.B..--,x,\+I)'&%#"!p *O[s  Z[XAQfa~EG7|# OIb j[26ezq/ (RXw` C&,dC jH\s Olc85iߢ0ؾՀνɷijïö1eڱO^qs^|$BAgrߜDm`y5j-nI3Q 0Q٢$ܦ6^`<=-N>\u `'G XIq t"5%'((-(&}%$% %$!$##!`Xw$bq<Y 5VRh>4&(:ؠY7YzJmC*l~f`qTA~L0*l:2/r۽S׊Vmԩў͜ɫǞɍ ܈Lo mv hw$gP'{k=: F=F|Y,+Dޝc 7e ki$2{-&\  v{W~R 7#"; p7%YF O g*n~q=54+vdߩB_ ^ 5-Jd:M2RL ,6p` / B!"G$%q$G" O!m#&(*k,.\1>33s2/M../=0/Q/U/000/.+))''/'U&%#-#"/#7#!HD*iNfE ^ B S  _ z H j   M  7  B 6 T  d 'I   % > ?  } =+&2=_\kc ޱ5t&bK,'/ &_\Q mG_V5D;v>.Dv @Z Q ' Q O  R Z.}qf% )K  "  ^ {t#_`]mJB"=RHmID&t5:*/T.>UZ@    =C |wu[T   h"#D$$ &'((0(''(b(''&G&&(()(( ((((d(':''L'L'&%$x#""""!x NG]d 0M2 t 0  5 ALV [Z Fh]9>mW]i0+ @Vc'pckb~ ^8B_(o9wY/jdٕ߳JQEޢb{em߼-! 9Pv&bK@un$HcRM^D, A#/Dc~"w?7go1g]?kN/iuQg  #*Nz  v@ z #   `sa@ s Jh e Z $ }SQdV~2 ^ b1  RS]_ l 9 @GL Y   qqGTWI(A08KCmzn4wc{8FVFkC  UU p Te +w3:py  xVmO.8-xi\}V.j<|  >7e$qTg:sg7Pz8h BW-ޤ%Pn޲V/^o+IN; ^B0 )\RE&@0  @VH  Q 4 a   $xg Y    5I b8|  q;\a~:|2 D[;P Tux7rPko  ZZV(h*5 8[\k  : i zSV? 19_y27 Ce1'[ \m3/ v*!cpE g?:|HEyw7u / ]1 P&!SI7k ?hVs_A,o|#_h $LM r$'E "hQ@w6y@ ,f = )6> %n U Ysl T 4P4 e# ^q 3 1r a cd_E  q4 A= @ F tp9U@W - E[ 04. 0 1$?<  |[~v' W "it? G <+Z.*M iA' ?'LU O /  T.K = lXx9 , /JB6R!qO. 'wt"uS:QBV,tG 6<'D @ )1q )@A# E _fJ q'ZDJ,yO4b # ^/X l12 r' j 7b Lb_ R wR < e/c   T+(~I  x+ :t f% 0mo 8 ZW`Jf} q  C-w NR*6mT{quK,$q'{  kE;32 Qg +  XX t1#4D ]$e zN|D $4+UIx)!y zW\6 ="L3 & ^> |08~  #(? /  T4TDXdK Kt% $ VPg \).FS>  #b ^h` <J rV r 1_ !\m7}5   n :Y*awB6 "/ I uL wKc pw{v7 @9NaR(u7Zx< 8L n $H0PD 5F%#pJ: ~ J@)Ah if=R3\ C>u^"{ 8+U-j; <7 ~ /Z.B T ih"  >$jG; * UG#6 e ` p%_+A4z @ c& H )QP,`=,> h!2|q^ f f b.)z"lf^ u^`l # > @ d)AG%<qK)b ^W2JMn,cA?{>LX.j N 6cR!xG$OO)s z N X% Pw}VR3 WUt(TvUD],AG6\e6vYsFe[7pGa_E4dHJdSUo |0( .v?8>`Ru!> _9E}E_W$ft!= MFu)I@g83Co>cba'&BkcFs{{6k["m4Dy([?LX/%|eS&7%O,"% AW  JlB9Mb \ % i%-6Yjx%6"!4(+v]v.jJzG c I@ x'\ = < ZD n&  }Kirw d6j: 57m /@9ls2JN  :e} 7| [ a-S j +kk~GPY] Jt|%;(!iQf s`q#i I"x h-N8f; m6t)pS. + pGO4)g ?pj!bV' Z io / k  } q l) i# \q5S,SB~@P d 9lP jC ==QeC r RW[  {Kur0 { =`.\\d.`M ].Dtm{JHXy  q,2jtm6u ~1.l4 6 ;Z'O_h 9n<5 mqk)O 6NJS:)f8 5 0 bX 20y  l ~ gx  DH+UO ~ QY ri i B(V e! -jMK[Fe4S qOy@-_ }  2 f;>B #O _>roA >)87 I i7m %`bsfO,]X  20y \U __E = }j7 T]] O*4~C,\N A~ Qu EObT \  xI M +x3 3Ln3  I\7 i> 9Q' vm2  . 4=>c Jf'Az03&J1 qUS& "wY E`iMnAQWjDDTM9+>" '+* w\ }VM9;`, )Uc =YH :i)Y_Qo)~NB9$nUDn pjA tDs< y6 "|llFzxp-){E k fkoW7]1x~J ]\WL&8ISA_F>Q 2  /;>xlA\ KA)J?vr5= Nl;:3=G^.AW[u:zp7 W,i .w/| !WxP9Ve})Xik{hfIml|boL;#'d OT.;M; 6}5F?WP*o#T"H %sk@`PrIX*}<N4NcUKni"`n&+!1sUD:v<Z.;R'#s$|,XBItak6[l "6%F>peHv 5Cy^\~|v-.p*.}1 E   a B  N-4=f 8"=&S(**n* *7+|,+*1)'%!h  $(gz0X6@`&H-lpּؠ3-M]%? A 4)9d !"f##! Jx?; c @ &/$ :?s 1 WpNz8vH}ϊF=h^&#gʸ u ̂N ϐЖNѻҭҒӕԬّS݁ߕO@=!4l I + o &V' E d u E b l 06}6  H F _H ] U J +H !"i#)$$]%%:&q&&l&F&a&&&&&%' '&*''''l'`'s''c'''%'&&e%$#"! "xK#D], %qQڱܘU=083# S&),,+0*4(#EGe m Z^Q ٬FvƑ*^š-ɭ =^ʶɬ*8{QhK,V/ ׏pIf6%  F!#%X()**o),'%#n" #!J,@ Z ) ZW"r@Ubԏd|q/:ɗjʵ|ʹϜ6U~NLul b  '%F?*'. p 2av ;,MPD-/X !  a !n#$%%&())**r+:,,_,,$, ,+++,+5+V*))'&$#q"I!8  qM;[* m'ANI~1VFE /L6u s * X U 1 I _ QS:"ң 9}DG) "R"a&))+_+8(`!kK p uX ӏssGᾴھDĪ,96;l(شپըHA!8H@BS! !n"#$&v(L)(l& #! #\ߊݾQ6NSښ*ܨHޥއ b݅1ߥb[s|P z Xwz @2 U% ;Y)T=WkNY| v-CC:kg=(5  SZ%!-#$E&s'9(v(('9'&%$z#!P.  th : QN4QcP"D\{H"~rNRQ1o=   $UD_9Y j l } q % I M? f }ӁFƵЯk~ !s'd+.}/00,#:L _[0"rlřÃhLüNmЫ"\A-@E!-{! }2h#v')d*p)<'$"O!')I eZ&lc/x02LٟۖN \5SZbD+>9w 7 ? l;0 S _Qp(D'GjS_%q_##HDV $   , 7h"44UgG3=:   <L  GuaUh\/Z k!!!!!@!  w{B15mh  ; G ? [g  t u f fP5PM@U  R ,&I="'i+./l/~+#R1 `XkٚфYċs8[‹DèĚ(ƾk΁UՂwd)ڐ`1"4 ejk!K"!)K$yD \ ;k\}`xݮ^v,0dLe9AO/=}0zp B ]X\7Ifߋߘc3*~;$X_ R 'P H  r 0 d 5 # F(`FX6=q@4K}z S (q W #!%!  [>fh^:<GlBmL'+j,@) 1 ; & s XIj]eA:Nm0v~?Cn4&޶[uX 3 b $(O*+)r%\C' E#~:iݥԆktǑIW˜z–~[{˖ՅMݿM?9Omt~ { @Be5   (M\>KZ\;o44eLfU,Wl8hD> N"=,o tEXbO1dKC^K~HT W K . _  %(0[@Q=P A v ^ m } 2zHeXJ^V|OM3'`paiiGjV3ks_TG~>" E @ <Vn,X#.[="1G1c8<!.#9 1C l i[L^; 4,;"SÂn{öĞaDBɁmՓݺ%WhWkvcsT ^CKZuX1 %?BiϘƏRdďŶ./]7kZ,߮1~WL! 2 v   ]&2Hm_AFC.H5NidMJ&dK#}PMfNg IP#q&N_>! <[+*1<V0'ma"UQ 9 c=( [{oKQ 6/o;]8 Q`d_.?2<0&_,7 e K e ?iE_DVQ,G; Q ? @.x3Ja*,zc  k Dp0#') (# c/z5DZŬıËâĐFLMˤ>yD/PC]L cAhf OL'F3u>bPh<5?Qh/Kh@_kC02DW3kBcTNA`p-)r ! _M!'HvkCD4[XYH<(.p!0n 2k'Jw[`cJ 7=lj3 t h v D 5  ^ n  X ?  Wa$lXQ]B  F*$'*,*%p0x gͲʝxŗI|5Ξԑ=p:nC' 'n@J.3zp&_q`D.W$5W _RhN(,WHG1nwl5;I3-8-L~Ft68/ f9X=WT ckx*ZCiIqP/&)=_E#d  I !$J3d~ma&` 7-+N=g*8$ps, t=@t [ h 2 [ Z  E  e S  s Z ;8E4dl S  " k%"*-//->']  d f " V$&͎Gopöċw7ӧݾ}*^|%"&(MOJ }w!.pq]7{o4Z"bK&DV{.t Zn)& ' Kau< |&Wb& 278hnuF1 y ~  x { o W VL$P D1+0S"%S*`-^/0{1/(I h@` ^1s+#;Чv.Ǵ|cy_QK5KH|POgyoQ9<-UPpg% ,NS&fg@vZ@#)U~ :,upiGEIO2RjFgm+Q32L 0zkb^GK R|- 9 C ^ ~x&co6+Cn7oz0 B, 9Wpba,KS~]nx"$~7v  P  3 ] 9  8 y B M $r3D*  *#(,./0/*" T X܀?1+̞ȳ$JĞU)ˁ\֘"XJR|8i?Iiy=XEab\#*|C=kV:rIrl1A TDs{; `^j ]R\JV:v*G^H(Keu%#b7WA<hsK H< w > h~96~&@j<3 Wr %q>2vs{;bt{<v&FhuY5,E5`. c8M`U7  S2߻2  +~"$%i)K,+& &(UQAؘѴ)~@ɍ#{ĵfŨXΘ֚+-$tWMoCt=|aS(;dWV+L@U`rZw'X}P4]QVmGf3)^L8&$*Dw,I(B;U<+RW+I1E:},]7AV|l7^'D{T K 9 H%m0* PFn Q?&MN ''aF8=a[]-0]D|-> ?  X ; ;  Y1|  *Pi~i!fmY H"!S"  GngLڻҴ;ɀ[}(\(cƮNтjLve "7AToNZh|L6'- $n >?T-1FIim%n GTTguH?j`Nc ?#uyl-P\bHI:KG3*Y(HGDu7 =M=Sz z ( f   VrCO! mDN) We!NT<tP+\<SUP589m4 \ ? Q F ?  :m\5 O H !>p":8+Yz'YChݛK3+RA%q P"pC@ + zZR9Y%Ә&|/ozuŦQǑ4xΛvӪ!ٚڣtsM(Z' $ 2>HLxq\JaPE::Fkf5f!B# #efmdXh^Myn%&efQ[hqQs}}d  i  6  U :i !/~ bpP On9$:L#$+VrL/(1!Ox4uQ$o%Hik; ^  { ! H  +  ; L*@pOr2FK:3:m[PdZ({;fd&2b[ S\/8 `d*&G)T\+LHJ|w!sX>+bFe,]X7]dv]r*.m ~,VMV/0O%fycd1 1mx81WPZU~=M)VBIq4 U B h Y g  J + 2Vm`p])tKJx.#+QV&Fi,*[uiNkgp1 yHAqgv^-a^N.da Z F S   L 8 {5+E'b!vy\ t%q oL3}&5Mz#T\ |5WX;1nJ./o#-G>^y0:,j7=Qh9bV<%S [7 Sk3{,Kdr8>ocv{|Y+"_~faF!e=3>,HO6]7,/<N ^!d8eX _ek0]V @6ral<#6T0 C om8lD%'/-,5 ^ eT rNPJ~/Qf|S 6X)@C (Wlp{3yaF6RI!NL*LBA_9c8Z%JXuNbVF&Eg`Jlk3Scog=AU/ZH\nx@f|,d=bB #+M2"N`tIe gh /om<>&!al['2s1)<D-,*75RRc~l_Bz'85[ Ej?3b?4Q=B,df}z1vA le7 2Dx-< )qO,6)}e@a KgN""+M7hH6LEPx$r?VoCYMz1i&S^V1-?#`.K;,_7B5Mt5MUtqPM<@Knd:d}V RHZG{(:vA_ uY?xh \{+ !-oZvY`k"Xiq 9T|W: +pk7cg+# B8y. #Pm2de3J;+.Ri-:;I QxE!-:F%n z8&pUC!rxu:%h -VD?t~[MW??KJ..bovkY -E7)KN71Z9NF?Kj ,s2Q8;Kf}FO[me28VXuo4SIAQ'9Lm#,5B=J;VlRT$!-(:A@NRNSii_j[F+)4/0|aVdVPM^rS9;@+ps_`qZ* mQ]bEH?@7  ySP>)+%|w_ckY/;2$myeO:/( oZanlM5<-/klZ@8QIB/,, | /9/G?F_oqLIn{u 0<:0.ICCQ]bdboq\ros  &*3#  ##35+$DE7;G]NCQ]ZkmSekjqhmy~lgeu|frs' 3=FAKW\dSCB\dkdZdny~vy|v}}~}yzvsafgvlvwxusw}qorlvwww    {}~z~iz}wu{sojxqmrbe_VS\TZe]i^JisXBYTKJII?D\^PNK7[`A/2660$+.4$#!/"')'"       }|w}z{pqwqcou[e{l]^mkqae}moyslxzlrekmoln{|yzxiek~qFI9 6puXuss|z~yj0f_9IZH~w=YR&,A^TD2Q*qqtH5 arXtWZ  $|UxGiH$^7Z^i`xJyP}Mmmc({ /O N(N]ZHSH_u wQ Z(N}Y ]iP91 }8:NWHz n$b  c<bR8yv]43:}d |y'pS@9#L YRDU{D1vx~a P?2wXsP*E.p3[K(4kDv*"/TL^A?W=fN$ITXqkI+}>VW|[9GKA_=Z(Wf`QC8 q-aFkG>}.wL(D>I4BcO1KO[<>nA/U Lj} t p k= Q8q 4sQ(:\$m}} `LlpAuDz|N GZN?mcqQw+ix O mi{ Ao0%2"!}L|<;YLhnuL~-! 6N0e&/f>i`_M^15|6/A1W$oo?^ 6fD)WpTa'GK% B4OX4# 56X4DN,~2r:L|}F}9A0&"GIh`/u^/yt#8O|taU<~!r] De<\n6A9~_ !pn*Y>kAb+c15.##D#uo9"D-me^5;p4pv\ 3FluVC f{ncG^]`7y` e i $   ;'dk~ Nqov.k"J   g  K v *I pkv:!$ z{sf ;)@~Dnk[XF"ka^| M%S4m +Xc=z[< pYh=Wh c K d +TIq#[ob_N~?w+4.h@zjrn_|7_ v JZOkTnHdf_rc<N)68HS.!Xo t7TN6Y/ GcI R6U dR`AZ 6U7Ciya[V\7v  -1y?r9b}.Cnd!a#$%&'(F))**)^)t)e)i('&&%%%$P%%%B%%$#""!w MH  s l U4g}"uy#Mk6UW]WYm,f{->! $Wg^AIY/WO~uk  Mw|E3gEp~o-mXk`  w +; 5&sn T| g0T'=/Xmmeuh, *,"|o !""""5#{###|"!!!T! a p]<Wul,&6O(\ > % y dV&|p),hqXd^*s. w*a+P#P9Q^Ci>o(C&;I U o =   Hj0]'f=y#k3&0gcy:U &c S:9:(+YDc J0 1  "8I&_1M}> )T@;ciW^4C # X[Z>0gwCt^RIy*'X7?Jap3xoE)aucT(#9-hxNw hBCrqspU  y :  9 p  ; l ['Cc#_vdRAiT!,]lGzO45Pt $  C " Z ${;[zV~W+ |bW\m]!zUZ# a;9#&L-g:+ߤc9ޝCi|ޣ=:hߝߕߛߩG\oH^~h=DRBD^C.s)(H^(~MWh|Nw^qQ&  n  . _ B`^ ],m"ioR_NbH}#q3Oz,2KxiGpee HasHf O x o + V Pld2?? F CBGY7E/ ky\'cRD  b"Mw <[Lak}q\K'Vo-*z:o Al T}{6{Wp|    @ S-clKL3-KAe`GEIVLQW^2%zE _ X P z R-*Ee SNPuk!~5 KLxAU0mvޑ)ܴe!ۤڽٲ-ס׻:K׊knvg]NJnחרה׋ך׺cعn$ڊ'xz݅,޲'ߊSe;_7crxvlEZx&K8a8n *3uA>  r o 0 . < .W(e>DU5{9ME691$('ZvA"yde?6  x \ t 2O4X&8hCu [ $ X  <  y  m } G E 3Km/\#^EM7VP8SOxhL7BjX]\I\E3kK b\S!F g 6&,.ETQ4BcPndaemz~kaKa`8.+9c _Q6||6QJ{ x-T / l O  j 1JWHC]{/i Bcmwa;*CmXpV"+eS  N W O`7Z1f(-d?3&6bh#LS>mZrhX~B/;2u;Z܉ܷڤoۧ۔ۆ۽MOۤڢcAAH3BRF&^ݪ#Xwގ(9)ߍj,= }>^At]cd|wq:[#}FD/I_N$#{M % u P A  X *DiN:C70!2CooLTQ ee9}BwSqWD Zk, u V < Q x . _ k\(L* /:;~ uWBO$!hbKB15o'IG #0|3Uif>3R[lI hq# ,Pf<t}@dOPb}#Nh[PH#|>+ CRo;4J3 ]u  o : j8fF!!DBfr4o/^3 @E@Y " d ' v m]nG~@ k6w'JCT2Mk5o]ebQY>VߕݲdQۯۊ۠ۆ$a4&ڕP @ڗ%`rr/Vޠl`'f']5c#^vP$W4}P~e{QTG(sCZ_"j. f = 3 ^ J*ax9t!)u BmdC6$.)n{~)WZ"R>j:~DVY   )  6 u B { i  d fVWg>"Q%}Q;i2mbq v')zI#"{}o_fU4- 7Ic5[yOX acz>y9*&C`[e?FXtUS+mgx 1~  T \ 7 QHI!45*jq]Q`K9>-{9:n0@X1 i  % V Yi\<2 uNu!`7hD4fOy@W?(g1)jd|LP;>nވݕVܾ܌bcܐ~XfiXJF))3T܁ܑBݘ7ވF߉#lm?!4Qt4n?aa\muo 1 k $ 5  4G.t $?LiE}pPObU:y(#Tj4l>|| f ' C "U) >  \ F  > { r ' ,o~2Kk=t{fY/+]tBcODnkYG y9{"XwW@:=Tg#cp;vLP~<58;xGs*""u`F-5zYI6^%xE :yRO* 1 b H  d ZpsaZ;3J|ZPD4  I 10_`bv  # G ` q pI,0KfaRPyAb7ZW6$VDSnQDWcyhBl?rߙgH ߻Hݵ݉OܤܮZbgݒ=ސ޳޵<߆FQQ`4x+ ,jYH6]Wbu_"Jc kx0@AZ\ S  s D  v ;wB`KCx9`lvqeh^8" ' P<vJ f    g epS`$(q1H *e q t K5WYv,!D=kk(817"^5Bd$M QJ|| g O l #E5&#S C wE=?=U[d %mGg> e[46h1Kxl-)xd"5f1C x+OIYMLW~]m ^  V f R N Y m   = < %  u 7 Dc68BU4= 1 _ m3' \H 1 x / t  U ^)Q@Qaxd4jK0PL3rQnN[/4b~L'=;jtsB!5e!o`w|}0oJeV/77IG&Jq&(5&y'''5+m8m! B   $ J k I W i  _x `5  |  =}en0B}PZ- 3 ^ IxOr# Q  s h " i - +  n c X=>=Oc#S 0DE !! "l7 R.M gZw=C$U!%he]OBvnF "{ox'rE/ $> [ p 9U|Rj l04/#|f?vi~[i$% L ! cR &1 ` &     4 ] J (  ^  , @'*Pv5#1ZCOb{i.:U8^V l q5s#C*./%,^nN ? 'Npl6t~]+\ >ef?=]viEA c6aNRvN'ޜPp؝U٠@rݑގRݙݻݜޒIVky>[]H2>RteditXq)},F0t6 vQ~Ys!IDJ`l n  W   U M P X3m2c'P[x x  l * X  ` &ioE N  i & 6X"H}b i  P ?  / U  d . y k  = d !Ot$Kkv &j+u}9/ Ahz=xG'cp7ESEo0_U<h    | DchN;cx@; H0Pf^V !W!qM  < & x + k 4 " k m  z   ) = Q #  p e  t^ UJ0! U W  k c /  " , " #  $  ? v Oh l a Q E   sA/% s !8v h VG7l];r,Uqy w5~{+Z%x{`OuWzU} U  !Q8  z " m dh+:_c[~pT"l0k ~'0wKR-J\b'(UA+xooyi\8@7x 7AK>JGd8bINxvh#':wr~*{0$*_!c`>>,Bn`n4ii Bs"7|s1iHDt;B +oC0E`4:M? 1  % y T T p B ] } \ k 2 h T/y  K` r*Eo d(L[-E>!FP  ' T u * B B "   -  B } r R  M  L{^:[(P|pU ku~iPp_H{pG4 8aJ8&39Vgr{X d? 9  ) a u t k Z . j ; E ?j $c$W4 8kKjo w , R (3|-L])q2L g X + G YN ~~W5/\ 4X!yN529/52:R\x* /<4GPRhobH)a*U(G>t>TesLm9n+LS#}'RZ9laal^RdI5]-Clsa}D4n/THqGv!;Avk#9X5y0s%]B M  ] p 1  f m   2 N C 45yc &V+  0 ] K & c v A   Z5? X[ tJ.F Z[^X{ ?s#wWlz 8 Q r ]  tsu(}U4 ?IC:\S.K=X'p9CN| Q"]_?2} & w % W  R&t%z/9T=1$R,cO/ ' 3 + 4   =!X~yv#2PyxNG*8~:m(!(S]S9]+qYu_t tPGnT7)^UfkUW)V2VC!@5<$jNY 8TGU[[_3Q IAb<K3_U%(jl>Gj.C=n;a6I,g,+.KnV<,9 =OKw { y Q  p #   v 9   s W ? Ky;H@Q$ x ] ' ) Z&  ! ^tO L6\[SMV]xD+^GV("&'J4 :  Z^0*tdRTf`Z 1 7uWcL-t;^a$q0 .)F&\64eeb!ZZF$a 9 l s@/.HEHA9c8) vA' D 5 n S l Fl4{I,xL&c'P)Wa(,(5QlfFT  7f /|0~3a#Em#W #s,G&w0,3,o|; mdqS4`!UbY_.f_YO BqpF`1g0zWR".Su)`_>R[nznU>MWO! w_ODhQ7+-#5[oieNV ]VrgLz|cvdob+0oR"'owX3[*1K,} w  | c n >2f} B   3 TBZ+A{V5qkb| ]UlGC w  g2 ?Zs#'M  y xZB^lJQLq^wt2@t#X!b!:D7XF4n_ߺߡ"Xd\" hag1)vz /q[AB~ruN(>C! C_B [ WzO9(BJ d1.  QS  B3LF!=0OB G < h**g$]X%'y  Bt!;1=m/u"$=wK z3['v= D=)FA?/xyy*DqJ,r'U]:71-i,Aqsdf&/X/+,)rlW*NN"&w"/cvb:G|55TWFp=+<G ^  m 5  / ( "LZ Vy:h>V (Kj}Q&-147(899P961h,'# mO G z NJ D UF,4{Sn'^;0dtFygy6:Or'z XkgIRC6 }عپۊ,G?IF ! ] .?Eh > L0\H2^3MW/q )xL=MT= J{L` y = {, FmU#  _qwQbs>1 + K } W ( e qdrN    4 [.Y_VIw"`^V hF_!e@U?5Il*Cy #]Q:f-, \k6JnDJ/ ^|hnM>e$qL?#0liwETJV0<^bZGJ4~}  ^JiO^WlI 'm$#!!^$(-=346h89: ;Y;:,6g.&? \ x PCVQݳ$=Eׂմ}Ս؈fZ}e6 }BqUqmO!$')T++*)'5%!Wv |Yp 5CG  v . C +vV ` ] `u>g P`'WoQ31p [cXn#__. xTaHa ==C  M dj9%V Z D q $ ~l6 E+ " ? >T9 %L `  ' \C2[HM^j9 S o`e{RzJEo f"Ch#)oZ\p'HMwg&#T[y^y|k*9tPyH$|[_uLYj\t m \'@m7F4-~m{whz/ j2_0{u,|s;-S1bV+(O+'b[6 B  '  /j1p%6l !),- .,-,-0368::;:s70'l5 JQB*&hcbVv "}=+-H`) !Ynn]!I$k&'(d))))('&%$(#  V  dahM>ECeS1=v j  X8]-{/ m3DX x".e<'fK t   l D l L Q P  " r/uK Q V >$jRxY:!D")tI+S J ^  Z oa3VrVEx .  Q Pk+/ rD6@J,DqJe 5`Cg.R[.^mez] 9  t l  0 R  X Q w # = f qk9&\Ib T}|]\!*Xu6}F,JB2e Ip 6X%U1Hq9*j!OaZ4}&Q;I5AhYttf@ps(*d=-C3K",kxL;vRpcEs YQ 5%-Z3x79C:85430N/-*&$QH ]i]G<S>N,#aa'y >G!$_')*>*)('%O#p 2d_=Gc\%_D<_  z-RKk(rsNH-n%#~d=:LmtO*minT,dNp&6_^35AI0BaI4  JN ]rA 8  O  -2 l  nRm h.WkiD4U{H>pRu L F ; B (d# ^ C }O@<Z;Bh%ByjuX(l ^QrTH+r I8fj}>s2iA3  wq-5@>CHJ _ $-297850-p,)# ?aI/ '  ^ " /  $ B ()x}By1W  w=%vs9lr !" $8%&'&%# OV{ >'oV[1g!/o  s . ) ;Y!(hurn%pPw#& > 9 '  = ( ; 3 e 5(d8`;nu M`( W tdva^$o3H=)z2 * j  k b-z|BTf; + vw`9%)p,-gp@pznyfXoXrSLB{ XwSyKqoKhd]n=")!.j\xTgV7k/Fq&`P'/366\3.(#UaRF'A| gj;i mMV}Ia;*LCv;) 4 4 9 }w d @"F$%'.'&&&\&$$#! Z*X\TY[*  h+d}6 BP-dJW><RAUw! 9T7me1b-|Kq L ' | V r    ( T /|)x]=LDq8_)P zbj}xFnC}9'WVT   > Z % ~ ~.* y !_z7P?5d%Pc@"*)\6dP%BjJc_Erw=1mM߉ߜߋߌ_ߩ}h;RH;U_'%P`|[Wnxq83dY~6{N8kAi/`fn}ckg8L% e;<J}`6| &)+)&O"X   V  J!("!r kH+nO\Wpmfo=( S5@E#XyPxsg7 2+  kxYQn 3mdOlm'Hhu6O7JY>O'Hmpa5"4JyL o:0v O   Jk}:= i  h N BMp!e~Is_pTNgO 1#7Kf 2~qU[idc#9F[p z J I % +&pgr{{D'3A 4 +iox~qYnDOrN4P8 ,b;B 1 F  5";Jx&F bh tm$.`v W 6 p w^] [   #%%YN9")c+kOq+ b < O z ^  # & y  c 0 e o | 5T9  3O_x}}w@npA Z}1Xm-ez! OV0 F M d ~ X f ZMNPRR\CFf nl " [ 2 P E ;  ! a  xnGB^ /GyZ,Kp D+_f6zhc} eGT?^qRrT.MzV-2 zJ29rh?sNA#Xo4mE{8YcGJfA An;} K x 4 S B > t 2Heys[m|^qxr[.0- t f d < ,      k 1  ~ o ^ ` %  ~ U  s B 8 / " d>vr(i4Q^6 }lW1') l\\GQFNfobUSju[buUG+ [>i_uKYnK8' rmrtV(fK8'^H%TBDX6'nOH* d]fD29( {ns[?B"& lub9AYO>E%j]\L#1 -00&$-#% +-2?Qs'#378:=CMTEZ~nox#>Qbu+`ps0;Ro ,3c8KEXWUvd@^bUMOekf[j+?K4"',-(C`*&;HI_in 4Wy| />KQ\R_kjggrswxr :<:VVVR:;2GF*#(!3&( |`^eicO;) maVP1!52!$wy}|ndA6A@"  e^R:s{zPK@%-(nPRC:>*,(9web^NKCG?04)    $-,A@:OV<QCE:>P87I$4W>Eev|h~l`zz~ih|vs|ywfbor[`||n|vy|~v}}|{agiVGP?,54 'q Cwm+O& 9I$f(f\D,?]FZ1`'Q<?iyirJG.#t7+{|c X3M>CL|/<\LSr Ql)8R0w epkg=b`7zY"h"/ B>My>`: R6mAjCLt8a<cPdUkj;8#6A]1ZkF7n\2/+n;N>3 g5&YW}r#r<^'H8iPp|X<= {}sQ\{y kf5 f7Y  ^ N398x?n !Qt/ IF?j6oz!?m1YK  d #N %U! Y>Hc4 8U%T3 T"u ;|V( nvF"3x= 1QY nu#=< u%`FBi2pi\$.'8avQc' 5V S(Z?o* 9/j}U?$r0 bTwMZ0VY:^LAA E%{^_ ZV & % o!6K c%Db | L[' t M6z!~#i }:GMiB1^=~7! ] Boq oht [e tD{P&`]C#Lo}  - u 7C'\+ ]-fycBh Zg#ZL] <D"]3lnsQRvi\2R;Q &p )  |> HW4 #H. CO# ZB   G5`yC2 GU'%*he 2W$ Esp h rZWQq = p/ #,Ro )^$D B{Sg8x 8 X.% 6=x)SCe'U/97 Sc.u)6 k@  }F@  eYW \Ry ^   :+ jRE ,* `/ + l NH'qc|?eeNOj|ttx A kY#p^ h^  r5F1lC _T tM &i8FJ[`~ dk jQ VXM ()> KmGIS{K 3z\SG^eM rJ 6Uz rB  +C\<5 v= wfqu^o \S+ 55z.NT    @V#Hn u JH u: }3_oGShf s pT k ,Y  kt> ->~1R:l b 8~s ZWD |% *Zf} V:z@#3 ~aiKT )%^sQ0)dD   7xG 3 a ;9 i L _Q _PM  0yT Pm m$d {VP g,R4^ ~cfW sRIA;rZ yHlTM VJw&i`r q01yv}~uDL$Y m_P:0sF!@sl 7V s $ jb 7*Z>C()+m8m,K>( &Dird,J_"  |H+  j|x#+ ? >P}g _, uidgEV#c#W lJA *#S `'OE_z& IQNf q<-3 ? V| i7I p/ v 38iymI >:hz %!o`eYfqxAd> ~ <)  [LT 5-M.GiNOS b : 9B!OiVn6oR*$|eN  xNcVC{ / !, O @4 M gJA $f@%n?iMfxn C nah dh/ R>Cd>_%a y @2 ) l [{qqnAg c<%R"] P`@QP8 N|Hq T<3 !MtW,L\0Yc:gYd..)DDzC@V]VnKh o Q6AGuj QH2F  E) 5Cj=#>XFz<vs Rf ^fEPzsC1O3,T 60!m_hwL 0uds9 G b d`T + T]- Ur~ q- og Gh=YxM!Gp<4B|#o^OpLw)~XPs qH vzrHP! q$ (j KA *8 K Q#e7HfA+'p@e>|:X/nCrPO .e\KGW`6Mt vqdGMJVW-XLh eRkXvJ /D9N 3{  np4O^/E<8)qFVH_%?IG z3Y-KT0G h_y ;wTh/=me obw{4/M(7Z9' &%@*6'| eK: L ^*ag5C, l"Q> `~JK1*T ,!TKTa-hG:fo|yI !C 1wS3MTz3 TSULc ~o L J}NdQRw2;qR:3F m#`$c$HsUYx+ta7@x2UB<Qa= 7#2)n)D9!4)4%P1`0i"l"Te>l]1m,)G.&Z{EN\8;Tm)|J=%3 [-@JQkC-~t8+ BNC6BgIL\/m ?y,|pj2l3O& a h < ^  )u1z(d Pap]-~5J,Rg#77i>EOMDX~72`24#$kc-c1a N1!B/pz e@`yas?A"&iy_^e-=R&+Vt >Fa)4=bb;9v&m` ! f ?   9H_Hp\Z@t0 .G "/}"gF/i]`m&|@% 4 v#d{M"   $"!E h fm@+ ?Uod-l~cs";)(V&Z X O r3 Z q O"1/!bz|?X Aߖ`Im*QLۀmIڿNة׸Uצַ֢՜*7d?Ոs8ս֥Qn׭TS׌׏NذנإXs@܉\p_;ޘEmkXE-$!(HiC}vJ%J q3bJ-P0/ j2 iR 17%&u+./,+)8&!i& y ; Gj ?##P" > 9p Z Y K.,:Q, L_k9 S[^z! 1u`dCJHVz  ? v .-h\5Fefj j*UI ?=h\*X'M@ qZZc *I |  ,]6 AVE=ub SsF!3"/""c"W"!!E! w3 Gtzv V2E_'FWy70+ +   0 u m 9   e!o{-l WEc&u?KY,vfzےC;؋qY#k\Սh`KNo9kФғєzeTgSOmXԇԒoֹ R>p3fT!?ڥځ!ܔ݄޶RHTZ"^ ]B$ cAm&Df{wjtCRd@k0s8  u n 8 l Z9 O  ; 4? U iA05 V!? \k#1um3F("$&%$" +=j:WguP F/ f | A l n-8 YdbN6{2Usz~ 7   F %    r ! M6 G v SuYZ=20X4u~r m>#fIeNZqXQ4?MJQ1Z!#O{7yLf&Zf|  Kn$Z Lzw5= P?z[I mV !"{""#c##Z##"""!c!&!  x-:3SwEQ1w Fc <  % ~/a'd$eUMSx'"!+GF [rGPݟ $a؞z*ؿ,Eg,(Iыј@ӠӾӸӔӕvDWcbsҵӾӉՠ ֝;I:*#{׬עם#qڹۅnSpi!_kX\-!p;x'jIr#j?:%/x d w  ` } z h~Y.8l#`L `g !"""!);] v#$#x! vOrmpq|Xfh:F$h Due#}%| h.czEbcmHT|^~iJpvS3KLB @tadj;@W .i *-#6j|2w Sey-ni'2=P}SpC4.(kG v |  JO q%,luJ;{t0 Q) l N H 1!! < m zx,e363u3 g Y = W GORk}np;:. K!\BgQq1_ݗ0ۃ۵iy٣qFS֜rB=m84hֆ|օֻ֦֟jaofֈ Q׻cؽGXUـ"Nڢq7ܷܒq=߆ߚ߳.`H31=\7^"OK##)!9S@6>Pm,<7   C P #[RXZy hXB{V&q"q!q Lz ZN|T(F}g4u8S> d: B ouU)6vaPvY j9R6sZuJGhx5,LZQZD! 8zy( atu9a62qpc:9I olT?y;M;Vo sc o  _<[V<~{!~3.r{t.LU!f+uv F `  HK~XaeYP-#8Zfolx!2i@anei"0޼ݼݐ)ݙ!NOK٤vQ_֍9K*֋ ^^B >N׈w&{c6oۙۋۓ8fܡ)Rޗ`G\*2HZ I6jL>>k6@ J rS>1Kyjz, X  } OA9Z:U4Gn,iU6npcj+Wk^AK>}j9R!pk7javsxOvs Q o   i.?y?@t+ } i>!2{gd=9&&eABe&fv{|!y)I9TzcY;(Oi*oG?OwF m S  B R i  + # 2 l  S h ~ 2 Q    " / J ] R C 4 ? % , ' V  u F '  6 | * hImL1kG9cIUAC6vea|'R sm"QrnxR ; Z " z L z #^YT_.&MeP^umeM,76XRSNM<*Q i -  >  ; R . m   dA)y7k0]#a1\P2fD(fU^K~8B3Big{D[br*/9P`"@VQ_loodozzws[pvERmgdb@JT. {p_/2@&q]R3-tob9cJ2Q>O1pcO?~rQ9n]C%!XVINV9%&+!0, "$)0&$*89LmbLLJCXF(/7, 20