pax_global_header00006660000000000000000000000064143446002320014510gustar00rootroot0000000000000052 comment=7ec9055e464e2179117813b2358d8ed1c0e669ec pd-mjlib-0.2.0/000077500000000000000000000000001434460023200132055ustar00rootroot00000000000000pd-mjlib-0.2.0/LICENSE.txt000066400000000000000000000432541434460023200150400ustar00rootroot00000000000000 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-mjlib-0.2.0/Makefile000066400000000000000000000005731434460023200146520ustar00rootroot00000000000000# Makefile for Makefile.pdlibbuilder. # lib.name = mjlib class.sources = \ src/about.c \ src/metroplus.c \ src/monorhythm.c \ src/morse.c \ src/n2m.c \ src/pin~.c \ src/prob.c \ src/synapseA~.c datadirs = examples datafiles = \ $(wildcard help/*.pd) \ VERSION \ README.txt \ mjlib-meta.pd PDLIBBUILDER_DIR=pd-lib-builder/ include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder pd-mjlib-0.2.0/README.md000066400000000000000000000020701434460023200144630ustar00rootroot00000000000000Mjlib is a small Pure Data library created by Mark Williamson. This git-fork of the Pure-data library mjlib is cloned from https://git.puredata.info/cgit/svn2git/libraries/mjlib.git, which is the svn-to-git from https://sourceforge.net/p/pure-data/svn/HEAD/tree/trunk/externals/mjlib/. The objects in the library are:
about
random generator based on anchor value and percentual deviation
metroplus
metro based in list of intervals
monorhythm
rythm generator outputs beat, accent and sync bangs
morse
converts ASCII to dot and dash bangs
n2m
note name to midi convertor
pin~
paramerterized random signal router
prob
random generator governed by time interval and probability
synapseA~
compares a signal to a set threshold
For bugs found in this version, please report them to me. Mark is not responsible for bugs introduced by me. Fred Jan Kraan fjkraan@electrickery.nl 2022-12-09 pd-mjlib-0.2.0/README.txt000066400000000000000000000050721434460023200147070ustar00rootroot00000000000000mjLib by mark williamson mailto:mark@junklight.com http://www.junklight.com The code is free for anyone to use under the GNU GPL. But if you use it, please mention me somewhere - its not like its going to cost you anything :-). If you need support you can try mailing me at the address above - I can be quite busy but I will try and deal with any queries. General notes This library will grow a bit - there are a few more objects that I want to put into it. There are currently five objects: pin~ - randomly delivers the input signal to either the right or left outlet with a given probability metroplus - allows complex timing bangs to be delivered prob - generates random events with a given probability monorhythm - basic rhythm pattern building blocks that allows polyrhthms to be generated quickly and easily about - delivers a number that is "about" the same as the input number. mark williamson January 2002 ___________________________________________________________ history: 2022-12-08 : - Updated Makefile to properly conform to tips&tricks - updated maintainer email. - updated version to 0.2.0 24th July 2016 : - restructured help patches - changed version number to 0.1.3 - prob: added checks and defaults for interval and probability - convolve~: removed this non-working and inappropriatly named object - morse: fixed crash in [rewind( before [msg(. 6th April 2004 added code to the Pd CVS and made all of the objects compile on MacOS X and GNU/Linux. 1st February release 2 added new mode to monorhythm (exclusive - allows the beat and accent bangs to be mutually exclusive) added about object 1st february release 1 added linux build files - not properly tested 31st January 2002 added prob and monorythm 30th January 2002 mods to metroplus to allow it to work just like metro is complex time mode not needed 29th january 2002 first release containing pin~ and metroplus Outdated build and install information: GNU/Linux Run: "make -f makefile.linux" and all of the objects will be compiled individually. MacOS X Run: "make -f makefile.darwin" and all of the objects will be compiled individually. Windows There is a VC++ 6 project file included an it builds fine with that. I haven't tried anyother tools as yet. However there is a binary version included in case you haven't got the compiler. To install - add mjLib.dll to your pd library path: -lib C:\pd\mjLib\mjLib and copy the contents of doc\mjLib into [pd home]\docs\5.reference\mjLib that should be you done. pd-mjlib-0.2.0/VERSION000066400000000000000000000000041434460023200142470ustar00rootroot000000000000000.2 pd-mjlib-0.2.0/examples/000077500000000000000000000000001434460023200150235ustar00rootroot00000000000000pd-mjlib-0.2.0/examples/polyexample.pd000066400000000000000000000023011434460023200177030ustar00rootroot00000000000000#N canvas 488 354 600 357 12; #X obj 120 193 monorhythm; #X obj 157 270 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X msg 155 91 start; #X obj 111 274 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X obj 200 228 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X msg 228 91 stop; #X msg 220 160 2000; #X obj 286 194 monorhythm; #X obj 323 271 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X obj 277 275 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X obj 358 226 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X msg 374 161 2000; #X text 42 16 An example of a polyrhythm ( 2 against 3) built with 2 monorhythm's; #X obj 321 121 loadbang; #X msg 305 160 2 1 1; #X msg 170 159 2 1; #X text 89 294 beat; #X text 148 292 accent; #X text 250 293 beat; #X text 313 295 accent; #X connect 0 0 3 0; #X connect 0 1 1 0; #X connect 0 2 4 0; #X connect 0 2 7 0; #X connect 2 0 0 0; #X connect 5 0 7 0; #X connect 5 0 0 0; #X connect 6 0 0 2; #X connect 7 0 9 0; #X connect 7 1 8 0; #X connect 7 2 10 0; #X connect 11 0 7 2; #X connect 13 0 11 0; #X connect 13 0 14 0; #X connect 13 0 15 0; #X connect 13 0 6 0; #X connect 14 0 7 1; #X connect 15 0 0 1; pd-mjlib-0.2.0/help/000077500000000000000000000000001434460023200141355ustar00rootroot00000000000000pd-mjlib-0.2.0/help/about-help.pd000066400000000000000000000064521434460023200165310ustar00rootroot00000000000000#N canvas 382 79 558 541 10; #X obj 0 0 cnv 15 552 40 empty empty about 3 12 0 18 -204280 -1 0; #X obj 0 354 cnv 3 550 3 empty empty inlets 8 12 0 13 -228856 -1 0 ; #X obj 0 421 cnv 3 550 3 empty empty outlets 8 12 0 13 -228856 -1 0 ; #X obj 0 458 cnv 3 550 3 empty empty arguments 8 12 0 13 -228856 -1 0; #X obj 79 430 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 79 368 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X text 107 430 signal; #X obj 0 543 cnv 15 552 21 empty empty empty 20 12 0 14 -233017 -33289 0; #N canvas 242 347 428 75 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 206 546 pd Related_objects; #X obj 512 4 about; #X text 8 23 random generator based on anchor value and percentual deviation, f 66; #N canvas 273 106 494 344 META 0; #X text 12 155 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 135 AUTHOR Mark Williamson ; #X text 12 25 LICENSE GPL v2; #X text 12 45 DESCRIPTION make numbers that are + or - a percenage error from a given value; #X text 12 75 INLET_0 float; #X text 12 95 INLET_1 float; #X text 12 115 OUTLET_0 float; #X text 12 5 KEYWORDS control filter; #X restore 501 547 pd META; #X floatatom 134 139 5 0 0 0 of_this_number---> - -, f 5; #X floatatom 134 311 5 0 0 0 - - -, f 5; #X obj 134 82 bng 35 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X floatatom 215 140 5 0 0 0 - - -, f 5; #X obj 79 392 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X text 107 368 float; #X text 107 392 float; #N canvas 0 50 450 250 (subpatch) 0; #X array \$0-about 100 float 2; #X coords 0 10 100 0 200 140 1 0 0; #X restore 337 59 graph; #N canvas 1 80 450 300 arrayWrite 0; #X obj 0 0 cnv 15 425 20 empty empty empty 3 12 0 14 -204280 -1 0; #X text 6 1 Array writer; #X obj 235 152 f 0; #X obj 261 153 + 1; #X obj 136 130 t f b; #X msg 235 129 0; #X text 259 129 restart; #X obj 136 82 inlet; #X obj 235 82 inlet; #X obj 136 174 tabwrite \$0-about; #X connect 2 0 3 0; #X connect 2 0 9 1; #X connect 3 0 2 1; #X connect 4 0 9 0; #X connect 4 1 2 0; #X connect 5 0 2 0; #X connect 7 0 4 0; #X connect 8 0 5 0; #X restore 134 329 pd arrayWrite; #X obj 209 310 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X msg 215 115 10; #X msg 275 115 100; #X msg 246 115 50; #X obj 134 65 metro 100; #X obj 134 50 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X text 321 187 0; #X text 321 59 10; #X obj 137 120 hsl 64 15 0 10 0 0 empty empty empty -2 -8 0 10 -262144 -1 -1 0 1; #X text 226 310 restart; #X obj 134 227 mjlib/about 10; #X text 162 368 - The center value of the generated number; #X text 160 430 - The generated value; #X text 96 467 default deviation percentage; #X text 162 392 - The percentual deviation range of the generated number ; #X obj 0 488 cnv 3 550 3 empty empty more_info 8 12 0 13 -228856 -1 0; #X text 96 497 about makes numbers that are + or - a percentage error from a given value. That is it makes numbers that are "about" the given value.; #X connect 12 0 31 0; #X connect 13 0 20 0; #X connect 14 0 29 0; #X connect 15 0 31 1; #X connect 21 0 20 1; #X connect 22 0 15 0; #X connect 23 0 15 0; #X connect 24 0 15 0; #X connect 25 0 14 0; #X connect 26 0 25 0; #X connect 29 0 12 0; #X connect 31 0 13 0; pd-mjlib-0.2.0/help/metroplus-help.pd000066400000000000000000000105641434460023200174500ustar00rootroot00000000000000#N canvas 383 79 556 531 10; #X obj 0 0 cnv 15 552 40 empty empty metroplus 3 12 0 18 -204280 -1 0; #X obj 0 356 cnv 3 550 3 empty empty inlets 8 12 0 13 -228856 -1 0 ; #X obj 0 466 cnv 3 550 3 empty empty outlets 8 12 0 13 -228856 -1 0 ; #X obj 0 503 cnv 3 550 3 empty empty arguments 8 12 0 13 -228856 -1 0; #X obj 79 475 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 79 370 cnv 17 3 50 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 0 535 cnv 15 552 21 empty empty empty 20 12 0 14 -233017 -33289 0; #N canvas 242 347 428 75 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 206 537 pd Related_objects; #X text 8 23 multi-interval metro; #X obj 483 2 metroplus; #X obj 79 426 cnv 17 3 30 empty empty 1 5 9 0 16 -228856 -162280 0 ; #X obj 107 285 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X msg 132 61 start; #X msg 140 81 stop; #X floatatom 315 60 5 0 0 0 - - -, f 5; #X msg 327 79 500 1000 200; #X obj 114 62 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #N canvas 275 223 494 344 META 0; #X text 12 155 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 135 AUTHOR Mark Williamson ; #X text 12 25 LICENSE GPL v2; #X text 12 45 DESCRIPTION variation on the metro object -- instead of providing a steady pulse it can provide an irregular beat; #X text 12 75 INLET_0 bang start stop; #X text 12 95 INLET_1 float list; #X text 12 115 OUTLET_0 bang; #X text 12 5 KEYWORDS control bang_op; #X restore 495 538 pd META; #N canvas 681 429 450 561 snare 0; #X obj 184 223 vline~; #X obj 171 438 *~; #X obj 142 302 cos~; #X obj 157 140 t f f; #X obj 142 282 *~; #X msg 157 114 70; #X obj 172 532 outlet~; #X obj 226 512 switch~; #X obj 226 464 env~; #X obj 226 488 > 0.1; #X msg 280 201 1; #X obj 176 64 t b b b; #X obj 176 10 inlet; #X text 330 471 ajf; #X obj 184 281 *~; #X obj 171 415 cos~; #X obj 116 480 s~ \$0-fb; #X obj 77 304 r~ \$0-fb; #X obj 127 353 +~; #X obj 76 380 *~; #X obj 185 306 *~; #X obj 128 328 sig~ 5; #X msg 195 114 6; #X obj 157 166 /; #X msg 184 201 1 0 0 \, 0 \$1 3; #X text 294 449 efficient snare drum; #X obj 112 89 del 5; #X msg 112 114 90; #X connect 0 0 4 0; #X connect 0 0 14 0; #X connect 0 0 14 1; #X connect 1 0 6 0; #X connect 1 0 8 0; #X connect 1 0 16 0; #X connect 2 0 18 1; #X connect 3 0 23 0; #X connect 3 1 24 0; #X connect 4 0 2 0; #X connect 5 0 3 0; #X connect 8 0 9 0; #X connect 9 0 7 0; #X connect 10 0 7 0; #X connect 11 0 26 0; #X connect 11 1 22 0; #X connect 11 2 10 0; #X connect 12 0 11 0; #X connect 14 0 20 0; #X connect 14 0 20 1; #X connect 15 0 1 0; #X connect 17 0 19 0; #X connect 18 0 19 1; #X connect 19 0 15 0; #X connect 20 0 1 1; #X connect 21 0 18 0; #X connect 22 0 23 1; #X connect 23 0 4 1; #X connect 24 0 0 0; #X connect 26 0 27 0; #X connect 26 0 5 0; #X connect 27 0 3 0; #X restore 132 284 pd snare; #X obj 133 308 output~; #X obj 132 198 mjlib/metroplus 1000 500 1000 200; #X msg 337 99 500 250 250 500; #X text 107 370 bang; #X text 162 370 - start metroplus; #X text 162 388 - start metroplus; #X text 107 388 start; #X text 107 405 stop; #X text 162 405 - stop metroplus; #X text 107 426 float; #X text 162 426 - the interval in ms \, just like metro; #X text 107 444 list; #X text 162 444 - list of intervals in ms; #X text 107 475 bang; #X text 160 475 - generated on each interval; #X text 96 512 initial list if intervals; #N canvas 521 79 442 300 original 0; #X text 18 28 by mark williamson (mark@junklight.com); #X text 18 61 metroplus is a variation on the metro object. Instead of providing a steady pulse however it can provide an irregular beat. It takes as its control a list of numbers representing intervals in milliseconds. These are the time between each "pulse". So for example with the initial setting below (in the metroplus object itself) - the first pulse comes after 1 second the second after 500ms the third after 1 second and the fourth after 200ms - the next beat comming a second after that because the sequence starts again.; #X obj 0 0 cnv 15 425 20 empty empty empty 3 12 0 14 -204280 -1 0; #X text 6 1 metroplus; #X restore 384 328 pd original text; #X connect 12 0 20 0; #X connect 13 0 20 0; #X connect 14 0 20 1; #X connect 15 0 20 1; #X connect 16 0 20 0; #X connect 18 0 19 0; #X connect 18 0 19 1; #X connect 20 0 11 0; #X connect 20 0 18 0; #X connect 21 0 20 1; pd-mjlib-0.2.0/help/monorhythm-help.pd000066400000000000000000000162051434460023200176200ustar00rootroot00000000000000#N canvas 382 79 556 531 10; #X obj 0 0 cnv 15 552 40 empty empty monorhythm 3 12 0 18 -204280 -1 0; #X obj 0 356 cnv 3 550 3 empty empty inlets 8 12 0 13 -228856 -1 0 ; #X obj 0 517 cnv 3 550 3 empty empty outlets 8 12 0 13 -228856 -1 0 ; #X obj 0 595 cnv 3 550 3 empty empty arguments 8 12 0 13 -228856 -1 0; #X obj 79 525 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 79 370 cnv 17 3 85 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 0 629 cnv 15 552 21 empty empty empty 20 12 0 14 -233017 -33289 0; #N canvas 242 347 428 75 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 206 631 pd Related_objects; #X obj 483 2 metroplus; #X obj 79 463 cnv 17 3 17 empty empty 1 5 9 0 16 -228856 -162280 0 ; #X obj 170 265 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X msg 170 61 start; #X msg 177 81 stop; #X obj 152 62 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X text 107 370 bang; #X text 184 370 - start metroplus; #X text 184 388 - start metroplus; #X text 107 388 start; #X text 107 405 stop; #X text 184 405 - stop metroplus; #X text 107 525 bang; #X text 8 23 multi-interval multi-output rhythm generator; #X obj 170 188 mjlib/monorhythm 2000 2 1 1; #X msg 249 60 1 2 0 1; #X msg 258 80 1 2 1 1; #X msg 338 81 1500; #N canvas 681 429 450 561 accent 0; #X obj 184 223 vline~; #X obj 171 438 *~; #X obj 142 302 cos~; #X obj 157 140 t f f; #X obj 142 282 *~; #X msg 157 114 70; #X obj 172 532 outlet~; #X obj 226 512 switch~; #X obj 226 464 env~; #X obj 226 488 > 0.1; #X msg 280 201 1; #X obj 176 64 t b b b; #X obj 176 10 inlet; #X text 330 471 ajf; #X obj 184 281 *~; #X obj 171 415 cos~; #X obj 116 480 s~ \$0-fb; #X obj 77 304 r~ \$0-fb; #X obj 127 353 +~; #X obj 76 380 *~; #X obj 185 306 *~; #X obj 128 328 sig~ 5; #X msg 195 114 6; #X obj 157 166 /; #X msg 184 201 1 0 0 \, 0 \$1 3; #X text 294 449 efficient snare drum; #X obj 112 89 del 5; #X msg 112 114 90; #X connect 0 0 4 0; #X connect 0 0 14 0; #X connect 0 0 14 1; #X connect 1 0 6 0; #X connect 1 0 8 0; #X connect 1 0 16 0; #X connect 2 0 18 1; #X connect 3 0 23 0; #X connect 3 1 24 0; #X connect 4 0 2 0; #X connect 5 0 3 0; #X connect 8 0 9 0; #X connect 9 0 7 0; #X connect 10 0 7 0; #X connect 11 0 26 0; #X connect 11 1 22 0; #X connect 11 2 10 0; #X connect 12 0 11 0; #X connect 14 0 20 0; #X connect 14 0 20 1; #X connect 15 0 1 0; #X connect 17 0 19 0; #X connect 18 0 19 1; #X connect 19 0 15 0; #X connect 20 0 1 1; #X connect 21 0 18 0; #X connect 22 0 23 1; #X connect 23 0 4 1; #X connect 24 0 0 0; #X connect 26 0 27 0; #X connect 26 0 5 0; #X connect 27 0 3 0; #X restore 249 284 pd accent; #N canvas 911 419 450 561 beat 0; #X obj 211 301 vline~; #X obj 165 434 *~; #X obj 165 409 cos~; #X obj 164 385 *~; #X obj 164 362 *~; #X obj 181 218 t f f; #X obj 165 338 *~; #X msg 211 279 1 0 0 \, 0 \$1 0; #X msg 181 194 70; #X obj 181 244 / 29; #X msg 274 196 33.9; #X msg 237 196 30.5; #X msg 312 196 36.1; #X obj 164 461 outlet~; #X obj 220 508 switch~; #X obj 220 460 env~; #X obj 220 484 > 0.1; #X msg 360 197 1; #X obj 290 85 t b b b; #X obj 252 112 t b b b; #X obj 215 142 t b b b; #X obj 233 26 inlet; #X text 284 445 efficient kick drum; #X text 321 467 ajf; #X obj 233 53 t b b b; #X connect 0 0 1 1; #X connect 0 0 6 0; #X connect 0 0 3 1; #X connect 1 0 13 0; #X connect 1 0 15 0; #X connect 2 0 1 0; #X connect 3 0 2 0; #X connect 4 0 3 0; #X connect 5 0 9 0; #X connect 5 1 7 0; #X connect 6 0 4 1; #X connect 6 0 4 0; #X connect 7 0 0 0; #X connect 8 0 5 0; #X connect 9 0 6 1; #X connect 10 0 9 1; #X connect 11 0 9 1; #X connect 12 0 9 1; #X connect 15 0 16 0; #X connect 16 0 14 0; #X connect 17 0 14 0; #X connect 18 0 8 0; #X connect 18 1 12 0; #X connect 18 2 17 0; #X connect 19 0 8 0; #X connect 19 1 10 0; #X connect 19 2 17 0; #X connect 20 0 8 0; #X connect 20 1 11 0; #X connect 20 2 17 0; #X connect 21 0 24 0; #X connect 24 0 20 0; #X connect 24 1 19 0; #X connect 24 2 18 0; #X restore 170 284 pd beat; #X obj 249 265 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 329 265 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X msg 329 61 2000; #X msg 64 61 exclusive; #X msg 65 81 nonexclusive; #N canvas 278 251 494 344 META 0; #X text 12 205 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 185 AUTHOR Mark Williamson ; #X text 12 25 LICENSE GPL v2; #X text 12 5 KEYWORDS control bang_op; #X text 12 45 DESCRIPTION designed to allow simple rhythms to be generated ; #X text 12 65 INLET_0 bang start stop exclusive nonexclusive; #X text 12 85 INLET_1 list; #X text 12 105 INLET_2 float; #X text 12 125 OUTLET_0 bang; #X text 12 145 OUTLET_1 bang; #X text 12 165 OUTLET_2 bang; #X restore 503 632 pd META; #X text 107 423 exclusive; #X text 184 423 - beat and accent bangs mutually exclusive; #X text 107 441 nonexclusive; #X text 184 441 - accent bang supplements the beat bang; #X text 107 463 list; #X text 184 463 - rhythm pattern. 0 = rest \, 1 = normal beat \, 2 = accented beat; #X obj 79 491 cnv 17 3 17 empty empty 2 5 9 0 16 -228856 -162280 0 ; #X text 107 492 float; #X text 184 492 - measure intervals in ms; #X text 160 525 - beat bang; #X text 107 547 bang; #X text 160 547 - accent bang; #X text 107 566 bang; #X text 160 566 - sync bang; #X obj 79 548 cnv 17 3 17 empty empty 1 5 9 0 16 -228856 -162280 0 ; #X obj 79 571 cnv 17 3 17 empty empty 2 5 9 0 16 -228856 -162280 0 ; #X text 96 606 default measure interval followed by default pattern ; #N canvas 613 532 431 353 original 0; #X text 23 28 by mark williamson; #X text 23 52 (mark@junklight.com); #X text 28 129 The monorhythm object is given a time interval and a rhythm pattern. It divides the interval into the number of beats in the pattern and outputs bangs as defined by the pattern. The performance time of the entire pattern is given by the time interval.; #X text 30 212 The pattern consists of strings of the symbols 0 \, 1 and 2 0 is a rest \, 1 is a normal beat and 2 is an accented beat. A rest produces no output. A 1 produces a bang on the leftmost outlet. A 2 produces a bang on the left most outlet and a bang on the middle outlet (the accent outlet).; #X text 30 296 In order to synchronise multiple monorhythms there is a third outlet - the sync outlet. This does a bang at the start of every bar - which can be fed to the left most inlet of a second (or Nth) monorhythm.; #X text 28 77 The monorhythm object is designed to allow simple rhythms to be generated. It is also constructed in such away so as to create more complex polyrhythms quickly and easily.; #X obj 1 1 cnv 15 425 20 empty empty empty 3 12 0 14 -204280 -1 0; #X text 5 2 monorhythm; #X restore 374 309 pd original text; #X obj 374 331 mjlib/examples/polyexample; #X text 327 282 sync; #X obj 170 312 mjlib/output~; #X connect 10 0 27 0; #X connect 11 0 22 0; #X connect 12 0 22 0; #X connect 13 0 22 0; #X connect 22 0 10 0; #X connect 22 1 28 0; #X connect 22 2 29 0; #X connect 23 0 22 1; #X connect 24 0 22 1; #X connect 25 0 22 2; #X connect 26 0 54 0; #X connect 26 0 54 1; #X connect 27 0 54 0; #X connect 27 0 54 1; #X connect 28 0 26 0; #X connect 30 0 22 2; #X connect 31 0 22 0; #X connect 32 0 22 0; pd-mjlib-0.2.0/help/morse-help.pd000066400000000000000000000111201434460023200165300ustar00rootroot00000000000000#N canvas 626 79 556 531 10; #X obj 0 0 cnv 15 552 40 empty empty morse 3 12 0 18 -204280 -1 0; #X obj 0 356 cnv 3 550 3 empty empty inlets 8 12 0 13 -228856 -1 0 ; #X obj 0 476 cnv 3 550 3 empty empty outlets 8 12 0 13 -228856 -1 0 ; #X obj 0 554 cnv 3 550 3 empty empty arguments 8 12 0 13 -228856 -1 0; #X obj 79 484 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 79 370 cnv 17 3 50 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 0 588 cnv 15 552 21 empty empty empty 20 12 0 14 -233017 -33289 0; #N canvas 240 348 428 75 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 206 590 pd Related_objects; #X obj 79 431 cnv 17 3 30 empty empty 1 5 9 0 16 -228856 -162280 0 ; #X text 107 370 bang; #X text 107 484 bang; #N canvas 234 413 494 344 META 0; #X text 12 185 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 165 AUTHOR Mark Williamson ; #X text 12 25 LICENSE GPL v2; #X text 12 105 OUTLET_0 bang; #X text 12 125 OUTLET_1 bang; #X text 12 145 OUTLET_2 bang; #X text 12 45 DESCRIPTION convert text to Morse code; #X text 12 65 INLET_0 bang msg; #X text 12 85 INLET_1 float symbol; #X text 12 5 KEYWORDS control morse converter; #X restore 503 591 pd META; #X text 107 506 bang; #X text 107 525 bang; #X obj 79 507 cnv 17 3 17 empty empty 1 5 9 0 16 -228856 -162280 0 ; #X obj 79 530 cnv 17 3 17 empty empty 2 5 9 0 16 -228856 -162280 0 ; #X obj 138 312 mjlib/output~; #X text 8 23 convert text to Morse Code; #X obj 137 180 mjlib/morse; #X obj 501 2 morse; #N canvas 556 423 607 506 dotDasher 0; #X obj 53 100 hsl 80 20 10 6000 0 0 \$0-s-fr \$0-r-fr frequency 9 9 1 10 -262144 -1 -1 0 1; #X obj 214 28 inlet dot; #X obj 358 28 inlet dash; #X obj 165 313 outlet~; #X obj 298 313 outlet speed; #X obj 214 208 line~; #X obj 214 124 delay 50; #X obj 214 104 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; #X obj 358 123 delay 50; #X obj 358 103 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; #X msg 174 164 1 1; #X msg 214 164 0 1; #X msg 318 164 1 1; #X msg 358 164 0 1; #X text 229 79 dot; #X text 365 81 dash; #X obj 102 191 osc~ 440; #X floatatom 6 157 5 0 0 0 - - -, f 5; #X obj 164 247 *~; #X msg 6 56 906.1; #X obj 6 29 loadbang; #X obj 53 120 hsl 80 20 10 1000 0 0 \$0-s-sp \$0-r-sp speed 8 10 0 10 -262144 -1 -1 513 1; #X floatatom 51 159 5 0 0 0 - - -, f 5; #X obj 403 83 * 3; #X msg 73 56 50; #X obj 73 29 loadbang; #X obj 259 52 t f f f; #X obj 0 0 cnv 15 425 20 empty empty empty 3 12 0 14 -204280 -1 0; #X text 6 1 Dot dash factory; #X connect 0 0 16 0; #X connect 0 0 17 0; #X connect 1 0 7 0; #X connect 2 0 9 0; #X connect 5 0 18 1; #X connect 6 0 11 0; #X connect 7 0 6 0; #X connect 7 0 10 0; #X connect 8 0 13 0; #X connect 9 0 8 0; #X connect 9 0 12 0; #X connect 10 0 5 0; #X connect 11 0 5 0; #X connect 12 0 5 0; #X connect 13 0 5 0; #X connect 16 0 18 0; #X connect 18 0 3 0; #X connect 19 0 0 0; #X connect 20 0 19 0; #X connect 21 0 22 0; #X connect 22 0 26 0; #X connect 23 0 8 1; #X connect 24 0 21 0; #X connect 25 0 24 0; #X connect 26 0 6 1; #X connect 26 1 23 0; #X connect 26 2 4 0; #X coords 0 -1 1 1 85 40 1 50 100; #X restore 137 263 pd dotDasher; #X obj 137 238 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 168 238 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 200 238 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X msg 27 70 1; #X msg 78 47 stop; #X obj 8 95 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1 ; #X obj 27 93 metro 100; #X msg 27 47 start; #X obj 228 313 s \$0-speed; #X obj 78 70 r \$0-speed; #X msg 165 75 msg this is a test message; #X msg 200 101 0; #X msg 165 49 msg pure data morse generator; #X text 184 370 - message clock; #X text 107 388 msg; #X text 184 388 - message to be send; #X text 107 405 rewind; #X msg 350 49 rewind; #X text 184 405 - restarts current message \, or sends last message again; #X text 107 448 symbol; #X text 184 448 - character to be send; #X text 107 431 float; #X text 184 431 - numberto be send; #X msg 230 101 11; #X text 160 484 - dot; #X text 160 506 - dash; #X text 160 525 - end of message; #X text 96 565 default message; #X connect 18 0 21 0; #X connect 18 1 22 0; #X connect 18 2 23 0; #X connect 20 0 16 0; #X connect 20 0 16 1; #X connect 20 1 29 0; #X connect 21 0 20 0; #X connect 22 0 20 1; #X connect 24 0 27 0; #X connect 25 0 27 0; #X connect 26 0 18 0; #X connect 27 0 26 0; #X connect 28 0 24 0; #X connect 30 0 27 1; #X connect 31 0 18 0; #X connect 32 0 18 1; #X connect 33 0 18 0; #X connect 38 0 18 0; #X connect 44 0 18 1; pd-mjlib-0.2.0/help/n2m-help.pd000066400000000000000000000056341434460023200161140ustar00rootroot00000000000000#N canvas 502 87 559 457 10; #X obj 0 0 cnv 15 552 40 empty empty n2m 3 12 0 18 -204280 -1 0; #X obj 0 314 cnv 3 550 3 empty empty inlets 8 12 0 13 -228856 -1 0 ; #X obj 0 357 cnv 3 550 3 empty empty outlets 8 12 0 13 -228856 -1 0 ; #X obj 0 394 cnv 3 550 3 empty empty arguments 8 12 0 13 -228856 -1 0; #X obj 79 366 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 79 328 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 0 421 cnv 15 552 21 empty empty empty 20 12 0 14 -233017 -33289 0; #N canvas 240 348 428 75 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 206 423 pd Related_objects; #N canvas 758 192 494 344 META 0; #X text 12 125 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 25 LICENSE GPL v2; #X text 12 5 KEYWORDS control conversion MIDI; #X text 12 45 DESCRIPTION note to midi; #X text 12 65 INLET_0 note; #X text 12 105 AUTHOR Mark Williamson ; #X text 12 85 OUTLET_0 float; #X restore 503 423 pd META; #X text 8 23 note list to midi, f 78; #X obj 524 4 n2m; #X msg 174 48 note c6; #X msg 195 114 note D; #X msg 200 136 note 7; #N canvas 941 222 433 300 mtos 0; #X obj 70 31 inlet; #X obj 71 267 outlet~; #X obj 70 132 unpack f f f; #X floatatom 70 205 5 0 0 0 - - -, f 5; #X floatatom 110 205 5 0 0 0 - - -, f 5; #X floatatom 151 205 5 0 0 0 - - -, f 5; #X obj 151 166 mtof; #X obj 110 166 mtof; #X obj 70 166 mtof; #X msg 187 143 0; #X obj 70 228 osc~; #X obj 70 94 t l b; #X obj 110 228 osc~; #X obj 151 228 osc~; #X obj 187 120 delay 1000; #X obj 164 67 t l; #X obj 144 31 inlet; #X obj 238 267 outlet; #X obj 187 166 t f f f b; #X obj 70 67 list prepend; #X obj 0 0 cnv 15 425 20 empty empty empty 3 12 0 14 -204280 -1 0; #X text 6 1 midi to sound; #X connect 0 0 19 0; #X connect 2 0 8 0; #X connect 2 1 7 0; #X connect 2 2 6 0; #X connect 3 0 10 0; #X connect 4 0 12 0; #X connect 5 0 13 0; #X connect 6 0 5 0; #X connect 7 0 4 0; #X connect 8 0 3 0; #X connect 9 0 18 0; #X connect 10 0 1 0; #X connect 11 0 2 0; #X connect 11 1 14 0; #X connect 12 0 1 0; #X connect 13 0 1 0; #X connect 14 0 9 0; #X connect 15 0 19 1; #X connect 16 0 19 1; #X connect 18 0 3 0; #X connect 18 1 4 0; #X connect 18 2 5 0; #X connect 18 3 17 0; #X connect 19 0 11 0; #X connect 19 0 15 0; #X restore 174 240 pd mtos; #X obj 227 240 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 174 266 mjlib/output~; #X obj 174 189 mjlib/n2m; #X msg 181 70 note C4 E4 G4; #X msg 188 92 note C4 D#4 G4; #X text 107 328 note; #X text 162 328 - list of note names; #X text 107 366 float; #X text 160 366 - midi note numbers; #X obj 261 238 print; #X connect 11 0 17 0; #X connect 12 0 17 0; #X connect 13 0 17 0; #X connect 14 0 16 0; #X connect 14 0 16 1; #X connect 14 1 15 0; #X connect 15 0 14 1; #X connect 17 0 14 0; #X connect 17 0 24 0; #X connect 18 0 17 0; #X connect 19 0 17 0; pd-mjlib-0.2.0/help/output~.pd000066400000000000000000000041341434460023200162220ustar00rootroot00000000000000#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-mjlib-0.2.0/help/pin~-help.pd000066400000000000000000000060001434460023200163700ustar00rootroot00000000000000#N canvas 504 86 559 457 10; #X obj 0 0 cnv 15 552 40 empty empty pin~ 3 12 0 18 -204280 -1 0; #X obj 0 314 cnv 3 550 3 empty empty inlets 8 12 0 13 -228856 -1 0 ; #X obj 0 357 cnv 3 550 3 empty empty outlets 8 12 0 13 -228856 -1 0 ; #X obj 0 412 cnv 3 550 3 empty empty arguments 8 12 0 13 -228856 -1 0; #X obj 79 366 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 79 328 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 0 454 cnv 15 552 21 empty empty empty 20 12 0 14 -233017 -33289 0; #N canvas 240 348 428 75 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 206 456 pd Related_objects; #N canvas 756 193 494 344 META 0; #X text 12 195 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 25 LICENSE GPL v2; #X text 12 175 AUTHOR Mark Williamson ; #X text 12 45 DESCRIPTION take a single signal input and output it to the left or right output at random based on the probability set ; #X text 12 75 INLET_0 signal; #X text 12 95 INLET_1 float; #X text 12 115 INLET_2 float; #X text 12 135 OUTLET_0 signal; #X text 12 155 OUTLET_1 signal; #X text 12 5 KEYWORDS signal random; #X restore 503 456 pd META; #X obj 152 260 mjlib/output~; #X floatatom 258 121 5 0 0 0 - - -, f 5; #X obj 153 187 mjlib/pin~ 0.5 100; #X obj 521 3 pin~; #X text 8 23 random based signal router, f 78; #X text 107 328 signal; #X text 162 328 - input signal; #X obj 79 390 cnv 17 3 17 empty empty 1 5 9 0 16 -228856 -162280 0 ; #X text 107 366 signal; #X text 107 390 signal; #X text 160 366 - first output signal. Either input signal or zero ; #X text 160 390 - second output signal. Either input signal or zero ; #X text 86 432 probability (0-1) and switch interval in ms.; #X obj 208 81 hsl 64 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144 -1 -1 0 1; #X floatatom 205 101 5 0 0 0 - - -, f 5; #X obj 261 102 hsl 64 15 0 1000 0 0 empty empty empty -2 -8 0 10 -262144 -1 -1 500 1; #X obj 154 60 osc~ 440; #N canvas 1 79 450 300 original 0; #X text 19 13 pin~; #X text 20 55 the pin~ object can be considered to be similar to the pin in a bagatelle game. The ball upon hitting it has a random probability of falling to one side or the other. The pin~ object takes a single signal input and outputs it to the left or right output at random based on the probability set (right most input). The interval at which the outlet is choosen can be set by the right most input. Setting this to 0 or less means a different output is choosen for every call of the dsp routine. A higher value means that the output is choosen every so many milliseconds.; #X text 19 30 by mark williamson (mark@junklight.com); #X text 21 199 note that no panning or envelopes are applied and therefore low choice intervals will add "switching" noise to the output.; #X restore 433 287 pd original text; #X connect 10 0 11 2; #X connect 11 0 9 0; #X connect 11 1 9 1; #X connect 22 0 23 0; #X connect 23 0 11 1; #X connect 24 0 10 0; #X connect 25 0 11 0; pd-mjlib-0.2.0/help/prob-help.pd000066400000000000000000000060411434460023200163530ustar00rootroot00000000000000#N canvas 498 89 559 457 10; #X obj 0 0 cnv 15 552 40 empty empty prob 3 12 0 18 -204280 -1 0; #X obj 0 301 cnv 3 550 3 empty empty inlets 8 12 0 13 -228856 -1 0 ; #X obj 0 344 cnv 3 550 3 empty empty outlets 8 12 0 13 -228856 -1 0 ; #X obj 0 381 cnv 3 550 3 empty empty arguments 8 12 0 13 -228856 -1 0; #X obj 79 353 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 79 315 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 0 471 cnv 15 552 21 empty empty empty 20 12 0 14 -233017 -33289 0; #N canvas 238 349 428 75 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 206 473 pd Related_objects; #N canvas 756 193 494 344 META 0; #X text 12 169 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 25 LICENSE GPL v2; #X text 12 149 AUTHOR Mark Williamson ; #X text 12 45 DESCRIPTION designed to generate a random event with a given probability at a given interval; #X text 12 130 OUTLET_0 bang; #X text 12 5 KEYWORDS control random event generator; #X text 12 75 INLET_0 bang start stop; #X text 12 94 INLET_1 float; #X text 11 112 INLET_2 float; #X restore 503 473 pd META; #X text 107 315 note; #X text 162 315 - list of note names; #X obj 513 4 prob; #X obj 223 280 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X msg 223 54 start; #X msg 223 77 stop; #X floatatom 275 74 5 0 0 0 - - -, f 5; #X floatatom 328 94 5 0 1 0 - - -, f 5; #X obj 204 54 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1 -1; #X obj 278 54 hsl 64 15 0 1000 0 0 empty empty empty -2 -8 0 10 -262144 -1 -1 0 1; #X obj 331 74 hsl 64 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144 -1 -1 0 1; #X obj 223 210 mjlib/prob 500 0.5; #X text 107 353 bang; #X text 93 391 timer interval and probability; #N canvas 1 79 450 300 original 0; #X text 20 42 prob; #X text 20 63 by mark williamson; #X text 18 83 (mark@junklight.com); #X text 21 111 prob is designed to generate a random event with a given probability at a given interval. Every clock tick (set by time) it generates a random number and compares it against the probability to see if an event should occur. If so a bang is output at the outlet. ; #X text 20 201 The probability is set as a value between 0 and 1 Time is measured in milliseconds. The messages start and stop - start and stop events being generated. The prob object can also be started with a bang.; #X obj 0 0 cnv 15 425 20 empty empty empty 3 12 0 14 -204280 -1 0; #X text 6 1 original text; #X restore 437 280 pd original text; #X obj 0 412 cnv 3 550 3 empty empty more_info 8 12 0 13 -228856 -1 0; #X text 93 422 prob generates each time interval a 0 or 1 When the value is 1 a bang is send to the outlet. The ratio between 0 and 1 is controlled by the probability value; #X text 8 23 random event generator, f 78; #X text 160 353 - random generated; #X connect 13 0 20 0; #X connect 14 0 20 0; #X connect 15 0 20 1; #X connect 16 0 20 2; #X connect 17 0 20 0; #X connect 18 0 15 0; #X connect 19 0 16 0; #X connect 20 0 12 0; pd-mjlib-0.2.0/help/synapseA~-help.pd000066400000000000000000000053511434460023200173750ustar00rootroot00000000000000#N canvas 550 79 559 457 10; #X obj 0 0 cnv 15 552 40 empty empty synapseA~ 3 12 0 18 -204280 -1 0; #X obj 0 311 cnv 3 550 3 empty empty outlets 8 12 0 13 -228856 -1 0 ; #X obj 0 397 cnv 3 550 3 empty empty arguments 8 12 0 13 -228856 -1 0; #X obj 79 320 cnv 17 3 25 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 0 471 cnv 15 552 21 empty empty empty 20 12 0 14 -233017 -33289 0; #N canvas 238 349 428 75 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 206 473 pd Related_objects; #N canvas 756 193 494 344 META 0; #X text 12 169 HELP_PATCH_AUTHORS "pd meta" information added by Jonathan Wilkes for Pd version 0.42.; #X text 12 25 LICENSE GPL v2; #X text 12 149 AUTHOR Mark Williamson ; #X text 12 45 DESCRIPTION designed to generate a random event with a given probability at a given interval; #X text 12 130 OUTLET_0 bang; #X text 12 5 KEYWORDS control random event generator; #X text 12 75 INLET_0 bang start stop; #X text 12 94 INLET_1 float; #X text 11 112 INLET_2 float; #X restore 503 473 pd META; #X obj 0 428 cnv 3 550 3 empty empty more_info 8 12 0 13 -228856 -1 0; #X obj 0 397 cnv 3 550 3 empty empty arguments 8 12 0 13 -228856 -1 0; #X text 93 407 timer interval and probability; #X obj 178 143 mjlib/synapseA~; #X obj 265 210 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 178 210 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X floatatom 265 80 5 0 0 0 - - -, f 5; #X obj 221 210 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 179 60 phasor~ 1; #X obj 268 60 hsl 64 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144 -1 -1 5900 1; #X obj 485 4 synapseA~; #X text 8 23 block based averager and comparator, f 78; #X obj 0 242 cnv 3 550 3 empty empty inlets 8 12 0 13 -228856 -1 0 ; #X obj 79 256 cnv 17 3 17 empty empty 0 5 9 0 16 -228856 -162280 0 ; #X obj 79 281 cnv 17 3 17 empty empty 1 5 9 0 16 -228856 -162280 0 ; #X text 107 256 signal; #X text 162 256 - sample source; #X text 107 281 float; #X text 162 281 - threshold level; #X text 107 320 float; #X text 160 320 - 0 or 1 depending on block average value compared to threshold; #X obj 79 351 cnv 17 3 17 empty empty 1 5 9 0 16 -228856 -162280 0 ; #X text 107 351 bang; #X text 160 351 - bangs when block average is lower than threshold ; #X obj 79 375 cnv 17 3 17 empty empty 2 5 9 0 16 -228856 -162280 0 ; #X text 107 375 bang; #X text 161 374 - bangs when block average is average than threshold ; #X text 94 438 do an average on the block and see if it is bigger than our threshold then check for state change and output accordingly; #X connect 10 0 12 0; #X connect 10 1 14 0; #X connect 10 2 11 0; #X connect 13 0 10 1; #X connect 15 0 10 0; #X connect 16 0 13 0; pd-mjlib-0.2.0/mjlib-meta.pd000066400000000000000000000004451434460023200155560ustar00rootroot00000000000000#N canvas 37 58 340 230 10; #X text 10 10 META this is the meta file for mjlib; #X text 10 30 NAME mjlib; #X text 10 50 AUTHOR mark williamson ; #X text 10 70 MAINTAINER Fred Jan Kraan ; #X text 10 90 LICENSE GNU GPL; #X text 10 110 VERSION 0.2.0; pd-mjlib-0.2.0/objects.txt000066400000000000000000000005451434460023200154030ustar00rootroot00000000000000about random generator based on anchor value and percentual deviation metroplus multi-interval metro monorhythm multi-interval multi-output rhythm generator morse convert text to Morse Code n2m note list to midi pin~ random based signal router prob random event generator synapseA~ block based averager and comparator pd-mjlib-0.2.0/pd-lib-builder/000077500000000000000000000000001434460023200160005ustar00rootroot00000000000000pd-mjlib-0.2.0/pd-lib-builder/Makefile.pdlibbuilder000066400000000000000000001266041434460023200221110ustar00rootroot00000000000000# 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-mjlib-0.2.0/src/000077500000000000000000000000001434460023200137745ustar00rootroot00000000000000pd-mjlib-0.2.0/src/StdAfx.h000066400000000000000000000014421434460023200153370ustar00rootroot00000000000000// stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently // #if !defined(AFX_STDAFX_H__FDC19764_88C2_4FB7_A4EB_729E948776D0__INCLUDED_) #define AFX_STDAFX_H__FDC19764_88C2_4FB7_A4EB_729E948776D0__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // Insert your headers here #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include // TODO: reference additional headers your program requires here //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_STDAFX_H__FDC19764_88C2_4FB7_A4EB_729E948776D0__INCLUDED_) pd-mjlib-0.2.0/src/about.c000066400000000000000000000032711434460023200152550ustar00rootroot00000000000000#ifdef NT #include #endif #include "m_pd.h" #include #include #include "about.h" /** * The about object is designed to output a number that is * "about" the same as its input. A percentage error factor * gives the deviation. */ static t_class *about_class; /** * a float causes a number that is within x_err range * of the input number */ static void about_float(t_about *x , t_float f) { float errp = (( (float) rand() / (float) RAND_MAX) * ( x->x_err * 2)); float tenp = ((errp - x->x_err)/100) * f; //float ep = (errp/100) * f; //float correction = ep - tenp; //float outf = f + correction; float outf = f + tenp; outlet_float( x->x_obj.ob_outlet , outf ); } /* * make a new about it takes one parameter - the percentage error */ static void *about_new( t_float f ) { t_about *x = (t_about *)pd_new(about_class); about_set_err( x , f ); // make us some ins and outs outlet_new(&x->x_obj, gensym("float")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("error")); return (x); } static void about_free(t_about *x) { // nothing doing here for now } /** * set the error factor */ static void about_set_err( t_about *x, t_float f ) { x->x_err = f; } /** * make a new one and setup all of our messages */ void about_setup(void) { srand( (unsigned) time( NULL ) ); about_class = class_new(gensym("about"), (t_newmethod)about_new, (t_method)about_free, sizeof(t_about), 0, A_DEFFLOAT , 0); class_addfloat( about_class, about_float ); class_addmethod(about_class, (t_method)about_set_err, gensym("error" ), A_FLOAT, 0); } pd-mjlib-0.2.0/src/about.h000066400000000000000000000004111434460023200152530ustar00rootroot00000000000000 typedef struct _about { t_object x_obj; t_float x_err; } t_about; static void *about_new( t_float t ); static void about_set_err( t_about *x, t_float f ); static void about_float( t_about *x, t_float f ); static void about_free(t_about *x); pd-mjlib-0.2.0/src/metroplus.c000066400000000000000000000102221434460023200161670ustar00rootroot00000000000000#ifdef NT #include #endif #include "m_pd.h" #include #include #include "metroplus.h" /** * The metroplus object is a more complex version of the metro * object - it allows a list of time intervals to be given which are * sequentially used thus giving a more compelex timing source * than the metro object * * the code is based on the metro code from the pd source code */ static t_class *metroplus_class; static t_class *metroplus_2_class; /** * clock tick - do a bang and wait the next * time delay in the list */ static void metroplus_tick(t_metroplus *x) { x->x_hit = 0; outlet_bang(x->x_obj.ob_outlet); if (!x->x_hit) clock_delay(x->x_clock, metroplus_getNextDelay(x) ); } /** * switch the metroplus object on or off */ static void metroplus_float(t_metroplus *x, t_float f) { if (f != 0) metroplus_tick(x); else clock_unset(x->x_clock); x->x_hit = 1; } /** * a bang turns us on - a start message also calls this function */ static void metroplus_bang(t_metroplus *x) { metroplus_float(x, 1); } /** * a stop message turns us off */ static void metroplus_stop(t_metroplus *x) { metroplus_float(x, 0); } /** * free our clock and our timer array */ static void metroplus_free(t_metroplus *x) { clock_free(x->x_clock); free( x->x_times ); pd_free( &( (t_metroplus*)x->x_shadow)->x_obj.ob_pd ); } /** * get the next delay time in the list - wrap * if we have run over the end */ static float metroplus_getNextDelay( t_metroplus *x ) { if ( x->x_idx == x->x_size ) { x->x_idx = 0; } return x->x_times[ x->x_idx++ ]; } /* * make a new metroplus - we can provide a list of times * so read these in too */ static void *metroplus_new(t_symbol *s, int argc, t_atom *argv) { int i; t_metroplus *x = (t_metroplus *)pd_new(metroplus_class); t_metroplus *x1 = (t_metroplus *)pd_new(metroplus_2_class); x->x_shadow=x1; x1->x_shadow=x; x->x_times = NULL; // a silly little kludge - out time_seq method assumes it is accessed from x1 // so we have to pass a pointer to this so it can dereference it metroplus_time_seq( x->x_shadow , s , argc , argv ); x->x_clock = clock_new(x, (t_method)metroplus_tick); outlet_new(&x->x_obj, gensym("bang")); inlet_new( &x->x_obj , &x1->x_obj.ob_pd,0,0); //inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("list"), gensym("tseq")); return (x); } /** * set a time sequence and free the old array */ static void metroplus_time_seq( t_metroplus *x1, t_symbol *s, int ac, t_atom *av ) { int i; t_metroplus *x = x1->x_shadow; if ( x->x_times != NULL ) { free( x->x_times ); } if ( ac > 0 ) { x->x_times = (float *) malloc( ac * sizeof( float )); for( i = 0 ; i < ac ; i++ ) { float t = atom_getfloat( &av[i] ); x->x_times[i] = t > 0 ? t : 10; } x->x_size=ac; } else { x->x_times = (float *) malloc( sizeof( float )); x->x_times[0] = 10; x->x_size=1; } x->x_idx = 0; x->x_hit = 0; } static void metroplus_time_float( t_metroplus *x1, t_float f ) { int i; t_metroplus *x = x1->x_shadow; post("here with %f" , f ); if ( x->x_times != NULL ) { free( x->x_times ); } x->x_times = (float *) malloc( sizeof( float )); x->x_times[0] = f > 0 ? f : 10; x->x_size=1; x->x_idx = 0; x->x_hit = 0; } /** * make a new one and setup all of our messages */ void metroplus_setup(void) { metroplus_class = class_new(gensym("metroplus"), (t_newmethod)metroplus_new, (t_method)metroplus_free, sizeof(t_metroplus), 0, A_GIMME, 0); metroplus_2_class = class_new(gensym("metroplus (second inlet)"), 0, 0, sizeof(t_metroplus), CLASS_PD | CLASS_NOINLET, 0); class_addbang(metroplus_class, metroplus_bang); class_addmethod(metroplus_class, (t_method)metroplus_stop, gensym("stop"), 0); class_addmethod(metroplus_class, (t_method)metroplus_bang, gensym("start"), 0); class_addmethod(metroplus_2_class, (t_method)metroplus_time_seq, gensym("list"),A_GIMME,0); class_addmethod(metroplus_2_class, (t_method)metroplus_time_float ,gensym("float"),A_FLOAT,0); } pd-mjlib-0.2.0/src/metroplus.h000066400000000000000000000013501434460023200161760ustar00rootroot00000000000000 typedef struct _metroplus { t_object x_obj; t_clock *x_clock; t_float *x_times ; int x_idx; int x_size; int x_hit; void* x_shadow; } t_metroplus; static void metroplus_tick(t_metroplus *x); static void metroplus_float(t_metroplus *x, t_float f); static void metroplus_bang(t_metroplus *x); static void metroplus_stop(t_metroplus *x); static void metroplus_ft1(t_metroplus *x, t_floatarg g); static void metroplus_free(t_metroplus *x); static void *metroplus_new(t_symbol *s, int argc, t_atom *argv); static float metroplus_getNextDelay( t_metroplus *x ); static void metroplus_time_seq( t_metroplus *x, t_symbol *s, int ac, t_atom *av ); static void metoplus_time_float( t_metroplus *x, t_float f ); pd-mjlib-0.2.0/src/mjLib.c000066400000000000000000000014641434460023200152020ustar00rootroot00000000000000#include "mjLib.h" #include "m_pd.h" #include "things.h" typedef struct _mjLib { t_object x_obj; } t_mjLib; static t_class* mjLib_class; static void* mjLib_new(t_symbol* s) { t_mjLib *x = (t_mjLib *)pd_new( mjLib_class); return (x); } void mjLib_setup(void) { mjLib_class = class_new(gensym("mjLib"), (t_newmethod)mjLib_new, 0, sizeof(t_mjLib), 0, (t_atomtype)0); pin_tilde_setup(); metroplus_setup(); monorhythm_setup(); prob_setup(); about_setup(); synapseA_tilde_setup(); n2m_setup(); morse_setup(); post("mjLib by mark williamson"); post("Contact: mark@junklight.com"); post("website: http://www.junklight.com"); post("mjLib: version: 0.1 "); post("mjLib: compiled: "__DATE__); post(""); } pd-mjlib-0.2.0/src/mjLib.h000066400000000000000000000016041434460023200152030ustar00rootroot00000000000000#ifdef NT // The following ifdef block is the standard way of creating macros which make exporting // from a DLL simpler. All files within this DLL are compiled with the MJLIB_EXPORTS // symbol defined on the command line. this symbol should not be defined on any project // that uses this DLL. This way any other project whose source files include this file see // MJLIB_API functions as being imported from a DLL, wheras this DLL sees symbols // defined with this macro as being exported. #ifdef MJLIB_EXPORTS #define MJLIB_API __declspec(dllexport) #else #define MJLIB_API __declspec(dllimport) #endif // This class is exported from the mjLib.dll //class MJLIB_API CMjLib { //public: // CMjLib(void); // TODO: add your methods here. //}; //extern MJLIB_API int nMjLib; //MJLIB_API int fnMjLib(void); __declspec(dllexport) void mjLib_setup( void ); #endif pd-mjlib-0.2.0/src/monorhythm.c000066400000000000000000000123031434460023200163430ustar00rootroot00000000000000#ifdef NT #include #endif #include "m_pd.h" #include #include #include "monorhythm.h" /** * The monorhythm object is designed to help build polyrhythms. Given * a time interval and a pattern it produces the pattern within the time * interval given. Thus if two where set going with the same time interval * the two patterns (assuming they where different) would play against * each other. * * this filename is spelt wrong 'cos I can't spell */ static t_class *monorhythm_class; /** * clock tick - do a bang and wait the next * time delay in the list */ static void monorhythm_tick(t_monorhythm *x) { if ( x->t_running ) { monorhythm_do_beat( x ); clock_delay(x->x_clock, x->x_beattime ); } } static void monorhythm_do_beat( t_monorhythm* x ) { float beat; if ( x->x_idx == x->x_size ) { x->x_idx = 0; } if ( x->x_idx == 0) { outlet_bang( x->x_sync ); } beat = x->x_pattern[ x->x_idx++ ]; if ( beat > 1 ) { if ( x->t_exclusive == 0 ) { outlet_bang( x->x_bang ); } outlet_bang( x->x_accent ); } else if ( beat == 1 ) { outlet_bang( x->x_bang ); } } /** * a bang causes a reset to the start of the bar - used to * synchronize multiple monorhythm's. If the rhythm is not * running it is started */ static void monorhythm_bang(t_monorhythm *x) { if ( x->x_beattime > 0 ) { monorhythm_restart( x ); } } /** * reset the rhythm to start at the beginning */ static void monorhythm_restart(t_monorhythm *x) { if ( x->x_beattime > 0 ) { x->t_running = 1; x->x_idx = 0; monorhythm_do_beat( x ); clock_delay(x->x_clock, x->x_beattime ); } } /** * a stop message turns us off */ static void monorhythm_stop(t_monorhythm *x) { x->t_running = 0; } /** * set exclusive mode */ static void monorhythm_set_exclusive(t_monorhythm *x) { x->t_exclusive = 1; } /** * set nonexclusive mode */ static void monorhythm_set_nonexclusive(t_monorhythm *x) { x->t_exclusive = 0; } /** * free our clock and our timer array */ static void monorhythm_free(t_monorhythm *x) { clock_free(x->x_clock); free( x->x_pattern ); } /* * make a new monorhythm - we can provide a list of times * so read these in too */ static void *monorhythm_new(t_symbol *s, int argc, t_atom *argv) { float f; t_monorhythm *x = (t_monorhythm *)pd_new(monorhythm_class); x->x_pattern = NULL; // parse any settings if ( argc > 0 ) { f = atom_getfloat( &argv[0] ); monorhythm_set_time( x , f ); monorhythm_pattern_seq( x, s , argc - 1 , argv + 1 ); } x->t_running=0; x->t_exclusive = 0; // make us some ins and outs x->x_clock = clock_new(x, (t_method)monorhythm_tick); x->x_bang = outlet_new(&x->x_obj, gensym("bang")); x->x_accent = outlet_new(&x->x_obj, gensym("accent")); x->x_sync = outlet_new(&x->x_obj, gensym("sync")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("list"), gensym("pattern")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("timeinterval")); return (x); } /** * set a time sequence and free the old array */ static void monorhythm_pattern_seq( t_monorhythm *x, t_symbol *s, int ac, t_atom *av ) { int i; if ( x->x_pattern != NULL ) { free( x->x_pattern ); } if ( ac > 0 ) { x->x_pattern = (float *) malloc( ac * sizeof( float )); for( i = 0 ; i < ac ; i++ ) { float t = atom_getfloat( &av[i] ); x->x_pattern[i] = t; } x->x_size=ac; monorhythm_calculate_beat_interval( x ); } else { // if there is no pattern it doens't do anything x->x_pattern = NULL; x->x_size=0; x->t_running = 0; } x->x_idx = 0; } /** * the time interval is divided by the number of beats that are * going to happen in order to get the beat time. If this would * be invallid for any reason it is set to 0 and the rhythm is stopped */ static void monorhythm_calculate_beat_interval( t_monorhythm *x ) { if ( ( x->x_size > 0 ) && ( x->x_time > 0 )) { x->x_beattime = x->x_time / x->x_size; } else { x->x_beattime = 0; x->t_running = 0; } } /** * set the time - recalculate the beat time */ static void monorhythm_set_time( t_monorhythm *x, t_float f ) { x->x_time = f; monorhythm_calculate_beat_interval( x ); } /** * make a new one and setup all of our messages */ void monorhythm_setup(void) { monorhythm_class = class_new(gensym("monorhythm"), (t_newmethod)monorhythm_new, (t_method)monorhythm_free, sizeof(t_monorhythm), 0, A_GIMME, 0); class_addbang(monorhythm_class, monorhythm_bang); class_addmethod(monorhythm_class, (t_method)monorhythm_stop, gensym("stop"), 0); class_addmethod(monorhythm_class, (t_method)monorhythm_bang, gensym("start"), 0); class_addmethod(monorhythm_class, (t_method)monorhythm_pattern_seq, gensym("pattern" ), A_GIMME, 0); class_addmethod(monorhythm_class, (t_method)monorhythm_set_time, gensym("timeinterval" ), A_FLOAT, 0); class_addmethod(monorhythm_class, (t_method)monorhythm_set_exclusive,gensym("exclusive"),0); class_addmethod(monorhythm_class, (t_method)monorhythm_set_nonexclusive,gensym("nonexclusive"),0); } pd-mjlib-0.2.0/src/monorhythm.h000066400000000000000000000020321434460023200163460ustar00rootroot00000000000000 typedef struct _monorhythm { t_object x_obj; t_clock *x_clock; t_float *x_pattern; int x_idx; int x_size; t_float x_time; t_float x_beattime; int t_running; int t_exclusive; t_outlet *x_bang; t_outlet *x_sync; t_outlet *x_accent; } t_monorhythm; static void monorhythm_tick(t_monorhythm *x); static void monorhythm_start(t_monorhythm *x); static void monorhythm_stop(t_monorhythm *x); static void monorhythm_free(t_monorhythm *x); static void *monorhythm_new(t_symbol *s, int argc, t_atom *argv); static void monorhythm_pattern_seq( t_monorhythm *x, t_symbol *s, int ac, t_atom *av ); static void monorhythm_time_float( t_monorhythm *x1, t_float f ); static void monorhythm_calculate_beat_interval( t_monorhythm *x ); static void monorhythm_set_time( t_monorhythm *x, t_float f ); static void monorhythm_restart(t_monorhythm *x); static void monorhythm_do_beat( t_monorhythm* x ); static void monorhythm_set_exclusive(t_monorhythm *x); static void monorhythm_set_nonexclusive(t_monorhythm *x); pd-mjlib-0.2.0/src/morse.c000066400000000000000000000167421434460023200152770ustar00rootroot00000000000000#ifdef NT #include #endif #include "m_pd.h" #include #include #include #include "morse.h" #define VERSION "0.1.3" /** * The morse object is designed to translate messages into * morse code. There are two outlets - a dot outlet and a dash * outlet (from left to right). In addition there is an end of * current message outlet. Each character in the current message * is emited upon reciept of a bang allowing external control over the * timing. A dot lasts one bang - a dash lasts three bangs, the space * between dots and dashes is one bang, the space between characters is * three bangs, the space between words is seven bangs * it currently only does digits and numbers */ static t_class *morse_class; char* morseletter[] = { ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", }; char * morsedigit[] = { "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", }; char* wordspace = "X"; /** * a bang causes a reset to the start of the bar - used to * synchronize multiple morse's. If the rhythm is not * running it is started */ static void morse_bang(t_morse *x) { if( x->x_spaceticks > 0 ) { //post("Tick"); x->x_spaceticks--; } else { if ( x->x_curmsg != NULL) { if ( x->x_curmsg->idx != x->x_curmsg->length ) { if( x->x_curmsg->msg == wordspace ) { //post("Doing wordspace"); x->x_spaceticks =6; x->x_curmsg->idx = 0; x->x_curmsg = x->x_curmsg->next; } else { //post("Doing %c" , x->x_curmsg->msg[ x->x_curmsg->idx++ ]); if( x->x_curmsg->msg[ x->x_curmsg->idx ] == '.') { outlet_bang( x->x_dot ); x->x_spaceticks = 1; } else { outlet_bang( x->x_dash ); x->x_spaceticks = 3; } x->x_curmsg->idx++ ; } } else { if( x->x_curmsg->next != NULL ) { if( x->x_curmsg->next->msg != wordspace ) { //post( "Doing space" ); x->x_spaceticks =2; } else if ( x->x_curmsg->next->next == NULL ) { //post("message end"); outlet_bang( x->x_end ); x->x_curmsg->idx = 0; x->x_spaceticks = 0; x->x_curmsg = x->x_curmsg->next; } } x->x_curmsg->idx = 0; x->x_curmsg = x->x_curmsg->next; } } } } static void morse_rewind( t_morse *x) { x->x_spaceticks = 0; if (x->x_msg) { // prevents crash on [rewind( before [msg( x->x_curmsg = x->x_msg; x->x_curmsg->idx = 0; } } /** * free our clock and our timer array */ static void morse_free(t_morse *x) { outlet_free( x->x_dot ); outlet_free( x->x_dash ); outlet_free( x->x_end ); if( x->x_msg != NULL ) { morse_freemsg( x->x_msg ); } } static void morse_freemsg( morse_msglet* msg) { if ( msg->next != NULL ) { morse_freemsg( msg->next ); } freebytes( (void*) msg , sizeof( morse_msglet) ); } /* * make a new morse - we can provide a list of times * so read these in too */ static void *morse_new(t_symbol *s, int argc, t_atom *argv) { t_morse *x = (t_morse *)pd_new(morse_class); x->x_msg = NULL; // parse any settings if ( argc > 0 ) { morse_message( x, s , argc , argv ); } // make us some ins and outs x->x_dot = outlet_new(&x->x_obj, gensym("dot")); x->x_dash = outlet_new(&x->x_obj, gensym("dash")); x->x_end = outlet_new(&x->x_obj, gensym("end")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("list"), gensym("msg")); return (x); } /** * set a message and free the old array */ static void morse_message( t_morse *x, t_symbol *s, int ac, t_atom *av ) { int i,j,l; if ( x->x_msg != NULL ) { morse_freemsg( x->x_msg ); x->x_msg = NULL; x->x_curmsg = NULL; x->x_spaceticks =0; } if ( ac > 0 ) { char buf[256]; for( i = 0 ; i < ac ; i++ ) { atom_string( &av[i] , buf, 255 ); l = strlen( buf ); #ifdef NT /* this is not part of ANSI or ISO standard C, only Microsoft and Borland use it. */ strlwr( buf ); #else /* Probably needs a loop using tolower(char c) from ctype.h * This way it'll just be case sensitive */ #endif for( j = 0 ; j < l ; j++ ) { morse_add_msg_part( x , morse_lookup( buf[j] )); } morse_add_msg_part( x , wordspace ); } x->x_curmsg = x->x_msg; x->x_spaceticks =0; } else { // if there is no pattern it doens't do anything x->x_msg = NULL; x->x_curmsg = NULL; x->x_spaceticks =0; } } /** * add a non null msg part onto the end of the message list - if its null * the lookup failed and we just ignore it */ static void morse_add_msg_part( t_morse *x , char *msgpart ) { morse_msglet* idx; morse_msglet* nmsg; if ( msgpart != NULL ) { idx = x->x_msg; if ( idx == NULL ) { nmsg = idx = (morse_msglet*) getbytes( sizeof( morse_msglet) ); x->x_msg = nmsg; } else { while( idx->next != NULL ) { idx = idx->next; } idx->next = nmsg = (morse_msglet*) getbytes( sizeof( morse_msglet) ); } nmsg->next = NULL; nmsg->idx = 0; if( msgpart == wordspace ) { nmsg->length = -1; } else { nmsg->length = strlen( msgpart ); } nmsg->msg = msgpart; } } /** * morse lookup returns a pointer to a character representation of the morse * code for a given character. If the character is not recognized then NULL * is returned. DO NOT TRY TO FREE THE RETURNED POINTER - its part * of the array above */ static char *morse_lookup( char c ) { if( ( c>= 'a') && ( c<='z')) { return ( morseletter[ c - 'a'] ); } else if( ( c>= '0') && ( c<='9')) { return ( morsedigit[ c - '0'] ); } return NULL; } static void morse_status( t_morse *x) { post("--==## mjlib/prob %s ##==--", VERSION); if (x->x_curmsg) { post("x_curmsg->msg: %s", x->x_curmsg->msg); post("x_curmsg->idx: %d", x->x_curmsg->idx); post("x_curmsg->length: %d", x->x_curmsg->length); post("x_curmsg->next: %s", (x->x_curmsg->next) ? "true" : "false"); } else { post("x_msg->x_curmsg:"); } int i = 0; morse_msglet* msg = x->x_msg; while( msg != NULL ) { post("%d: msg->msg: %s", i, msg->msg); post("%d: msg->idx: %d", i, msg->idx); post("%d: msg->length: %d", i, msg->length); post("%d: msg->next: %s", i, (msg->next) ? "true" : "false"); msg = msg->next; i++; } post("x_spaceticks: %f", x->x_spaceticks); } /** * make a new one and setup all of our messages */ void morse_setup(void) { morse_class = class_new(gensym("morse"), (t_newmethod)morse_new, (t_method)morse_free, sizeof(t_morse), 0, A_GIMME, 0); class_addbang(morse_class, morse_bang); class_addmethod(morse_class, (t_method)morse_message, gensym("msg" ), A_GIMME, 0); //class_addmethod(morse_class, (t_method)morse_set_time, gensym("timeinterval" ), A_FLOAT, 0); class_addmethod(morse_class, (t_method)morse_rewind, gensym("rewind"),0); //class_addmethod(morse_class, (t_method)morse_set_nonexclusive,gensym("nonexclusive"),0); class_addmethod(morse_class, (t_method)morse_status, gensym("status" ), 0); } pd-mjlib-0.2.0/src/morse.h000066400000000000000000000012061434460023200152710ustar00rootroot00000000000000 typedef struct _msglet { char* msg; int idx; int length; struct _msglet *next; } morse_msglet; typedef struct _morse { t_object x_obj; morse_msglet *x_msg; morse_msglet *x_curmsg; int x_spaceticks; t_outlet *x_dot; t_outlet *x_dash; t_outlet *x_end; } t_morse; static void morse_add_msg_part( t_morse *x , char *msgpart ); static char *morse_lookup( char c ); static void morse_freemsg( morse_msglet* msg); static void morse_free(t_morse *x); static void *morse_new(t_symbol *s, int argc, t_atom *argv); static void morse_message( t_morse *x, t_symbol *s, int ac, t_atom *av ); pd-mjlib-0.2.0/src/n2m.c000066400000000000000000000055611434460023200146430ustar00rootroot00000000000000#ifdef _WIN32 #include #endif #include "m_pd.h" #include #include #include #include #include "n2m.h" char* notes_up[12] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; int octaveoffset[11] = { 0 , 12, 24 ,36, 48, 60, 72, 84, 96, 108 ,120 }; /** * The n2m object is designed to output a midi note number * in response to a note name of the form * for example C5 or D#3. */ static t_class *n2m_class; /* * make a new n2m it takes one parameter - the percentage error */ static void *n2m_new( t_float f ) { t_n2m *x = (t_n2m *)pd_new(n2m_class); // make us an output for the note number outlet_new(&x->x_obj, gensym("float")); return (x); } static void n2m_free(t_n2m *x) { // nothing doing here for now } /** * set the error factor */ static void n2m_notename( t_n2m *x, t_symbol *s, int ac, t_atom *av ) { char buf[255]; char note[255]; int octave; int i; for( i = 0 ; i < ac ; i++ ) { atom_string( &av[i] , buf, 255 ); //post("Symbol [%s]", buf ); splitsym( buf , note , &octave ); //post( "Which is %s note and %u octave and midi value %d" , note , octave , midilookup( note , octave ) ); outlet_float( x->x_obj.ob_outlet , midilookup( note , octave ) ); } } /** * make a new one and setup all of our messages */ void n2m_setup(void) { n2m_class = class_new(gensym("n2m"), (t_newmethod)n2m_new, (t_method)n2m_free, sizeof(t_n2m), 0, 0); class_addmethod(n2m_class, (t_method)n2m_notename, gensym("note" ), A_GIMME, 0); } /** * splitsym takes a note symbol and splits it into note and octave * if note not specified it defaults to C and if octave not specified * it defaults to 4 */ static void splitsym( char* buf , char* note, int* octave ) { int i,j; int split = -1; for( i = 0 ; buf[i] != 0 ; i++ ) { if ( ( buf[i] >= '0' ) && ( buf[i] <= '9')) { split = i; if ( i > 0 ) { for( j=0; j < i;j++) { note[j] = buf[j]; } note[i] = 0; } else { note[0] = 'C'; note[1] = 0; } sscanf( buf + i , "%u" , octave ); break; } } if ( split == -1 ) { i = 0; while( buf[i] != 0 ) { note[i] = buf[i]; i++; } note[i] = 0; *octave = 4; } } /** * return a midi note value for a given note name and octave */ static int midilookup( char* note , int octave ) { int i,j; int nnum = 4; for( i = 0 ; i < 12 ; i++ ) { #ifdef NT /* stricmp() is not an ANSI or ISO standard C function */ if ( stricmp( note , notes_up[i]) == 0) { nnum = i; break; } #else /* replacing with a ANSI function, but it'll now be case sensitive */ if ( strcmp( note , notes_up[i]) == 0) { nnum = i; break; } #endif } return octaveoffset[octave + 1 ] + nnum; } pd-mjlib-0.2.0/src/n2m.h000066400000000000000000000005521434460023200146430ustar00rootroot00000000000000 typedef struct _n2m { t_object x_obj; t_float x_err; } t_n2m; static void *n2m_new( t_float t ); static void n2m_set_err( t_n2m *x, t_float f ); static void n2m_float( t_n2m *x, t_float f ); static void n2m_free(t_n2m *x); static void splitsym( char* buf , char* note, int* octave ); static int midilookup( char* note , int octave ); pd-mjlib-0.2.0/src/pin~.c000066400000000000000000000110201434460023200151160ustar00rootroot00000000000000#include "m_pd.h" #ifdef NT #include #endif #include #include #include "pin~.h" /* ------------------------ pin_tilde~ ----------------------------- */ static t_class *pin_tilde_class; /** * the perform routine unpacks its parameters * looks to see if time is zero (do channel prob * everytime) if it is to chooses a channel. * the routine then copies everything in the input * to the choosen output */ t_int *pin_tilde_perform(t_int *w) { float *in = (float *)(w[1]); float *outl = (float *)(w[2]); float *outr = (float *)(w[3]); t_pin_tilde*obj = (t_pin_tilde *)(w[4]); int n = (t_int)(w[5]); int i = 0; if ( obj->p_ticktime <= 0 ) { if ( rand() < obj->p_normalized_prob ) { obj->p_outchannel=0; } else { obj->p_outchannel=1; } } if ( obj->p_outchannel == 0 ) { for( i = 0 ; i< n ; i++ ) { *outl++ = *in++; *outr++ = 0; } } else { for( i = 0 ; i< n ; i++ ) { *outr++ = *in++; *outl++ = 0; } } return w+6; } /** * set up our dsp perform routine - it takes parameters * the input channel, the output channels ( left and right), * the pin object and the number of samples in the array */ static void pin_tilde_dsp(t_pin_tilde *x, t_signal **sp) { dsp_add(pin_tilde_perform, 5,sp[0]->s_vec, sp[1]->s_vec , sp[2]->s_vec , x ,sp[0]->s_n); } /** * free up the tilde object - for now we only need * to get rid of the clock */ static void pin_tilde_free(t_pin_tilde *x) { clock_free( x->p_clock ); } /** * make a new object - set up out internal variables * and add our inlets and outlets */ static void *pin_tilde_new(t_floatarg prob , t_floatarg tick) { t_pin_tilde *x = (t_pin_tilde *)pd_new(pin_tilde_class); if ( prob < 0 ) { post("probability must be between 0 and 1 "); prob = 0; } else if( prob > 1 ) { post("probability must be between 0 and 1 "); prob = 1; } else if (prob == 0 ) { // note that prob defaullts to 0.5 prob = 0.5; } x->p_prob = prob; x->p_normalized_prob = prob * RAND_MAX; // set up our clocks x->p_ticktime = tick; x->p_clock = clock_new(x, (t_method) pin_tilde_tick); if (x->p_ticktime > 0) { clock_delay(x->p_clock, x->p_ticktime); } // start off with a random channel if ( rand() < x->p_normalized_prob ) { x->p_outchannel=0; } else { x->p_outchannel=1; } // set up our inlets inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("prob")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("tick")); outlet_new(&x->x_obj, gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); return (x); } /** * ticktime has been set - we only care about ticks above * zero. */ static void pin_tilde_ticktime( t_pin_tilde* x, t_float tick ) { x->p_ticktime = tick; if ( x->p_ticktime > 0 ) { clock_delay(x->p_clock, x->p_ticktime); } } /** * allows the probability to be set - note that although * we accept a probability between 0 and 1 we need to * normalize it becuase rand() produces a number between * 0 and rand_max. We precalucluate the normalized * number becuase we sometimes use it in the dsp routine * (if tick is zero). */ static void pin_tilde_prob( t_pin_tilde* x, t_float prob ) { if ( prob < 0 ) { post("probability must be between 0 and 1 "); prob = 0; } else if( prob > 1 ) { post("probability must be between 0 and 1 "); prob = 1; } x->p_prob=prob; x->p_normalized_prob = prob * RAND_MAX; } /** * clock tick - choose a channel and wait again */ static void pin_tilde_tick(t_pin_tilde *x) { if ( rand() < x->p_normalized_prob ) { x->p_outchannel=0; } else { x->p_outchannel=1; } if (x->p_ticktime > 0) { clock_delay(x->p_clock, x->p_ticktime); } } /** * setup - add our methods and seed the random number generator */ void pin_tilde_setup(void) { srand( (unsigned) time( NULL ) ); pin_tilde_class = class_new(gensym("pin~"), (t_newmethod) pin_tilde_new, (t_method) pin_tilde_free, sizeof(t_pin_tilde), 0, A_DEFFLOAT, A_DEFFLOAT, 0); CLASS_MAINSIGNALIN( pin_tilde_class, t_pin_tilde, x_f); class_addmethod(pin_tilde_class, (t_method) pin_tilde_dsp, gensym("dsp"), (t_atomtype)0); class_addmethod(pin_tilde_class, (t_method) pin_tilde_ticktime, gensym("tick") , A_DEFFLOAT , (t_atomtype)0 ); class_addmethod(pin_tilde_class, (t_method) pin_tilde_prob, gensym("prob") , A_DEFFLOAT , (t_atomtype)0 ); } pd-mjlib-0.2.0/src/pin~.h000066400000000000000000000012711434460023200151320ustar00rootroot00000000000000/* declarations for the pin~ object */ typedef struct _pin_tilde { t_object x_obj; float p_prob; float p_ticktime; int p_outchannel; t_clock* p_clock; long p_numticks; int p_normalized_prob; float x_f; } t_pin_tilde; t_int *pin_tilde_perform(t_int *w); static void pin_tilde_dsp(t_pin_tilde *x, t_signal **sp); static void pin_tilde_free(t_pin_tilde *x); static void *pin_tilde_new(t_floatarg prob , t_floatarg tick); static void pin_tilde_float(t_pin_tilde* x, t_float n); static void pin_tilde_ticktime( t_pin_tilde* x, t_float tick ); static void pin_tilde_prob( t_pin_tilde* x, t_float prob ); static void pin_tilde_tick(t_pin_tilde *x); pd-mjlib-0.2.0/src/prob.c000066400000000000000000000070601434460023200151050ustar00rootroot00000000000000#ifdef NT #include #endif #include "m_pd.h" #include #include #include "prob.h" #define VERSION "0.1.3" /** * The prob object is designed to generate random events * with a given probability - essentially every clock tick * it looks to see if it should generate an event or not */ static t_class *prob_class; /** * clock tick - do a bang and wait the next * time delay in the list */ static void prob_tick(t_prob *x) { if ( x->x_running ) { if ( prob_event( x) ) { outlet_bang(x->x_obj.ob_outlet); } clock_delay(x->x_clock, x->x_time ); } } /** * prob event looks to see if we should generate and event or not */ static int prob_event( t_prob* x ) { int ret = 0; if ( rand() < x->x_probability * RAND_MAX) { ret = 1; } return ret; } /** * a bang causes a reset to the start of the bar - used to * synchronize multiple prob's. If the rhythm is not * running it is started */ static void prob_bang(t_prob *x) { x->x_running = 1; clock_delay(x->x_clock, x->x_time ); } /** * a stop message turns us off */ static void prob_stop(t_prob *x) { x->x_running = 0; } /** * free our clock and our timer array */ static void prob_free(t_prob *x) { clock_free(x->x_clock); } /* * make a new prob - we can provide a list of times * so read these in too */ static void *prob_new(t_float _interval, t_float _probability) { t_prob *x = (t_prob *)pd_new(prob_class); t_float interval = (_interval <= 0) ? DEFAULT_INTERVAL : _interval; t_float probability = (_probability < 0 || _probability > 1) ? DEFAULT_PROBABILITY : _probability; prob_set_time(x, interval); prob_set_probability(x, probability); x->x_running = 0; // make us some ins and outs x->x_clock = clock_new(x, (t_method)prob_tick); outlet_new(&x->x_obj, gensym("bang")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("time")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("probability")); return (x); } /** * set the probability */ static void prob_set_probability( t_prob *x, t_float f ) { if ( f < 0 ) { post("probability must be between 0 and 1 "); f = 0; } else if( f > 1 ) { post("probability must be between 0 and 1 "); f = 1; } x->x_probability = f; } /** * set the time */ static void prob_set_time( t_prob *x, t_float _interval) { if (_interval > 0) { x->x_time = _interval; } else { post("timer interval must be larger than 0"); } } static void prob_set_status( t_prob *x) { post("--==## mjlib/prob %s ##==--", VERSION); post("x_time: %f", x->x_time); post("x_probability: %f", x->x_probability); post("x_running: %f", x->x_running); } /** * make a new one and setup all of our messages */ void prob_setup(void) { srand( (unsigned) time( NULL ) ); prob_class = class_new(gensym("prob"), (t_newmethod)prob_new, (t_method)prob_free, sizeof(t_prob), 0, A_DEFFLOAT , A_DEFFLOAT, 0); class_addbang(prob_class, prob_bang); class_addmethod(prob_class, (t_method)prob_stop, gensym("stop"), 0); class_addmethod(prob_class, (t_method)prob_bang, gensym("start"), 0); class_addmethod(prob_class, (t_method)prob_set_probability, gensym("probability" ), A_FLOAT, 0); class_addmethod(prob_class, (t_method)prob_set_time, gensym("time" ), A_FLOAT, 0); class_addmethod(prob_class, (t_method)prob_set_status, gensym("status" ), 0); } pd-mjlib-0.2.0/src/prob.h000066400000000000000000000010421434460023200151040ustar00rootroot00000000000000 typedef struct _prob { t_object x_obj; t_clock *x_clock; t_float x_time; t_float x_probability; t_float x_running; } t_prob; #define DEFAULT_PROBABILITY 0 #define DEFAULT_INTERVAL 100 static void prob_tick(t_prob *x); static void prob_bang(t_prob *x); static void prob_stop(t_prob *x); static void prob_free(t_prob *x); static void *prob_new( t_float , t_float); static void prob_set_time( t_prob *x, t_float f ); static void prob_set_probability( t_prob *x, t_float f ); static int prob_event(t_prob *x); pd-mjlib-0.2.0/src/synapseA~.c000066400000000000000000000054051434460023200161250ustar00rootroot00000000000000#include "m_pd.h" #ifdef NT #include #endif #include #include #include "synapseA~.h" /* ------------------------ synapseA_tilde~ ----------------------------- */ static t_class *synapseA_tilde_class; /** * do an average and see if it is bigger than our threshold * then check for state change and output accordingly */ t_int *synapseA_tilde_perform(t_int *w) { float *in = (float *)(w[1]); t_synapseA_tilde *x = (t_synapseA_tilde *)(w[2]); int n = (t_int)(w[3]); t_float buf = 0.; while (n--) { buf += *in++; } if ( buf*x->n_inv > x->x_threshold ) { if( !x->x_state ) { x->x_state = 1; outlet_float( x->x_obj.ob_outlet , x->x_state ); outlet_bang( x->x_onbang ); } } else { if( x->x_state ) { x->x_state = 0; outlet_float( x->x_obj.ob_outlet , x->x_state ); outlet_bang( x->x_offbang ); } } return (w+4); } /** * set up our dsp perform routine - it takes parameters * the input channel, the output channels ( left and right), * the pin object and the number of samples in the array */ static void synapseA_tilde_dsp(t_synapseA_tilde *x, t_signal **sp) { x->n_inv=1./sp[0]->s_n; dsp_add(synapseA_tilde_perform, 3,sp[0]->s_vec , x ,sp[0]->s_n); } /** * free up the tilde object - for now we only need * to get rid of the clock */ static void synapseA_tilde_free(t_synapseA_tilde *x) { } static void synapseA_tilde_threshold(t_synapseA_tilde *x, t_float f ) { if ( f > 0 ) { x->x_threshold = f; } else { post( "Threshold must be bigger than 0 - setting to 0"); x->x_threshold = 0; } } /** * make a new object - set up out internal variables * and add our inlets and outlets */ static void *synapseA_tilde_new(t_floatarg prob , t_floatarg tick) { // set up our inlets t_synapseA_tilde *x = (t_synapseA_tilde *)pd_new(synapseA_tilde_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("threshold")); outlet_new(&x->x_obj, gensym("float")); x->x_onbang = outlet_new(&x->x_obj, gensym("bang")); x->x_offbang = outlet_new(&x->x_obj, gensym("bang")); return (x); } /** * setup - add our methods and seed the random number generator */ void synapseA_tilde_setup(void) { synapseA_tilde_class = class_new(gensym("synapseA~"), (t_newmethod) synapseA_tilde_new, (t_method) synapseA_tilde_free, sizeof(t_synapseA_tilde), 0, A_DEFFLOAT, A_DEFFLOAT, 0); CLASS_MAINSIGNALIN( synapseA_tilde_class, t_synapseA_tilde, x_f); class_addmethod(synapseA_tilde_class, (t_method) synapseA_tilde_dsp, gensym("dsp"), (t_atomtype)0); class_addmethod(synapseA_tilde_class, (t_method) synapseA_tilde_threshold, gensym("threshold") , A_DEFFLOAT , (t_atomtype)0 ); } pd-mjlib-0.2.0/src/synapseA~.h000066400000000000000000000011711434460023200161260ustar00rootroot00000000000000/* declarations for the pin~ object */ typedef struct _synapseA_tilde { t_object x_obj; t_float x_f; t_float x_threshold; t_outlet *x_onbang; t_outlet *x_offbang; t_float n_inv; t_float x_state; } t_synapseA_tilde; t_int *synapseA_tilde_perform(t_int *w); static void synapseA_tilde_dsp(t_synapseA_tilde *x, t_signal **sp); static void synapseA_tilde_free(t_synapseA_tilde *x); static void *synapseA_tilde_new(t_floatarg prob , t_floatarg tick); static void synapseA_tilde_float(t_synapseA_tilde* x, t_float n); static void synapseA_tilde_threshold(t_synapseA_tilde *x, t_float f ); pd-mjlib-0.2.0/src/things.h000066400000000000000000000006261434460023200154450ustar00rootroot00000000000000 #if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) extern "C" { #endif void pin_tilde_setup(); void metroplus_setup(void); void monorhythm_setup(void); void prob_setup(void); void about_setup(void); void synapseA_tilde_setup(void); void convolve_tilde_setup(void); void n2m_setup(void); void morse_setup(void); #if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus) } #endifpd-mjlib-0.2.0/test/000077500000000000000000000000001434460023200141645ustar00rootroot00000000000000pd-mjlib-0.2.0/test/prob-test.pd000066400000000000000000000003311434460023200164250ustar00rootroot00000000000000#N canvas 211 438 450 300 10; #X msg 121 87 status; #X msg 175 87 -1; #X msg 208 87 2; #X msg 69 126 foo bar; #X obj 147 201 mjlib/prob; #X connect 0 0 4 0; #X connect 1 0 4 1; #X connect 2 0 4 2; #X connect 3 0 4 0;